1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2020 Facebook */ 3 #include <test_progs.h> 4 #include <bpf/btf.h> 5 6 static int duration = 0; 7 8 void test_btf_write() { 9 const struct btf_var_secinfo *vi; 10 const struct btf_type *t; 11 const struct btf_member *m; 12 const struct btf_enum *v; 13 const struct btf_param *p; 14 struct btf *btf; 15 int id, err, str_off; 16 17 btf = btf__new_empty(); 18 if (CHECK(IS_ERR(btf), "new_empty", "failed: %ld\n", PTR_ERR(btf))) 19 return; 20 21 str_off = btf__find_str(btf, "int"); 22 ASSERT_EQ(str_off, -ENOENT, "int_str_missing_off"); 23 24 str_off = btf__add_str(btf, "int"); 25 ASSERT_EQ(str_off, 1, "int_str_off"); 26 27 str_off = btf__find_str(btf, "int"); 28 ASSERT_EQ(str_off, 1, "int_str_found_off"); 29 30 /* BTF_KIND_INT */ 31 id = btf__add_int(btf, "int", 4, BTF_INT_SIGNED); 32 ASSERT_EQ(id, 1, "int_id"); 33 34 t = btf__type_by_id(btf, 1); 35 /* should re-use previously added "int" string */ 36 ASSERT_EQ(t->name_off, str_off, "int_name_off"); 37 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "int", "int_name"); 38 ASSERT_EQ(btf_kind(t), BTF_KIND_INT, "int_kind"); 39 ASSERT_EQ(t->size, 4, "int_sz"); 40 ASSERT_EQ(btf_int_encoding(t), BTF_INT_SIGNED, "int_enc"); 41 ASSERT_EQ(btf_int_bits(t), 32, "int_bits"); 42 43 /* invalid int size */ 44 id = btf__add_int(btf, "bad sz int", 7, 0); 45 ASSERT_ERR(id, "int_bad_sz"); 46 /* invalid encoding */ 47 id = btf__add_int(btf, "bad enc int", 4, 123); 48 ASSERT_ERR(id, "int_bad_enc"); 49 /* NULL name */ 50 id = btf__add_int(btf, NULL, 4, 0); 51 ASSERT_ERR(id, "int_bad_null_name"); 52 /* empty name */ 53 id = btf__add_int(btf, "", 4, 0); 54 ASSERT_ERR(id, "int_bad_empty_name"); 55 56 /* PTR/CONST/VOLATILE/RESTRICT */ 57 id = btf__add_ptr(btf, 1); 58 ASSERT_EQ(id, 2, "ptr_id"); 59 t = btf__type_by_id(btf, 2); 60 ASSERT_EQ(btf_kind(t), BTF_KIND_PTR, "ptr_kind"); 61 ASSERT_EQ(t->type, 1, "ptr_type"); 62 63 id = btf__add_const(btf, 5); /* points forward to restrict */ 64 ASSERT_EQ(id, 3, "const_id"); 65 t = btf__type_by_id(btf, 3); 66 ASSERT_EQ(btf_kind(t), BTF_KIND_CONST, "const_kind"); 67 ASSERT_EQ(t->type, 5, "const_type"); 68 69 id = btf__add_volatile(btf, 3); 70 ASSERT_EQ(id, 4, "volatile_id"); 71 t = btf__type_by_id(btf, 4); 72 ASSERT_EQ(btf_kind(t), BTF_KIND_VOLATILE, "volatile_kind"); 73 ASSERT_EQ(t->type, 3, "volatile_type"); 74 75 id = btf__add_restrict(btf, 4); 76 ASSERT_EQ(id, 5, "restrict_id"); 77 t = btf__type_by_id(btf, 5); 78 ASSERT_EQ(btf_kind(t), BTF_KIND_RESTRICT, "restrict_kind"); 79 ASSERT_EQ(t->type, 4, "restrict_type"); 80 81 /* ARRAY */ 82 id = btf__add_array(btf, 1, 2, 10); /* int *[10] */ 83 ASSERT_EQ(id, 6, "array_id"); 84 t = btf__type_by_id(btf, 6); 85 ASSERT_EQ(btf_kind(t), BTF_KIND_ARRAY, "array_kind"); 86 ASSERT_EQ(btf_array(t)->index_type, 1, "array_index_type"); 87 ASSERT_EQ(btf_array(t)->type, 2, "array_elem_type"); 88 ASSERT_EQ(btf_array(t)->nelems, 10, "array_nelems"); 89 90 /* STRUCT */ 91 err = btf__add_field(btf, "field", 1, 0, 0); 92 ASSERT_ERR(err, "no_struct_field"); 93 id = btf__add_struct(btf, "s1", 8); 94 ASSERT_EQ(id, 7, "struct_id"); 95 err = btf__add_field(btf, "f1", 1, 0, 0); 96 ASSERT_OK(err, "f1_res"); 97 err = btf__add_field(btf, "f2", 1, 32, 16); 98 ASSERT_OK(err, "f2_res"); 99 100 t = btf__type_by_id(btf, 7); 101 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "s1", "struct_name"); 102 ASSERT_EQ(btf_kind(t), BTF_KIND_STRUCT, "struct_kind"); 103 ASSERT_EQ(btf_vlen(t), 2, "struct_vlen"); 104 ASSERT_EQ(btf_kflag(t), true, "struct_kflag"); 105 ASSERT_EQ(t->size, 8, "struct_sz"); 106 m = btf_members(t) + 0; 107 ASSERT_STREQ(btf__str_by_offset(btf, m->name_off), "f1", "f1_name"); 108 ASSERT_EQ(m->type, 1, "f1_type"); 109 ASSERT_EQ(btf_member_bit_offset(t, 0), 0, "f1_bit_off"); 110 ASSERT_EQ(btf_member_bitfield_size(t, 0), 0, "f1_bit_sz"); 111 m = btf_members(t) + 1; 112 ASSERT_STREQ(btf__str_by_offset(btf, m->name_off), "f2", "f2_name"); 113 ASSERT_EQ(m->type, 1, "f2_type"); 114 ASSERT_EQ(btf_member_bit_offset(t, 1), 32, "f2_bit_off"); 115 ASSERT_EQ(btf_member_bitfield_size(t, 1), 16, "f2_bit_sz"); 116 117 /* UNION */ 118 id = btf__add_union(btf, "u1", 8); 119 ASSERT_EQ(id, 8, "union_id"); 120 121 /* invalid, non-zero offset */ 122 err = btf__add_field(btf, "field", 1, 1, 0); 123 ASSERT_ERR(err, "no_struct_field"); 124 125 err = btf__add_field(btf, "f1", 1, 0, 16); 126 ASSERT_OK(err, "f1_res"); 127 128 t = btf__type_by_id(btf, 8); 129 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "u1", "union_name"); 130 ASSERT_EQ(btf_kind(t), BTF_KIND_UNION, "union_kind"); 131 ASSERT_EQ(btf_vlen(t), 1, "union_vlen"); 132 ASSERT_EQ(btf_kflag(t), true, "union_kflag"); 133 ASSERT_EQ(t->size, 8, "union_sz"); 134 m = btf_members(t) + 0; 135 ASSERT_STREQ(btf__str_by_offset(btf, m->name_off), "f1", "f1_name"); 136 ASSERT_EQ(m->type, 1, "f1_type"); 137 ASSERT_EQ(btf_member_bit_offset(t, 0), 0, "f1_bit_off"); 138 ASSERT_EQ(btf_member_bitfield_size(t, 0), 16, "f1_bit_sz"); 139 140 /* ENUM */ 141 id = btf__add_enum(btf, "e1", 4); 142 ASSERT_EQ(id, 9, "enum_id"); 143 err = btf__add_enum_value(btf, "v1", 1); 144 ASSERT_OK(err, "v1_res"); 145 err = btf__add_enum_value(btf, "v2", 2); 146 ASSERT_OK(err, "v2_res"); 147 148 t = btf__type_by_id(btf, 9); 149 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "e1", "enum_name"); 150 ASSERT_EQ(btf_kind(t), BTF_KIND_ENUM, "enum_kind"); 151 ASSERT_EQ(btf_vlen(t), 2, "enum_vlen"); 152 ASSERT_EQ(t->size, 4, "enum_sz"); 153 v = btf_enum(t) + 0; 154 ASSERT_STREQ(btf__str_by_offset(btf, v->name_off), "v1", "v1_name"); 155 ASSERT_EQ(v->val, 1, "v1_val"); 156 v = btf_enum(t) + 1; 157 ASSERT_STREQ(btf__str_by_offset(btf, v->name_off), "v2", "v2_name"); 158 ASSERT_EQ(v->val, 2, "v2_val"); 159 160 /* FWDs */ 161 id = btf__add_fwd(btf, "struct_fwd", BTF_FWD_STRUCT); 162 ASSERT_EQ(id, 10, "struct_fwd_id"); 163 t = btf__type_by_id(btf, 10); 164 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "struct_fwd", "fwd_name"); 165 ASSERT_EQ(btf_kind(t), BTF_KIND_FWD, "fwd_kind"); 166 ASSERT_EQ(btf_kflag(t), 0, "fwd_kflag"); 167 168 id = btf__add_fwd(btf, "union_fwd", BTF_FWD_UNION); 169 ASSERT_EQ(id, 11, "union_fwd_id"); 170 t = btf__type_by_id(btf, 11); 171 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "union_fwd", "fwd_name"); 172 ASSERT_EQ(btf_kind(t), BTF_KIND_FWD, "fwd_kind"); 173 ASSERT_EQ(btf_kflag(t), 1, "fwd_kflag"); 174 175 id = btf__add_fwd(btf, "enum_fwd", BTF_FWD_ENUM); 176 ASSERT_EQ(id, 12, "enum_fwd_id"); 177 t = btf__type_by_id(btf, 12); 178 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "enum_fwd", "fwd_name"); 179 ASSERT_EQ(btf_kind(t), BTF_KIND_ENUM, "enum_fwd_kind"); 180 ASSERT_EQ(btf_vlen(t), 0, "enum_fwd_kind"); 181 ASSERT_EQ(t->size, 4, "enum_fwd_sz"); 182 183 /* TYPEDEF */ 184 id = btf__add_typedef(btf, "typedef1", 1); 185 ASSERT_EQ(id, 13, "typedef_fwd_id"); 186 t = btf__type_by_id(btf, 13); 187 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "typedef1", "typedef_name"); 188 ASSERT_EQ(btf_kind(t), BTF_KIND_TYPEDEF, "typedef_kind"); 189 ASSERT_EQ(t->type, 1, "typedef_type"); 190 191 /* FUNC & FUNC_PROTO */ 192 id = btf__add_func(btf, "func1", BTF_FUNC_GLOBAL, 15); 193 ASSERT_EQ(id, 14, "func_id"); 194 t = btf__type_by_id(btf, 14); 195 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "func1", "func_name"); 196 ASSERT_EQ(t->type, 15, "func_type"); 197 ASSERT_EQ(btf_kind(t), BTF_KIND_FUNC, "func_kind"); 198 ASSERT_EQ(btf_vlen(t), BTF_FUNC_GLOBAL, "func_vlen"); 199 200 id = btf__add_func_proto(btf, 1); 201 ASSERT_EQ(id, 15, "func_proto_id"); 202 err = btf__add_func_param(btf, "p1", 1); 203 ASSERT_OK(err, "p1_res"); 204 err = btf__add_func_param(btf, "p2", 2); 205 ASSERT_OK(err, "p2_res"); 206 207 t = btf__type_by_id(btf, 15); 208 ASSERT_EQ(btf_kind(t), BTF_KIND_FUNC_PROTO, "func_proto_kind"); 209 ASSERT_EQ(btf_vlen(t), 2, "func_proto_vlen"); 210 ASSERT_EQ(t->type, 1, "func_proto_ret_type"); 211 p = btf_params(t) + 0; 212 ASSERT_STREQ(btf__str_by_offset(btf, p->name_off), "p1", "p1_name"); 213 ASSERT_EQ(p->type, 1, "p1_type"); 214 p = btf_params(t) + 1; 215 ASSERT_STREQ(btf__str_by_offset(btf, p->name_off), "p2", "p2_name"); 216 ASSERT_EQ(p->type, 2, "p2_type"); 217 218 /* VAR */ 219 id = btf__add_var(btf, "var1", BTF_VAR_GLOBAL_ALLOCATED, 1); 220 ASSERT_EQ(id, 16, "var_id"); 221 t = btf__type_by_id(btf, 16); 222 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "var1", "var_name"); 223 ASSERT_EQ(btf_kind(t), BTF_KIND_VAR, "var_kind"); 224 ASSERT_EQ(t->type, 1, "var_type"); 225 ASSERT_EQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_ALLOCATED, "var_type"); 226 227 /* DATASECT */ 228 id = btf__add_datasec(btf, "datasec1", 12); 229 ASSERT_EQ(id, 17, "datasec_id"); 230 err = btf__add_datasec_var_info(btf, 1, 4, 8); 231 ASSERT_OK(err, "v1_res"); 232 233 t = btf__type_by_id(btf, 17); 234 ASSERT_STREQ(btf__str_by_offset(btf, t->name_off), "datasec1", "datasec_name"); 235 ASSERT_EQ(t->size, 12, "datasec_sz"); 236 ASSERT_EQ(btf_kind(t), BTF_KIND_DATASEC, "datasec_kind"); 237 ASSERT_EQ(btf_vlen(t), 1, "datasec_vlen"); 238 vi = btf_var_secinfos(t) + 0; 239 ASSERT_EQ(vi->type, 1, "v1_type"); 240 ASSERT_EQ(vi->offset, 4, "v1_off"); 241 ASSERT_EQ(vi->size, 8, "v1_sz"); 242 243 btf__free(btf); 244 } 245