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",
26 [BTF_KIND_FLOAT
] = "FLOAT",
27 [BTF_KIND_DECL_TAG
] = "DECL_TAG",
28 [BTF_KIND_TYPE_TAG
] = "TYPE_TAG",
29 [BTF_KIND_ENUM64
] = "ENUM64",
32 static const char *btf_kind_str(__u16 kind
)
34 if (kind
> BTF_KIND_ENUM64
)
36 return btf_kind_str_mapping
[kind
];
39 static const char *btf_int_enc_str(__u8 encoding
)
55 static const char *btf_var_linkage_str(__u32 linkage
)
60 case BTF_VAR_GLOBAL_ALLOCATED
:
61 return "global-alloc";
67 static const char *btf_func_linkage_str(const struct btf_type
*t
)
69 switch (btf_vlen(t
)) {
81 static const char *btf_str(const struct btf
*btf
, __u32 off
)
85 return btf__str_by_offset(btf
, off
) ?: "(invalid)";
88 int fprintf_btf_type_raw(FILE *out
, const struct btf
*btf
, __u32 id
)
90 const struct btf_type
*t
;
94 t
= btf__type_by_id(btf
, id
);
101 fprintf(out
, "[%u] %s '%s'", id
, btf_kind_str(kind
), btf_str(btf
, t
->name_off
));
105 fprintf(out
, " size=%u bits_offset=%u nr_bits=%u encoding=%s",
106 t
->size
, btf_int_offset(t
), btf_int_bits(t
),
107 btf_int_enc_str(btf_int_encoding(t
)));
111 case BTF_KIND_VOLATILE
:
112 case BTF_KIND_RESTRICT
:
113 case BTF_KIND_TYPEDEF
:
114 case BTF_KIND_TYPE_TAG
:
115 fprintf(out
, " type_id=%u", t
->type
);
117 case BTF_KIND_ARRAY
: {
118 const struct btf_array
*arr
= btf_array(t
);
120 fprintf(out
, " type_id=%u index_type_id=%u nr_elems=%u",
121 arr
->type
, arr
->index_type
, arr
->nelems
);
124 case BTF_KIND_STRUCT
:
125 case BTF_KIND_UNION
: {
126 const struct btf_member
*m
= btf_members(t
);
128 fprintf(out
, " size=%u vlen=%u", t
->size
, vlen
);
129 for (i
= 0; i
< vlen
; i
++, m
++) {
130 __u32 bit_off
, bit_sz
;
132 bit_off
= btf_member_bit_offset(t
, i
);
133 bit_sz
= btf_member_bitfield_size(t
, i
);
134 fprintf(out
, "\n\t'%s' type_id=%u bits_offset=%u",
135 btf_str(btf
, m
->name_off
), m
->type
, bit_off
);
137 fprintf(out
, " bitfield_size=%u", bit_sz
);
141 case BTF_KIND_ENUM
: {
142 const struct btf_enum
*v
= btf_enum(t
);
145 fmt_str
= btf_kflag(t
) ? "\n\t'%s' val=%d" : "\n\t'%s' val=%u";
146 fprintf(out
, " encoding=%s size=%u vlen=%u",
147 btf_kflag(t
) ? "SIGNED" : "UNSIGNED", t
->size
, vlen
);
148 for (i
= 0; i
< vlen
; i
++, v
++) {
149 fprintf(out
, fmt_str
,
150 btf_str(btf
, v
->name_off
), v
->val
);
154 case BTF_KIND_ENUM64
: {
155 const struct btf_enum64
*v
= btf_enum64(t
);
158 fmt_str
= btf_kflag(t
) ? "\n\t'%s' val=%lld" : "\n\t'%s' val=%llu";
160 fprintf(out
, " encoding=%s size=%u vlen=%u",
161 btf_kflag(t
) ? "SIGNED" : "UNSIGNED", t
->size
, vlen
);
162 for (i
= 0; i
< vlen
; i
++, v
++) {
163 fprintf(out
, fmt_str
,
164 btf_str(btf
, v
->name_off
),
165 ((__u64
)v
->val_hi32
<< 32) | v
->val_lo32
);
170 fprintf(out
, " fwd_kind=%s", btf_kflag(t
) ? "union" : "struct");
173 fprintf(out
, " type_id=%u linkage=%s", t
->type
, btf_func_linkage_str(t
));
175 case BTF_KIND_FUNC_PROTO
: {
176 const struct btf_param
*p
= btf_params(t
);
178 fprintf(out
, " ret_type_id=%u vlen=%u", t
->type
, vlen
);
179 for (i
= 0; i
< vlen
; i
++, p
++) {
180 fprintf(out
, "\n\t'%s' type_id=%u",
181 btf_str(btf
, p
->name_off
), p
->type
);
186 fprintf(out
, " type_id=%u, linkage=%s",
187 t
->type
, btf_var_linkage_str(btf_var(t
)->linkage
));
189 case BTF_KIND_DATASEC
: {
190 const struct btf_var_secinfo
*v
= btf_var_secinfos(t
);
192 fprintf(out
, " size=%u vlen=%u", t
->size
, vlen
);
193 for (i
= 0; i
< vlen
; i
++, v
++) {
194 fprintf(out
, "\n\ttype_id=%u offset=%u size=%u",
195 v
->type
, v
->offset
, v
->size
);
200 fprintf(out
, " size=%u", t
->size
);
202 case BTF_KIND_DECL_TAG
:
203 fprintf(out
, " type_id=%u component_idx=%d",
204 t
->type
, btf_decl_tag(t
)->component_idx
);
213 /* Print raw BTF type dump into a local buffer and return string pointer back.
214 * Buffer *will* be overwritten by subsequent btf_type_raw_dump() calls
216 const char *btf_type_raw_dump(const struct btf
*btf
, int type_id
)
218 static char buf
[16 * 1024];
221 buf_file
= fmemopen(buf
, sizeof(buf
) - 1, "w");
223 fprintf(stderr
, "Failed to open memstream: %d\n", errno
);
227 fprintf_btf_type_raw(buf_file
, btf
, type_id
);
234 int btf_validate_raw(struct btf
*btf
, int nr_types
, const char *exp_types
[])
239 ASSERT_EQ(btf__type_cnt(btf
) - 1, nr_types
, "btf_nr_types");
241 for (i
= 1; i
<= nr_types
; i
++) {
242 if (!ASSERT_STREQ(btf_type_raw_dump(btf
, i
), exp_types
[i
- 1], "raw_dump"))
249 static void btf_dump_printf(void *ctx
, const char *fmt
, va_list args
)
251 vfprintf(ctx
, fmt
, args
);
254 /* Print BTF-to-C dump into a local buffer and return string pointer back.
255 * Buffer *will* be overwritten by subsequent btf_type_raw_dump() calls
257 const char *btf_type_c_dump(const struct btf
*btf
)
259 static char buf
[16 * 1024];
261 struct btf_dump
*d
= NULL
;
264 buf_file
= fmemopen(buf
, sizeof(buf
) - 1, "w");
266 fprintf(stderr
, "Failed to open memstream: %d\n", errno
);
270 d
= btf_dump__new(btf
, btf_dump_printf
, buf_file
, NULL
);
271 if (libbpf_get_error(d
)) {
272 fprintf(stderr
, "Failed to create btf_dump instance: %ld\n", libbpf_get_error(d
));
276 for (i
= 1; i
< btf__type_cnt(btf
); i
++) {
277 err
= btf_dump__dump_type(d
, i
);
279 fprintf(stderr
, "Failed to dump type [%d]: %d\n", i
, err
);