• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Alan-Jowett / libbtf / 28060332906

31 Mar 2026 06:26PM UTC coverage: 92.773% (-2.3%) from 95.029%
28060332906

push

github

web-flow
Merge pull request #194 from Alan-Jowett/dependabot/github_actions/actions-f78bc712d6

Bump the actions group with 3 updates

2285 of 2463 relevant lines covered (92.77%)

768.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.84
/libbtf/btf_write.cpp
1
// Copyright (c) Prevail Verifier contributors.
2
// SPDX-License-Identifier: MIT
3

4
#include "btf_write.h"
5
#include "btf_c_type.h"
6

7
#include <cstring>
8

9
namespace libbtf {
10

11
static void write_btf(std::vector<std::byte> &btf, const auto &value) {
1,704✔
12
  size_t length = sizeof(value);
1,704✔
13
  size_t offset = btf.size();
1,704✔
14
  btf.resize(offset + length);
1,704✔
15
  memcpy(btf.data() + offset, &value, length);
1,704✔
16
}
1,704✔
17

18
class btf_string_table {
19
public:
20
  btf_string_table() { add(""); }
35✔
21
  ~btf_string_table() = default;
35✔
22

23
  uint32_t add(const std::optional<std::string> &str) {
1,422✔
24
    if (!str) {
1,422✔
25
      return 0;
20✔
26
    }
27

28
    auto it = offsets.find(*str);
1,402✔
29
    if (it != offsets.end()) {
1,402✔
30
      return it->second;
998✔
31
    }
32
    size_t offset = bytes.size();
404✔
33
    bytes.insert(
404✔
34
        bytes.end(), reinterpret_cast<const std::byte *>(str->data()),
404✔
35
        reinterpret_cast<const std::byte *>(str->data() + str->size()));
404✔
36
    bytes.push_back(std::byte{0});
404✔
37
    offsets[*str] = static_cast<uint32_t>(offset);
404✔
38
    return static_cast<uint32_t>(offset);
404✔
39
  }
40

41
  const std::vector<std::byte> &get_bytes() const { return bytes; }
35✔
42

43
private:
44
  std::vector<std::byte> bytes;
45
  std::map<std::string, uint32_t> offsets;
46
};
47

48
std::vector<std::byte> btf_write_types(const std::vector<btf_kind> &btf_kind) {
35✔
49
  std::vector<std::byte> btf;
35✔
50
  btf_string_table string_table;
35✔
51
  std::vector<std::byte> type_table_bytes;
35✔
52

53
  auto pack_btf_int_data = [](bool is_signed, bool is_char, bool is_bool,
57✔
54
                              size_t offset, size_t bits) {
55
    uint32_t value = 0;
57✔
56
    value |= is_signed ? BTF_INT_SIGNED : 0;
57✔
57
    value |= is_char ? BTF_INT_CHAR : 0;
57✔
58
    value |= is_bool ? BTF_INT_BOOL : 0;
57✔
59
    value = value << 24;
57✔
60
    value |= offset & UINT8_MAX << 16;
57✔
61
    value |= bits & UINT8_MAX;
57✔
62
    return value;
57✔
63
  };
64

65
  for (const auto &kind : btf_kind) {
459✔
66
    if (kind.index() == BTF_KIND_VOID) {
424✔
67
      continue;
35✔
68
    }
69
    // Write common BTF type header.
70
    std::visit(
389✔
71
        [&](const auto &value) {
389✔
72
          btf_type_t btf_type = {0};
389✔
73
          uint32_t vlen = 0;
389✔
74

75
          if constexpr (btf_kind_traits<decltype(value)>::has_optional_name ||
76
                        btf_kind_traits<decltype(value)>::has_name) {
77
            btf_type.name_off = string_table.add(value.name);
229✔
78
          }
79
          if constexpr (btf_kind_traits<decltype(value)>::has_return_type) {
80
            btf_type.type = value.return_type;
22✔
81
          }
82
          if constexpr (btf_kind_traits<decltype(value)>::has_type) {
83
            btf_type.type = value.type;
175✔
84
          }
85
          if constexpr (btf_kind_traits<decltype(value)>::has_members) {
86
            vlen = static_cast<uint32_t>(value.members.size());
90✔
87
          }
88
          if constexpr (btf_kind_traits<decltype(value)>::has_parameters) {
89
            vlen = static_cast<uint32_t>(value.parameters.size());
22✔
90
          }
91
          if constexpr (btf_kind_traits<decltype(value)>::has_size_in_bytes) {
92
            btf_type.size = value.size_in_bytes;
135✔
93
          }
94
          if constexpr (btf_kind_traits<decltype(value)>::has_linkage) {
95
            vlen = value.linkage;
37✔
96
          }
97

98
          btf_type.info = (static_cast<uint8_t>(kind.index()) << 24) |
389✔
99
                          static_cast<uint16_t>(vlen);
389✔
100
          write_btf(type_table_bytes, btf_type);
389✔
101
        },
389✔
102
        kind);
103

104
    // Write BTF type-specific data.
105
    switch (kind.index()) {
389✔
106
    case BTF_KIND_INT: {
57✔
107
      const auto &int_type = std::get<BTF_KIND_INT>(kind);
57✔
108
      write_btf(type_table_bytes,
57✔
109
                pack_btf_int_data(int_type.is_signed, int_type.is_char,
57✔
110
                                  int_type.is_bool,
57✔
111
                                  int_type.offset_from_start_in_bits,
57✔
112
                                  int_type.field_width_in_bits));
57✔
113
      break;
57✔
114
    }
115
    case BTF_KIND_ARRAY: {
34✔
116
      const auto &array_type = std::get<BTF_KIND_ARRAY>(kind);
34✔
117
      write_btf(type_table_bytes, btf_array_t{
×
118
                                      .type = array_type.element_type,
34✔
119
                                      .index_type = array_type.index_type,
34✔
120
                                      .nelems = array_type.count_of_elements,
34✔
121
                                  });
122
      break;
34✔
123
    }
124
    case BTF_KIND_STRUCT: {
73✔
125
      const auto &struct_type = std::get<BTF_KIND_STRUCT>(kind);
73✔
126
      for (const auto &member : struct_type.members) {
1,201✔
127
        write_btf(type_table_bytes,
1,128✔
128
                  btf_member_t{
1,128✔
129
                      .name_off = string_table.add(member.name),
1,128✔
130
                      .type = member.type,
1,128✔
131
                      .offset = member.offset_from_start_in_bits,
1,128✔
132
                  });
133
      }
134
      break;
73✔
135
    }
136
    case BTF_KIND_UNION: {
2✔
137
      const auto &union_type = std::get<BTF_KIND_UNION>(kind);
2✔
138
      for (const auto &member : union_type.members) {
4✔
139
        write_btf(type_table_bytes,
2✔
140
                  btf_member_t{
2✔
141
                      .name_off = string_table.add(member.name),
2✔
142
                      .type = member.type,
2✔
143
                      .offset = member.offset_from_start_in_bits,
2✔
144
                  });
145
      }
146
      break;
2✔
147
    }
148
    case BTF_KIND_ENUM: {
1✔
149
      const auto &enum_type = std::get<BTF_KIND_ENUM>(kind);
1✔
150
      for (const auto &member : enum_type.members) {
4✔
151
        write_btf(type_table_bytes,
3✔
152
                  btf_enum_t{
×
153
                      .name_off = string_table.add(member.name),
6✔
154
                      .val = member.value,
3✔
155
                  });
156
      }
157
      break;
1✔
158
    }
159
    case BTF_KIND_FUNCTION_PROTOTYPE: {
22✔
160
      const auto &func_proto_type = std::get<BTF_KIND_FUNCTION_PROTOTYPE>(kind);
22✔
161
      for (const auto &parameter : func_proto_type.parameters) {
44✔
162
        write_btf(type_table_bytes,
22✔
163
                  btf_param_t{
×
164
                      .name_off = string_table.add(parameter.name),
44✔
165
                      .type = parameter.type,
22✔
166
                  });
167
      }
168
      break;
22✔
169
    }
170
    case BTF_KIND_VAR: {
15✔
171
      const auto &var_type = std::get<BTF_KIND_VAR>(kind);
15✔
172
      write_btf(type_table_bytes, static_cast<uint32_t>(var_type.linkage));
15✔
173
      break;
15✔
174
    }
175
    case BTF_KIND_DATA_SECTION: {
13✔
176
      const auto &data_section_type = std::get<BTF_KIND_DATA_SECTION>(kind);
13✔
177
      for (const auto &member : data_section_type.members) {
28✔
178
        write_btf(type_table_bytes, btf_var_secinfo_t{
15✔
179
                                        .type = member.type,
15✔
180
                                        .offset = member.offset,
15✔
181
                                        .size = member.size,
15✔
182
                                    });
183
      }
184

185
      break;
13✔
186
    }
187
    case BTF_KIND_DECL_TAG: {
1✔
188
      const auto &decl_tag_type = std::get<BTF_KIND_DECL_TAG>(kind);
1✔
189
      write_btf(type_table_bytes,
1✔
190
                btf_decl_tag_t{.component_idx = decl_tag_type.component_index});
1✔
191
      break;
1✔
192
    }
193
    case BTF_KIND_ENUM64: {
1✔
194
      const auto &enum64_type = std::get<BTF_KIND_ENUM64>(kind);
1✔
195
      for (const auto &member : enum64_type.members) {
4✔
196
        btf_enum64_t enum_member = {0};
3✔
197
        enum_member.name_off = string_table.add(member.name);
3✔
198
        enum_member.val_lo32 = member.value & 0xFFFFFFFF;
3✔
199
        enum_member.val_hi32 = member.value >> 32;
3✔
200
        write_btf(type_table_bytes, enum_member);
3✔
201
      }
202
      break;
1✔
203
    }
204
    }
205
  }
206

207
  auto string_table_bytes = string_table.get_bytes();
35✔
208

209
  // Write the BTF header.
210
  write_btf(btf,
35✔
211
            btf_header_t{
35✔
212
                .magic = BTF_HEADER_MAGIC,
213
                .version = BTF_HEADER_VERSION,
214
                .flags = 0,
215
                .hdr_len = sizeof(btf_header_t),
216
                .type_off = 0,
217
                .type_len = static_cast<unsigned int>(type_table_bytes.size()),
35✔
218
                .str_off = static_cast<unsigned int>(type_table_bytes.size()),
35✔
219
                .str_len = static_cast<unsigned int>(string_table_bytes.size()),
35✔
220
            });
221

222
  btf.insert(btf.end(), type_table_bytes.begin(), type_table_bytes.end());
35✔
223
  btf.insert(btf.end(), string_table_bytes.begin(), string_table_bytes.end());
35✔
224

225
  return btf;
70✔
226
}
35✔
227
} // namespace libbtf
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc