1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Facebook */
6 #include <bpf/libbpf.h>
7 #include "test_progs.h"
9 static const char * const btf_kind_str_mapping
[] = {
10 [BTF_KIND_UNKN
] = "UNKNOWN",
11 [BTF_KIND_INT
] = "INT",
12 [BTF_KIND_PTR
] = "PTR",
13 [BTF_KIND_ARRAY
] = "ARRAY",
14 [BTF_KIND_STRUCT
] = "STRUCT",
15 [BTF_KIND_UNION
] = "UNION",
16 [BTF_KIND_ENUM
] = "ENUM",
17 [BTF_KIND_FWD
] = "FWD",
18 [BTF_KIND_TYPEDEF
] = "TYPEDEF",
19 [BTF_KIND_VOLATILE
] = "VOLATILE",
20 [BTF_KIND_CONST
] = "CONST",
21 [BTF_KIND_RESTRICT
] = "RESTRICT",
22 [BTF_KIND_FUNC
] = "FUNC",
23 [BTF_KIND_FUNC_PROTO
] = "FUNC_PROTO",
24 [BTF_KIND_VAR
] = "VAR",
25 [BTF_KIND_DATASEC
] = "DATASEC",
28 static const char *btf_kind_str(__u16 kind
)
30 if (kind
> BTF_KIND_DATASEC
)
32 return btf_kind_str_mapping
[kind
];
35 static const char *btf_int_enc_str(__u8 encoding
)
51 static const char *btf_var_linkage_str(__u32 linkage
)
56 case BTF_VAR_GLOBAL_ALLOCATED
:
57 return "global-alloc";
63 static const char *btf_func_linkage_str(const struct btf_type
*t
)
65 switch (btf_vlen(t
)) {
77 static const char *btf_str(const struct btf
*btf
, __u32 off
)
81 return btf__str_by_offset(btf
, off
) ?: "(invalid)";
84 int fprintf_btf_type_raw(FILE *out
, const struct btf
*btf
, __u32 id
)
86 const struct btf_type
*t
;
90 t
= btf__type_by_id(btf
, id
);
97 fprintf(out
, "[%u] %s '%s'", id
, btf_kind_str(kind
), btf_str(btf
, t
->name_off
));
101 fprintf(out
, " size=%u bits_offset=%u nr_bits=%u encoding=%s",
102 t
->size
, btf_int_offset(t
), btf_int_bits(t
),
103 btf_int_enc_str(btf_int_encoding(t
)));
107 case BTF_KIND_VOLATILE
:
108 case BTF_KIND_RESTRICT
:
109 case BTF_KIND_TYPEDEF
:
110 fprintf(out
, " type_id=%u", t
->type
);
112 case BTF_KIND_ARRAY
: {
113 const struct btf_array
*arr
= btf_array(t
);
115 fprintf(out
, " type_id=%u index_type_id=%u nr_elems=%u",
116 arr
->type
, arr
->index_type
, arr
->nelems
);
119 case BTF_KIND_STRUCT
:
120 case BTF_KIND_UNION
: {
121 const struct btf_member
*m
= btf_members(t
);
123 fprintf(out
, " size=%u vlen=%u", t
->size
, vlen
);
124 for (i
= 0; i
< vlen
; i
++, m
++) {
125 __u32 bit_off
, bit_sz
;
127 bit_off
= btf_member_bit_offset(t
, i
);
128 bit_sz
= btf_member_bitfield_size(t
, i
);
129 fprintf(out
, "\n\t'%s' type_id=%u bits_offset=%u",
130 btf_str(btf
, m
->name_off
), m
->type
, bit_off
);
132 fprintf(out
, " bitfield_size=%u", bit_sz
);
136 case BTF_KIND_ENUM
: {
137 const struct btf_enum
*v
= btf_enum(t
);
139 fprintf(out
, " size=%u vlen=%u", t
->size
, vlen
);
140 for (i
= 0; i
< vlen
; i
++, v
++) {
141 fprintf(out
, "\n\t'%s' val=%u",
142 btf_str(btf
, v
->name_off
), v
->val
);
147 fprintf(out
, " fwd_kind=%s", btf_kflag(t
) ? "union" : "struct");
150 fprintf(out
, " type_id=%u linkage=%s", t
->type
, btf_func_linkage_str(t
));
152 case BTF_KIND_FUNC_PROTO
: {
153 const struct btf_param
*p
= btf_params(t
);
155 fprintf(out
, " ret_type_id=%u vlen=%u", t
->type
, vlen
);
156 for (i
= 0; i
< vlen
; i
++, p
++) {
157 fprintf(out
, "\n\t'%s' type_id=%u",
158 btf_str(btf
, p
->name_off
), p
->type
);
163 fprintf(out
, " type_id=%u, linkage=%s",
164 t
->type
, btf_var_linkage_str(btf_var(t
)->linkage
));
166 case BTF_KIND_DATASEC
: {
167 const struct btf_var_secinfo
*v
= btf_var_secinfos(t
);
169 fprintf(out
, " size=%u vlen=%u", t
->size
, vlen
);
170 for (i
= 0; i
< vlen
; i
++, v
++) {
171 fprintf(out
, "\n\ttype_id=%u offset=%u size=%u",
172 v
->type
, v
->offset
, v
->size
);
183 /* Print raw BTF type dump into a local buffer and return string pointer back.
184 * Buffer *will* be overwritten by subsequent btf_type_raw_dump() calls
186 const char *btf_type_raw_dump(const struct btf
*btf
, int type_id
)
188 static char buf
[16 * 1024];
191 buf_file
= fmemopen(buf
, sizeof(buf
) - 1, "w");
193 fprintf(stderr
, "Failed to open memstream: %d\n", errno
);
197 fprintf_btf_type_raw(buf_file
, btf
, type_id
);
204 int btf_validate_raw(struct btf
*btf
, int nr_types
, const char *exp_types
[])
209 ASSERT_EQ(btf__get_nr_types(btf
), nr_types
, "btf_nr_types");
211 for (i
= 1; i
<= nr_types
; i
++) {
212 if (!ASSERT_STREQ(btf_type_raw_dump(btf
, i
), exp_types
[i
- 1], "raw_dump"))
219 static void btf_dump_printf(void *ctx
, const char *fmt
, va_list args
)
221 vfprintf(ctx
, fmt
, args
);
224 /* Print BTF-to-C dump into a local buffer and return string pointer back.
225 * Buffer *will* be overwritten by subsequent btf_type_raw_dump() calls
227 const char *btf_type_c_dump(const struct btf
*btf
)
229 static char buf
[16 * 1024];
231 struct btf_dump
*d
= NULL
;
232 struct btf_dump_opts opts
= {};
235 buf_file
= fmemopen(buf
, sizeof(buf
) - 1, "w");
237 fprintf(stderr
, "Failed to open memstream: %d\n", errno
);
242 d
= btf_dump__new(btf
, NULL
, &opts
, btf_dump_printf
);
243 if (libbpf_get_error(d
)) {
244 fprintf(stderr
, "Failed to create btf_dump instance: %ld\n", libbpf_get_error(d
));
248 for (i
= 1; i
<= btf__get_nr_types(btf
); i
++) {
249 err
= btf_dump__dump_type(d
, i
);
251 fprintf(stderr
, "Failed to dump type [%d]: %d\n", i
, err
);