1*858ea5e5SAndroid Build Coastguard Worker // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*858ea5e5SAndroid Build Coastguard Worker /* Copyright (C) 2019 Facebook */
3*858ea5e5SAndroid Build Coastguard Worker
4*858ea5e5SAndroid Build Coastguard Worker #include <errno.h>
5*858ea5e5SAndroid Build Coastguard Worker #include <fcntl.h>
6*858ea5e5SAndroid Build Coastguard Worker #include <linux/err.h>
7*858ea5e5SAndroid Build Coastguard Worker #include <stdbool.h>
8*858ea5e5SAndroid Build Coastguard Worker #include <stdio.h>
9*858ea5e5SAndroid Build Coastguard Worker #include <string.h>
10*858ea5e5SAndroid Build Coastguard Worker #include <unistd.h>
11*858ea5e5SAndroid Build Coastguard Worker #include <linux/btf.h>
12*858ea5e5SAndroid Build Coastguard Worker #include <sys/types.h>
13*858ea5e5SAndroid Build Coastguard Worker #include <sys/stat.h>
14*858ea5e5SAndroid Build Coastguard Worker
15*858ea5e5SAndroid Build Coastguard Worker #include <bpf/bpf.h>
16*858ea5e5SAndroid Build Coastguard Worker #include <bpf/btf.h>
17*858ea5e5SAndroid Build Coastguard Worker #include <bpf/hashmap.h>
18*858ea5e5SAndroid Build Coastguard Worker #include <bpf/libbpf.h>
19*858ea5e5SAndroid Build Coastguard Worker
20*858ea5e5SAndroid Build Coastguard Worker #include "json_writer.h"
21*858ea5e5SAndroid Build Coastguard Worker #include "main.h"
22*858ea5e5SAndroid Build Coastguard Worker
23*858ea5e5SAndroid Build Coastguard Worker static const char * const btf_kind_str[NR_BTF_KINDS] = {
24*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_UNKN] = "UNKNOWN",
25*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_INT] = "INT",
26*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_PTR] = "PTR",
27*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_ARRAY] = "ARRAY",
28*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_STRUCT] = "STRUCT",
29*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_UNION] = "UNION",
30*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_ENUM] = "ENUM",
31*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_FWD] = "FWD",
32*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_TYPEDEF] = "TYPEDEF",
33*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_VOLATILE] = "VOLATILE",
34*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_CONST] = "CONST",
35*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_RESTRICT] = "RESTRICT",
36*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_FUNC] = "FUNC",
37*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO",
38*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_VAR] = "VAR",
39*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_DATASEC] = "DATASEC",
40*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_FLOAT] = "FLOAT",
41*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_DECL_TAG] = "DECL_TAG",
42*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_TYPE_TAG] = "TYPE_TAG",
43*858ea5e5SAndroid Build Coastguard Worker [BTF_KIND_ENUM64] = "ENUM64",
44*858ea5e5SAndroid Build Coastguard Worker };
45*858ea5e5SAndroid Build Coastguard Worker
btf_int_enc_str(__u8 encoding)46*858ea5e5SAndroid Build Coastguard Worker static const char *btf_int_enc_str(__u8 encoding)
47*858ea5e5SAndroid Build Coastguard Worker {
48*858ea5e5SAndroid Build Coastguard Worker switch (encoding) {
49*858ea5e5SAndroid Build Coastguard Worker case 0:
50*858ea5e5SAndroid Build Coastguard Worker return "(none)";
51*858ea5e5SAndroid Build Coastguard Worker case BTF_INT_SIGNED:
52*858ea5e5SAndroid Build Coastguard Worker return "SIGNED";
53*858ea5e5SAndroid Build Coastguard Worker case BTF_INT_CHAR:
54*858ea5e5SAndroid Build Coastguard Worker return "CHAR";
55*858ea5e5SAndroid Build Coastguard Worker case BTF_INT_BOOL:
56*858ea5e5SAndroid Build Coastguard Worker return "BOOL";
57*858ea5e5SAndroid Build Coastguard Worker default:
58*858ea5e5SAndroid Build Coastguard Worker return "UNKN";
59*858ea5e5SAndroid Build Coastguard Worker }
60*858ea5e5SAndroid Build Coastguard Worker }
61*858ea5e5SAndroid Build Coastguard Worker
btf_var_linkage_str(__u32 linkage)62*858ea5e5SAndroid Build Coastguard Worker static const char *btf_var_linkage_str(__u32 linkage)
63*858ea5e5SAndroid Build Coastguard Worker {
64*858ea5e5SAndroid Build Coastguard Worker switch (linkage) {
65*858ea5e5SAndroid Build Coastguard Worker case BTF_VAR_STATIC:
66*858ea5e5SAndroid Build Coastguard Worker return "static";
67*858ea5e5SAndroid Build Coastguard Worker case BTF_VAR_GLOBAL_ALLOCATED:
68*858ea5e5SAndroid Build Coastguard Worker return "global";
69*858ea5e5SAndroid Build Coastguard Worker case BTF_VAR_GLOBAL_EXTERN:
70*858ea5e5SAndroid Build Coastguard Worker return "extern";
71*858ea5e5SAndroid Build Coastguard Worker default:
72*858ea5e5SAndroid Build Coastguard Worker return "(unknown)";
73*858ea5e5SAndroid Build Coastguard Worker }
74*858ea5e5SAndroid Build Coastguard Worker }
75*858ea5e5SAndroid Build Coastguard Worker
btf_func_linkage_str(const struct btf_type * t)76*858ea5e5SAndroid Build Coastguard Worker static const char *btf_func_linkage_str(const struct btf_type *t)
77*858ea5e5SAndroid Build Coastguard Worker {
78*858ea5e5SAndroid Build Coastguard Worker switch (btf_vlen(t)) {
79*858ea5e5SAndroid Build Coastguard Worker case BTF_FUNC_STATIC:
80*858ea5e5SAndroid Build Coastguard Worker return "static";
81*858ea5e5SAndroid Build Coastguard Worker case BTF_FUNC_GLOBAL:
82*858ea5e5SAndroid Build Coastguard Worker return "global";
83*858ea5e5SAndroid Build Coastguard Worker case BTF_FUNC_EXTERN:
84*858ea5e5SAndroid Build Coastguard Worker return "extern";
85*858ea5e5SAndroid Build Coastguard Worker default:
86*858ea5e5SAndroid Build Coastguard Worker return "(unknown)";
87*858ea5e5SAndroid Build Coastguard Worker }
88*858ea5e5SAndroid Build Coastguard Worker }
89*858ea5e5SAndroid Build Coastguard Worker
btf_str(const struct btf * btf,__u32 off)90*858ea5e5SAndroid Build Coastguard Worker static const char *btf_str(const struct btf *btf, __u32 off)
91*858ea5e5SAndroid Build Coastguard Worker {
92*858ea5e5SAndroid Build Coastguard Worker if (!off)
93*858ea5e5SAndroid Build Coastguard Worker return "(anon)";
94*858ea5e5SAndroid Build Coastguard Worker return btf__name_by_offset(btf, off) ? : "(invalid)";
95*858ea5e5SAndroid Build Coastguard Worker }
96*858ea5e5SAndroid Build Coastguard Worker
btf_kind_safe(int kind)97*858ea5e5SAndroid Build Coastguard Worker static int btf_kind_safe(int kind)
98*858ea5e5SAndroid Build Coastguard Worker {
99*858ea5e5SAndroid Build Coastguard Worker return kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN;
100*858ea5e5SAndroid Build Coastguard Worker }
101*858ea5e5SAndroid Build Coastguard Worker
dump_btf_type(const struct btf * btf,__u32 id,const struct btf_type * t)102*858ea5e5SAndroid Build Coastguard Worker static int dump_btf_type(const struct btf *btf, __u32 id,
103*858ea5e5SAndroid Build Coastguard Worker const struct btf_type *t)
104*858ea5e5SAndroid Build Coastguard Worker {
105*858ea5e5SAndroid Build Coastguard Worker json_writer_t *w = json_wtr;
106*858ea5e5SAndroid Build Coastguard Worker int kind = btf_kind(t);
107*858ea5e5SAndroid Build Coastguard Worker
108*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
109*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(w);
110*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "id", id);
111*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "kind", btf_kind_str[btf_kind_safe(kind)]);
112*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "name", btf_str(btf, t->name_off));
113*858ea5e5SAndroid Build Coastguard Worker } else {
114*858ea5e5SAndroid Build Coastguard Worker printf("[%u] %s '%s'", id, btf_kind_str[btf_kind_safe(kind)],
115*858ea5e5SAndroid Build Coastguard Worker btf_str(btf, t->name_off));
116*858ea5e5SAndroid Build Coastguard Worker }
117*858ea5e5SAndroid Build Coastguard Worker
118*858ea5e5SAndroid Build Coastguard Worker switch (kind) {
119*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_INT: {
120*858ea5e5SAndroid Build Coastguard Worker __u32 v = *(__u32 *)(t + 1);
121*858ea5e5SAndroid Build Coastguard Worker const char *enc;
122*858ea5e5SAndroid Build Coastguard Worker
123*858ea5e5SAndroid Build Coastguard Worker enc = btf_int_enc_str(BTF_INT_ENCODING(v));
124*858ea5e5SAndroid Build Coastguard Worker
125*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
126*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "size", t->size);
127*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "bits_offset", BTF_INT_OFFSET(v));
128*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "nr_bits", BTF_INT_BITS(v));
129*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "encoding", enc);
130*858ea5e5SAndroid Build Coastguard Worker } else {
131*858ea5e5SAndroid Build Coastguard Worker printf(" size=%u bits_offset=%u nr_bits=%u encoding=%s",
132*858ea5e5SAndroid Build Coastguard Worker t->size, BTF_INT_OFFSET(v), BTF_INT_BITS(v),
133*858ea5e5SAndroid Build Coastguard Worker enc);
134*858ea5e5SAndroid Build Coastguard Worker }
135*858ea5e5SAndroid Build Coastguard Worker break;
136*858ea5e5SAndroid Build Coastguard Worker }
137*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_PTR:
138*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_CONST:
139*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_VOLATILE:
140*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_RESTRICT:
141*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_TYPEDEF:
142*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_TYPE_TAG:
143*858ea5e5SAndroid Build Coastguard Worker if (json_output)
144*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "type_id", t->type);
145*858ea5e5SAndroid Build Coastguard Worker else
146*858ea5e5SAndroid Build Coastguard Worker printf(" type_id=%u", t->type);
147*858ea5e5SAndroid Build Coastguard Worker break;
148*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_ARRAY: {
149*858ea5e5SAndroid Build Coastguard Worker const struct btf_array *arr = (const void *)(t + 1);
150*858ea5e5SAndroid Build Coastguard Worker
151*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
152*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "type_id", arr->type);
153*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "index_type_id", arr->index_type);
154*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "nr_elems", arr->nelems);
155*858ea5e5SAndroid Build Coastguard Worker } else {
156*858ea5e5SAndroid Build Coastguard Worker printf(" type_id=%u index_type_id=%u nr_elems=%u",
157*858ea5e5SAndroid Build Coastguard Worker arr->type, arr->index_type, arr->nelems);
158*858ea5e5SAndroid Build Coastguard Worker }
159*858ea5e5SAndroid Build Coastguard Worker break;
160*858ea5e5SAndroid Build Coastguard Worker }
161*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_STRUCT:
162*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_UNION: {
163*858ea5e5SAndroid Build Coastguard Worker const struct btf_member *m = (const void *)(t + 1);
164*858ea5e5SAndroid Build Coastguard Worker __u16 vlen = BTF_INFO_VLEN(t->info);
165*858ea5e5SAndroid Build Coastguard Worker int i;
166*858ea5e5SAndroid Build Coastguard Worker
167*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
168*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "size", t->size);
169*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "vlen", vlen);
170*858ea5e5SAndroid Build Coastguard Worker jsonw_name(w, "members");
171*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(w);
172*858ea5e5SAndroid Build Coastguard Worker } else {
173*858ea5e5SAndroid Build Coastguard Worker printf(" size=%u vlen=%u", t->size, vlen);
174*858ea5e5SAndroid Build Coastguard Worker }
175*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < vlen; i++, m++) {
176*858ea5e5SAndroid Build Coastguard Worker const char *name = btf_str(btf, m->name_off);
177*858ea5e5SAndroid Build Coastguard Worker __u32 bit_off, bit_sz;
178*858ea5e5SAndroid Build Coastguard Worker
179*858ea5e5SAndroid Build Coastguard Worker if (BTF_INFO_KFLAG(t->info)) {
180*858ea5e5SAndroid Build Coastguard Worker bit_off = BTF_MEMBER_BIT_OFFSET(m->offset);
181*858ea5e5SAndroid Build Coastguard Worker bit_sz = BTF_MEMBER_BITFIELD_SIZE(m->offset);
182*858ea5e5SAndroid Build Coastguard Worker } else {
183*858ea5e5SAndroid Build Coastguard Worker bit_off = m->offset;
184*858ea5e5SAndroid Build Coastguard Worker bit_sz = 0;
185*858ea5e5SAndroid Build Coastguard Worker }
186*858ea5e5SAndroid Build Coastguard Worker
187*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
188*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(w);
189*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "name", name);
190*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "type_id", m->type);
191*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "bits_offset", bit_off);
192*858ea5e5SAndroid Build Coastguard Worker if (bit_sz) {
193*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "bitfield_size",
194*858ea5e5SAndroid Build Coastguard Worker bit_sz);
195*858ea5e5SAndroid Build Coastguard Worker }
196*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(w);
197*858ea5e5SAndroid Build Coastguard Worker } else {
198*858ea5e5SAndroid Build Coastguard Worker printf("\n\t'%s' type_id=%u bits_offset=%u",
199*858ea5e5SAndroid Build Coastguard Worker name, m->type, bit_off);
200*858ea5e5SAndroid Build Coastguard Worker if (bit_sz)
201*858ea5e5SAndroid Build Coastguard Worker printf(" bitfield_size=%u", bit_sz);
202*858ea5e5SAndroid Build Coastguard Worker }
203*858ea5e5SAndroid Build Coastguard Worker }
204*858ea5e5SAndroid Build Coastguard Worker if (json_output)
205*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(w);
206*858ea5e5SAndroid Build Coastguard Worker break;
207*858ea5e5SAndroid Build Coastguard Worker }
208*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_ENUM: {
209*858ea5e5SAndroid Build Coastguard Worker const struct btf_enum *v = (const void *)(t + 1);
210*858ea5e5SAndroid Build Coastguard Worker __u16 vlen = BTF_INFO_VLEN(t->info);
211*858ea5e5SAndroid Build Coastguard Worker const char *encoding;
212*858ea5e5SAndroid Build Coastguard Worker int i;
213*858ea5e5SAndroid Build Coastguard Worker
214*858ea5e5SAndroid Build Coastguard Worker encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
215*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
216*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "encoding", encoding);
217*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "size", t->size);
218*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "vlen", vlen);
219*858ea5e5SAndroid Build Coastguard Worker jsonw_name(w, "values");
220*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(w);
221*858ea5e5SAndroid Build Coastguard Worker } else {
222*858ea5e5SAndroid Build Coastguard Worker printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
223*858ea5e5SAndroid Build Coastguard Worker }
224*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < vlen; i++, v++) {
225*858ea5e5SAndroid Build Coastguard Worker const char *name = btf_str(btf, v->name_off);
226*858ea5e5SAndroid Build Coastguard Worker
227*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
228*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(w);
229*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "name", name);
230*858ea5e5SAndroid Build Coastguard Worker if (btf_kflag(t))
231*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(w, "val", v->val);
232*858ea5e5SAndroid Build Coastguard Worker else
233*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "val", v->val);
234*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(w);
235*858ea5e5SAndroid Build Coastguard Worker } else {
236*858ea5e5SAndroid Build Coastguard Worker if (btf_kflag(t))
237*858ea5e5SAndroid Build Coastguard Worker printf("\n\t'%s' val=%d", name, v->val);
238*858ea5e5SAndroid Build Coastguard Worker else
239*858ea5e5SAndroid Build Coastguard Worker printf("\n\t'%s' val=%u", name, v->val);
240*858ea5e5SAndroid Build Coastguard Worker }
241*858ea5e5SAndroid Build Coastguard Worker }
242*858ea5e5SAndroid Build Coastguard Worker if (json_output)
243*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(w);
244*858ea5e5SAndroid Build Coastguard Worker break;
245*858ea5e5SAndroid Build Coastguard Worker }
246*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_ENUM64: {
247*858ea5e5SAndroid Build Coastguard Worker const struct btf_enum64 *v = btf_enum64(t);
248*858ea5e5SAndroid Build Coastguard Worker __u16 vlen = btf_vlen(t);
249*858ea5e5SAndroid Build Coastguard Worker const char *encoding;
250*858ea5e5SAndroid Build Coastguard Worker int i;
251*858ea5e5SAndroid Build Coastguard Worker
252*858ea5e5SAndroid Build Coastguard Worker encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
253*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
254*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "encoding", encoding);
255*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "size", t->size);
256*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "vlen", vlen);
257*858ea5e5SAndroid Build Coastguard Worker jsonw_name(w, "values");
258*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(w);
259*858ea5e5SAndroid Build Coastguard Worker } else {
260*858ea5e5SAndroid Build Coastguard Worker printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
261*858ea5e5SAndroid Build Coastguard Worker }
262*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < vlen; i++, v++) {
263*858ea5e5SAndroid Build Coastguard Worker const char *name = btf_str(btf, v->name_off);
264*858ea5e5SAndroid Build Coastguard Worker __u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
265*858ea5e5SAndroid Build Coastguard Worker
266*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
267*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(w);
268*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "name", name);
269*858ea5e5SAndroid Build Coastguard Worker if (btf_kflag(t))
270*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(w, "val", val);
271*858ea5e5SAndroid Build Coastguard Worker else
272*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "val", val);
273*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(w);
274*858ea5e5SAndroid Build Coastguard Worker } else {
275*858ea5e5SAndroid Build Coastguard Worker if (btf_kflag(t))
276*858ea5e5SAndroid Build Coastguard Worker printf("\n\t'%s' val=%lldLL", name,
277*858ea5e5SAndroid Build Coastguard Worker (unsigned long long)val);
278*858ea5e5SAndroid Build Coastguard Worker else
279*858ea5e5SAndroid Build Coastguard Worker printf("\n\t'%s' val=%lluULL", name,
280*858ea5e5SAndroid Build Coastguard Worker (unsigned long long)val);
281*858ea5e5SAndroid Build Coastguard Worker }
282*858ea5e5SAndroid Build Coastguard Worker }
283*858ea5e5SAndroid Build Coastguard Worker if (json_output)
284*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(w);
285*858ea5e5SAndroid Build Coastguard Worker break;
286*858ea5e5SAndroid Build Coastguard Worker }
287*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_FWD: {
288*858ea5e5SAndroid Build Coastguard Worker const char *fwd_kind = BTF_INFO_KFLAG(t->info) ? "union"
289*858ea5e5SAndroid Build Coastguard Worker : "struct";
290*858ea5e5SAndroid Build Coastguard Worker
291*858ea5e5SAndroid Build Coastguard Worker if (json_output)
292*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "fwd_kind", fwd_kind);
293*858ea5e5SAndroid Build Coastguard Worker else
294*858ea5e5SAndroid Build Coastguard Worker printf(" fwd_kind=%s", fwd_kind);
295*858ea5e5SAndroid Build Coastguard Worker break;
296*858ea5e5SAndroid Build Coastguard Worker }
297*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_FUNC: {
298*858ea5e5SAndroid Build Coastguard Worker const char *linkage = btf_func_linkage_str(t);
299*858ea5e5SAndroid Build Coastguard Worker
300*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
301*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "type_id", t->type);
302*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "linkage", linkage);
303*858ea5e5SAndroid Build Coastguard Worker } else {
304*858ea5e5SAndroid Build Coastguard Worker printf(" type_id=%u linkage=%s", t->type, linkage);
305*858ea5e5SAndroid Build Coastguard Worker }
306*858ea5e5SAndroid Build Coastguard Worker break;
307*858ea5e5SAndroid Build Coastguard Worker }
308*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_FUNC_PROTO: {
309*858ea5e5SAndroid Build Coastguard Worker const struct btf_param *p = (const void *)(t + 1);
310*858ea5e5SAndroid Build Coastguard Worker __u16 vlen = BTF_INFO_VLEN(t->info);
311*858ea5e5SAndroid Build Coastguard Worker int i;
312*858ea5e5SAndroid Build Coastguard Worker
313*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
314*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "ret_type_id", t->type);
315*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "vlen", vlen);
316*858ea5e5SAndroid Build Coastguard Worker jsonw_name(w, "params");
317*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(w);
318*858ea5e5SAndroid Build Coastguard Worker } else {
319*858ea5e5SAndroid Build Coastguard Worker printf(" ret_type_id=%u vlen=%u", t->type, vlen);
320*858ea5e5SAndroid Build Coastguard Worker }
321*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < vlen; i++, p++) {
322*858ea5e5SAndroid Build Coastguard Worker const char *name = btf_str(btf, p->name_off);
323*858ea5e5SAndroid Build Coastguard Worker
324*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
325*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(w);
326*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "name", name);
327*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "type_id", p->type);
328*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(w);
329*858ea5e5SAndroid Build Coastguard Worker } else {
330*858ea5e5SAndroid Build Coastguard Worker printf("\n\t'%s' type_id=%u", name, p->type);
331*858ea5e5SAndroid Build Coastguard Worker }
332*858ea5e5SAndroid Build Coastguard Worker }
333*858ea5e5SAndroid Build Coastguard Worker if (json_output)
334*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(w);
335*858ea5e5SAndroid Build Coastguard Worker break;
336*858ea5e5SAndroid Build Coastguard Worker }
337*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_VAR: {
338*858ea5e5SAndroid Build Coastguard Worker const struct btf_var *v = (const void *)(t + 1);
339*858ea5e5SAndroid Build Coastguard Worker const char *linkage;
340*858ea5e5SAndroid Build Coastguard Worker
341*858ea5e5SAndroid Build Coastguard Worker linkage = btf_var_linkage_str(v->linkage);
342*858ea5e5SAndroid Build Coastguard Worker
343*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
344*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "type_id", t->type);
345*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(w, "linkage", linkage);
346*858ea5e5SAndroid Build Coastguard Worker } else {
347*858ea5e5SAndroid Build Coastguard Worker printf(" type_id=%u, linkage=%s", t->type, linkage);
348*858ea5e5SAndroid Build Coastguard Worker }
349*858ea5e5SAndroid Build Coastguard Worker break;
350*858ea5e5SAndroid Build Coastguard Worker }
351*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_DATASEC: {
352*858ea5e5SAndroid Build Coastguard Worker const struct btf_var_secinfo *v = (const void *)(t + 1);
353*858ea5e5SAndroid Build Coastguard Worker const struct btf_type *vt;
354*858ea5e5SAndroid Build Coastguard Worker __u16 vlen = BTF_INFO_VLEN(t->info);
355*858ea5e5SAndroid Build Coastguard Worker int i;
356*858ea5e5SAndroid Build Coastguard Worker
357*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
358*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "size", t->size);
359*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "vlen", vlen);
360*858ea5e5SAndroid Build Coastguard Worker jsonw_name(w, "vars");
361*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(w);
362*858ea5e5SAndroid Build Coastguard Worker } else {
363*858ea5e5SAndroid Build Coastguard Worker printf(" size=%u vlen=%u", t->size, vlen);
364*858ea5e5SAndroid Build Coastguard Worker }
365*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < vlen; i++, v++) {
366*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
367*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(w);
368*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "type_id", v->type);
369*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "offset", v->offset);
370*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "size", v->size);
371*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(w);
372*858ea5e5SAndroid Build Coastguard Worker } else {
373*858ea5e5SAndroid Build Coastguard Worker printf("\n\ttype_id=%u offset=%u size=%u",
374*858ea5e5SAndroid Build Coastguard Worker v->type, v->offset, v->size);
375*858ea5e5SAndroid Build Coastguard Worker
376*858ea5e5SAndroid Build Coastguard Worker if (v->type < btf__type_cnt(btf)) {
377*858ea5e5SAndroid Build Coastguard Worker vt = btf__type_by_id(btf, v->type);
378*858ea5e5SAndroid Build Coastguard Worker printf(" (%s '%s')",
379*858ea5e5SAndroid Build Coastguard Worker btf_kind_str[btf_kind_safe(btf_kind(vt))],
380*858ea5e5SAndroid Build Coastguard Worker btf_str(btf, vt->name_off));
381*858ea5e5SAndroid Build Coastguard Worker }
382*858ea5e5SAndroid Build Coastguard Worker }
383*858ea5e5SAndroid Build Coastguard Worker }
384*858ea5e5SAndroid Build Coastguard Worker if (json_output)
385*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(w);
386*858ea5e5SAndroid Build Coastguard Worker break;
387*858ea5e5SAndroid Build Coastguard Worker }
388*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_FLOAT: {
389*858ea5e5SAndroid Build Coastguard Worker if (json_output)
390*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "size", t->size);
391*858ea5e5SAndroid Build Coastguard Worker else
392*858ea5e5SAndroid Build Coastguard Worker printf(" size=%u", t->size);
393*858ea5e5SAndroid Build Coastguard Worker break;
394*858ea5e5SAndroid Build Coastguard Worker }
395*858ea5e5SAndroid Build Coastguard Worker case BTF_KIND_DECL_TAG: {
396*858ea5e5SAndroid Build Coastguard Worker const struct btf_decl_tag *tag = (const void *)(t + 1);
397*858ea5e5SAndroid Build Coastguard Worker
398*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
399*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(w, "type_id", t->type);
400*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(w, "component_idx", tag->component_idx);
401*858ea5e5SAndroid Build Coastguard Worker } else {
402*858ea5e5SAndroid Build Coastguard Worker printf(" type_id=%u component_idx=%d", t->type, tag->component_idx);
403*858ea5e5SAndroid Build Coastguard Worker }
404*858ea5e5SAndroid Build Coastguard Worker break;
405*858ea5e5SAndroid Build Coastguard Worker }
406*858ea5e5SAndroid Build Coastguard Worker default:
407*858ea5e5SAndroid Build Coastguard Worker break;
408*858ea5e5SAndroid Build Coastguard Worker }
409*858ea5e5SAndroid Build Coastguard Worker
410*858ea5e5SAndroid Build Coastguard Worker if (json_output)
411*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
412*858ea5e5SAndroid Build Coastguard Worker else
413*858ea5e5SAndroid Build Coastguard Worker printf("\n");
414*858ea5e5SAndroid Build Coastguard Worker
415*858ea5e5SAndroid Build Coastguard Worker return 0;
416*858ea5e5SAndroid Build Coastguard Worker }
417*858ea5e5SAndroid Build Coastguard Worker
dump_btf_raw(const struct btf * btf,__u32 * root_type_ids,int root_type_cnt)418*858ea5e5SAndroid Build Coastguard Worker static int dump_btf_raw(const struct btf *btf,
419*858ea5e5SAndroid Build Coastguard Worker __u32 *root_type_ids, int root_type_cnt)
420*858ea5e5SAndroid Build Coastguard Worker {
421*858ea5e5SAndroid Build Coastguard Worker const struct btf_type *t;
422*858ea5e5SAndroid Build Coastguard Worker int i;
423*858ea5e5SAndroid Build Coastguard Worker
424*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
425*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
426*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "types");
427*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
428*858ea5e5SAndroid Build Coastguard Worker }
429*858ea5e5SAndroid Build Coastguard Worker
430*858ea5e5SAndroid Build Coastguard Worker if (root_type_cnt) {
431*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < root_type_cnt; i++) {
432*858ea5e5SAndroid Build Coastguard Worker t = btf__type_by_id(btf, root_type_ids[i]);
433*858ea5e5SAndroid Build Coastguard Worker dump_btf_type(btf, root_type_ids[i], t);
434*858ea5e5SAndroid Build Coastguard Worker }
435*858ea5e5SAndroid Build Coastguard Worker } else {
436*858ea5e5SAndroid Build Coastguard Worker const struct btf *base;
437*858ea5e5SAndroid Build Coastguard Worker int cnt = btf__type_cnt(btf);
438*858ea5e5SAndroid Build Coastguard Worker int start_id = 1;
439*858ea5e5SAndroid Build Coastguard Worker
440*858ea5e5SAndroid Build Coastguard Worker base = btf__base_btf(btf);
441*858ea5e5SAndroid Build Coastguard Worker if (base)
442*858ea5e5SAndroid Build Coastguard Worker start_id = btf__type_cnt(base);
443*858ea5e5SAndroid Build Coastguard Worker
444*858ea5e5SAndroid Build Coastguard Worker for (i = start_id; i < cnt; i++) {
445*858ea5e5SAndroid Build Coastguard Worker t = btf__type_by_id(btf, i);
446*858ea5e5SAndroid Build Coastguard Worker dump_btf_type(btf, i, t);
447*858ea5e5SAndroid Build Coastguard Worker }
448*858ea5e5SAndroid Build Coastguard Worker }
449*858ea5e5SAndroid Build Coastguard Worker
450*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
451*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
452*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
453*858ea5e5SAndroid Build Coastguard Worker }
454*858ea5e5SAndroid Build Coastguard Worker return 0;
455*858ea5e5SAndroid Build Coastguard Worker }
456*858ea5e5SAndroid Build Coastguard Worker
btf_dump_printf(void * ctx,const char * fmt,va_list args)457*858ea5e5SAndroid Build Coastguard Worker static void __printf(2, 0) btf_dump_printf(void *ctx,
458*858ea5e5SAndroid Build Coastguard Worker const char *fmt, va_list args)
459*858ea5e5SAndroid Build Coastguard Worker {
460*858ea5e5SAndroid Build Coastguard Worker vfprintf(stdout, fmt, args);
461*858ea5e5SAndroid Build Coastguard Worker }
462*858ea5e5SAndroid Build Coastguard Worker
dump_btf_c(const struct btf * btf,__u32 * root_type_ids,int root_type_cnt)463*858ea5e5SAndroid Build Coastguard Worker static int dump_btf_c(const struct btf *btf,
464*858ea5e5SAndroid Build Coastguard Worker __u32 *root_type_ids, int root_type_cnt)
465*858ea5e5SAndroid Build Coastguard Worker {
466*858ea5e5SAndroid Build Coastguard Worker struct btf_dump *d;
467*858ea5e5SAndroid Build Coastguard Worker int err = 0, i;
468*858ea5e5SAndroid Build Coastguard Worker
469*858ea5e5SAndroid Build Coastguard Worker d = btf_dump__new(btf, btf_dump_printf, NULL, NULL);
470*858ea5e5SAndroid Build Coastguard Worker if (!d)
471*858ea5e5SAndroid Build Coastguard Worker return -errno;
472*858ea5e5SAndroid Build Coastguard Worker
473*858ea5e5SAndroid Build Coastguard Worker printf("#ifndef __VMLINUX_H__\n");
474*858ea5e5SAndroid Build Coastguard Worker printf("#define __VMLINUX_H__\n");
475*858ea5e5SAndroid Build Coastguard Worker printf("\n");
476*858ea5e5SAndroid Build Coastguard Worker printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
477*858ea5e5SAndroid Build Coastguard Worker printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n");
478*858ea5e5SAndroid Build Coastguard Worker printf("#endif\n\n");
479*858ea5e5SAndroid Build Coastguard Worker
480*858ea5e5SAndroid Build Coastguard Worker if (root_type_cnt) {
481*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < root_type_cnt; i++) {
482*858ea5e5SAndroid Build Coastguard Worker err = btf_dump__dump_type(d, root_type_ids[i]);
483*858ea5e5SAndroid Build Coastguard Worker if (err)
484*858ea5e5SAndroid Build Coastguard Worker goto done;
485*858ea5e5SAndroid Build Coastguard Worker }
486*858ea5e5SAndroid Build Coastguard Worker } else {
487*858ea5e5SAndroid Build Coastguard Worker int cnt = btf__type_cnt(btf);
488*858ea5e5SAndroid Build Coastguard Worker
489*858ea5e5SAndroid Build Coastguard Worker for (i = 1; i < cnt; i++) {
490*858ea5e5SAndroid Build Coastguard Worker err = btf_dump__dump_type(d, i);
491*858ea5e5SAndroid Build Coastguard Worker if (err)
492*858ea5e5SAndroid Build Coastguard Worker goto done;
493*858ea5e5SAndroid Build Coastguard Worker }
494*858ea5e5SAndroid Build Coastguard Worker }
495*858ea5e5SAndroid Build Coastguard Worker
496*858ea5e5SAndroid Build Coastguard Worker printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
497*858ea5e5SAndroid Build Coastguard Worker printf("#pragma clang attribute pop\n");
498*858ea5e5SAndroid Build Coastguard Worker printf("#endif\n");
499*858ea5e5SAndroid Build Coastguard Worker printf("\n");
500*858ea5e5SAndroid Build Coastguard Worker printf("#endif /* __VMLINUX_H__ */\n");
501*858ea5e5SAndroid Build Coastguard Worker
502*858ea5e5SAndroid Build Coastguard Worker done:
503*858ea5e5SAndroid Build Coastguard Worker btf_dump__free(d);
504*858ea5e5SAndroid Build Coastguard Worker return err;
505*858ea5e5SAndroid Build Coastguard Worker }
506*858ea5e5SAndroid Build Coastguard Worker
507*858ea5e5SAndroid Build Coastguard Worker static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
508*858ea5e5SAndroid Build Coastguard Worker
get_vmlinux_btf_from_sysfs(void)509*858ea5e5SAndroid Build Coastguard Worker static struct btf *get_vmlinux_btf_from_sysfs(void)
510*858ea5e5SAndroid Build Coastguard Worker {
511*858ea5e5SAndroid Build Coastguard Worker struct btf *base;
512*858ea5e5SAndroid Build Coastguard Worker
513*858ea5e5SAndroid Build Coastguard Worker base = btf__parse(sysfs_vmlinux, NULL);
514*858ea5e5SAndroid Build Coastguard Worker if (!base)
515*858ea5e5SAndroid Build Coastguard Worker p_err("failed to parse vmlinux BTF at '%s': %d\n",
516*858ea5e5SAndroid Build Coastguard Worker sysfs_vmlinux, -errno);
517*858ea5e5SAndroid Build Coastguard Worker
518*858ea5e5SAndroid Build Coastguard Worker return base;
519*858ea5e5SAndroid Build Coastguard Worker }
520*858ea5e5SAndroid Build Coastguard Worker
521*858ea5e5SAndroid Build Coastguard Worker #define BTF_NAME_BUFF_LEN 64
522*858ea5e5SAndroid Build Coastguard Worker
btf_is_kernel_module(__u32 btf_id)523*858ea5e5SAndroid Build Coastguard Worker static bool btf_is_kernel_module(__u32 btf_id)
524*858ea5e5SAndroid Build Coastguard Worker {
525*858ea5e5SAndroid Build Coastguard Worker struct bpf_btf_info btf_info = {};
526*858ea5e5SAndroid Build Coastguard Worker char btf_name[BTF_NAME_BUFF_LEN];
527*858ea5e5SAndroid Build Coastguard Worker int btf_fd;
528*858ea5e5SAndroid Build Coastguard Worker __u32 len;
529*858ea5e5SAndroid Build Coastguard Worker int err;
530*858ea5e5SAndroid Build Coastguard Worker
531*858ea5e5SAndroid Build Coastguard Worker btf_fd = bpf_btf_get_fd_by_id(btf_id);
532*858ea5e5SAndroid Build Coastguard Worker if (btf_fd < 0) {
533*858ea5e5SAndroid Build Coastguard Worker p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno));
534*858ea5e5SAndroid Build Coastguard Worker return false;
535*858ea5e5SAndroid Build Coastguard Worker }
536*858ea5e5SAndroid Build Coastguard Worker
537*858ea5e5SAndroid Build Coastguard Worker len = sizeof(btf_info);
538*858ea5e5SAndroid Build Coastguard Worker btf_info.name = ptr_to_u64(btf_name);
539*858ea5e5SAndroid Build Coastguard Worker btf_info.name_len = sizeof(btf_name);
540*858ea5e5SAndroid Build Coastguard Worker err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len);
541*858ea5e5SAndroid Build Coastguard Worker close(btf_fd);
542*858ea5e5SAndroid Build Coastguard Worker if (err) {
543*858ea5e5SAndroid Build Coastguard Worker p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno));
544*858ea5e5SAndroid Build Coastguard Worker return false;
545*858ea5e5SAndroid Build Coastguard Worker }
546*858ea5e5SAndroid Build Coastguard Worker
547*858ea5e5SAndroid Build Coastguard Worker return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0;
548*858ea5e5SAndroid Build Coastguard Worker }
549*858ea5e5SAndroid Build Coastguard Worker
do_dump(int argc,char ** argv)550*858ea5e5SAndroid Build Coastguard Worker static int do_dump(int argc, char **argv)
551*858ea5e5SAndroid Build Coastguard Worker {
552*858ea5e5SAndroid Build Coastguard Worker struct btf *btf = NULL, *base = NULL;
553*858ea5e5SAndroid Build Coastguard Worker __u32 root_type_ids[2];
554*858ea5e5SAndroid Build Coastguard Worker int root_type_cnt = 0;
555*858ea5e5SAndroid Build Coastguard Worker bool dump_c = false;
556*858ea5e5SAndroid Build Coastguard Worker __u32 btf_id = -1;
557*858ea5e5SAndroid Build Coastguard Worker const char *src;
558*858ea5e5SAndroid Build Coastguard Worker int fd = -1;
559*858ea5e5SAndroid Build Coastguard Worker int err = 0;
560*858ea5e5SAndroid Build Coastguard Worker
561*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(2)) {
562*858ea5e5SAndroid Build Coastguard Worker usage();
563*858ea5e5SAndroid Build Coastguard Worker return -1;
564*858ea5e5SAndroid Build Coastguard Worker }
565*858ea5e5SAndroid Build Coastguard Worker src = GET_ARG();
566*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(src, "map")) {
567*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
568*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
569*858ea5e5SAndroid Build Coastguard Worker
570*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(2)) {
571*858ea5e5SAndroid Build Coastguard Worker usage();
572*858ea5e5SAndroid Build Coastguard Worker return -1;
573*858ea5e5SAndroid Build Coastguard Worker }
574*858ea5e5SAndroid Build Coastguard Worker
575*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
576*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
577*858ea5e5SAndroid Build Coastguard Worker return -1;
578*858ea5e5SAndroid Build Coastguard Worker
579*858ea5e5SAndroid Build Coastguard Worker btf_id = info.btf_id;
580*858ea5e5SAndroid Build Coastguard Worker if (argc && is_prefix(*argv, "key")) {
581*858ea5e5SAndroid Build Coastguard Worker root_type_ids[root_type_cnt++] = info.btf_key_type_id;
582*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
583*858ea5e5SAndroid Build Coastguard Worker } else if (argc && is_prefix(*argv, "value")) {
584*858ea5e5SAndroid Build Coastguard Worker root_type_ids[root_type_cnt++] = info.btf_value_type_id;
585*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
586*858ea5e5SAndroid Build Coastguard Worker } else if (argc && is_prefix(*argv, "all")) {
587*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
588*858ea5e5SAndroid Build Coastguard Worker } else if (argc && is_prefix(*argv, "kv")) {
589*858ea5e5SAndroid Build Coastguard Worker root_type_ids[root_type_cnt++] = info.btf_key_type_id;
590*858ea5e5SAndroid Build Coastguard Worker root_type_ids[root_type_cnt++] = info.btf_value_type_id;
591*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
592*858ea5e5SAndroid Build Coastguard Worker } else {
593*858ea5e5SAndroid Build Coastguard Worker root_type_ids[root_type_cnt++] = info.btf_key_type_id;
594*858ea5e5SAndroid Build Coastguard Worker root_type_ids[root_type_cnt++] = info.btf_value_type_id;
595*858ea5e5SAndroid Build Coastguard Worker }
596*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(src, "prog")) {
597*858ea5e5SAndroid Build Coastguard Worker struct bpf_prog_info info = {};
598*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
599*858ea5e5SAndroid Build Coastguard Worker
600*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(2)) {
601*858ea5e5SAndroid Build Coastguard Worker usage();
602*858ea5e5SAndroid Build Coastguard Worker return -1;
603*858ea5e5SAndroid Build Coastguard Worker }
604*858ea5e5SAndroid Build Coastguard Worker
605*858ea5e5SAndroid Build Coastguard Worker fd = prog_parse_fd(&argc, &argv);
606*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
607*858ea5e5SAndroid Build Coastguard Worker return -1;
608*858ea5e5SAndroid Build Coastguard Worker
609*858ea5e5SAndroid Build Coastguard Worker err = bpf_prog_get_info_by_fd(fd, &info, &len);
610*858ea5e5SAndroid Build Coastguard Worker if (err) {
611*858ea5e5SAndroid Build Coastguard Worker p_err("can't get prog info: %s", strerror(errno));
612*858ea5e5SAndroid Build Coastguard Worker goto done;
613*858ea5e5SAndroid Build Coastguard Worker }
614*858ea5e5SAndroid Build Coastguard Worker
615*858ea5e5SAndroid Build Coastguard Worker btf_id = info.btf_id;
616*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(src, "id")) {
617*858ea5e5SAndroid Build Coastguard Worker char *endptr;
618*858ea5e5SAndroid Build Coastguard Worker
619*858ea5e5SAndroid Build Coastguard Worker btf_id = strtoul(*argv, &endptr, 0);
620*858ea5e5SAndroid Build Coastguard Worker if (*endptr) {
621*858ea5e5SAndroid Build Coastguard Worker p_err("can't parse %s as ID", *argv);
622*858ea5e5SAndroid Build Coastguard Worker return -1;
623*858ea5e5SAndroid Build Coastguard Worker }
624*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
625*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(src, "file")) {
626*858ea5e5SAndroid Build Coastguard Worker const char sysfs_prefix[] = "/sys/kernel/btf/";
627*858ea5e5SAndroid Build Coastguard Worker
628*858ea5e5SAndroid Build Coastguard Worker if (!base_btf &&
629*858ea5e5SAndroid Build Coastguard Worker strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 &&
630*858ea5e5SAndroid Build Coastguard Worker strcmp(*argv, sysfs_vmlinux) != 0)
631*858ea5e5SAndroid Build Coastguard Worker base = get_vmlinux_btf_from_sysfs();
632*858ea5e5SAndroid Build Coastguard Worker
633*858ea5e5SAndroid Build Coastguard Worker btf = btf__parse_split(*argv, base ?: base_btf);
634*858ea5e5SAndroid Build Coastguard Worker if (!btf) {
635*858ea5e5SAndroid Build Coastguard Worker err = -errno;
636*858ea5e5SAndroid Build Coastguard Worker p_err("failed to load BTF from %s: %s",
637*858ea5e5SAndroid Build Coastguard Worker *argv, strerror(errno));
638*858ea5e5SAndroid Build Coastguard Worker goto done;
639*858ea5e5SAndroid Build Coastguard Worker }
640*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
641*858ea5e5SAndroid Build Coastguard Worker } else {
642*858ea5e5SAndroid Build Coastguard Worker err = -1;
643*858ea5e5SAndroid Build Coastguard Worker p_err("unrecognized BTF source specifier: '%s'", src);
644*858ea5e5SAndroid Build Coastguard Worker goto done;
645*858ea5e5SAndroid Build Coastguard Worker }
646*858ea5e5SAndroid Build Coastguard Worker
647*858ea5e5SAndroid Build Coastguard Worker while (argc) {
648*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(*argv, "format")) {
649*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
650*858ea5e5SAndroid Build Coastguard Worker if (argc < 1) {
651*858ea5e5SAndroid Build Coastguard Worker p_err("expecting value for 'format' option\n");
652*858ea5e5SAndroid Build Coastguard Worker err = -EINVAL;
653*858ea5e5SAndroid Build Coastguard Worker goto done;
654*858ea5e5SAndroid Build Coastguard Worker }
655*858ea5e5SAndroid Build Coastguard Worker if (strcmp(*argv, "c") == 0) {
656*858ea5e5SAndroid Build Coastguard Worker dump_c = true;
657*858ea5e5SAndroid Build Coastguard Worker } else if (strcmp(*argv, "raw") == 0) {
658*858ea5e5SAndroid Build Coastguard Worker dump_c = false;
659*858ea5e5SAndroid Build Coastguard Worker } else {
660*858ea5e5SAndroid Build Coastguard Worker p_err("unrecognized format specifier: '%s', possible values: raw, c",
661*858ea5e5SAndroid Build Coastguard Worker *argv);
662*858ea5e5SAndroid Build Coastguard Worker err = -EINVAL;
663*858ea5e5SAndroid Build Coastguard Worker goto done;
664*858ea5e5SAndroid Build Coastguard Worker }
665*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
666*858ea5e5SAndroid Build Coastguard Worker } else {
667*858ea5e5SAndroid Build Coastguard Worker p_err("unrecognized option: '%s'", *argv);
668*858ea5e5SAndroid Build Coastguard Worker err = -EINVAL;
669*858ea5e5SAndroid Build Coastguard Worker goto done;
670*858ea5e5SAndroid Build Coastguard Worker }
671*858ea5e5SAndroid Build Coastguard Worker }
672*858ea5e5SAndroid Build Coastguard Worker
673*858ea5e5SAndroid Build Coastguard Worker if (!btf) {
674*858ea5e5SAndroid Build Coastguard Worker if (!base_btf && btf_is_kernel_module(btf_id)) {
675*858ea5e5SAndroid Build Coastguard Worker p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)",
676*858ea5e5SAndroid Build Coastguard Worker sysfs_vmlinux);
677*858ea5e5SAndroid Build Coastguard Worker base_btf = get_vmlinux_btf_from_sysfs();
678*858ea5e5SAndroid Build Coastguard Worker }
679*858ea5e5SAndroid Build Coastguard Worker
680*858ea5e5SAndroid Build Coastguard Worker btf = btf__load_from_kernel_by_id_split(btf_id, base_btf);
681*858ea5e5SAndroid Build Coastguard Worker if (!btf) {
682*858ea5e5SAndroid Build Coastguard Worker err = -errno;
683*858ea5e5SAndroid Build Coastguard Worker p_err("get btf by id (%u): %s", btf_id, strerror(errno));
684*858ea5e5SAndroid Build Coastguard Worker goto done;
685*858ea5e5SAndroid Build Coastguard Worker }
686*858ea5e5SAndroid Build Coastguard Worker }
687*858ea5e5SAndroid Build Coastguard Worker
688*858ea5e5SAndroid Build Coastguard Worker if (dump_c) {
689*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
690*858ea5e5SAndroid Build Coastguard Worker p_err("JSON output for C-syntax dump is not supported");
691*858ea5e5SAndroid Build Coastguard Worker err = -ENOTSUP;
692*858ea5e5SAndroid Build Coastguard Worker goto done;
693*858ea5e5SAndroid Build Coastguard Worker }
694*858ea5e5SAndroid Build Coastguard Worker err = dump_btf_c(btf, root_type_ids, root_type_cnt);
695*858ea5e5SAndroid Build Coastguard Worker } else {
696*858ea5e5SAndroid Build Coastguard Worker err = dump_btf_raw(btf, root_type_ids, root_type_cnt);
697*858ea5e5SAndroid Build Coastguard Worker }
698*858ea5e5SAndroid Build Coastguard Worker
699*858ea5e5SAndroid Build Coastguard Worker done:
700*858ea5e5SAndroid Build Coastguard Worker close(fd);
701*858ea5e5SAndroid Build Coastguard Worker btf__free(btf);
702*858ea5e5SAndroid Build Coastguard Worker btf__free(base);
703*858ea5e5SAndroid Build Coastguard Worker return err;
704*858ea5e5SAndroid Build Coastguard Worker }
705*858ea5e5SAndroid Build Coastguard Worker
btf_parse_fd(int * argc,char *** argv)706*858ea5e5SAndroid Build Coastguard Worker static int btf_parse_fd(int *argc, char ***argv)
707*858ea5e5SAndroid Build Coastguard Worker {
708*858ea5e5SAndroid Build Coastguard Worker unsigned int id;
709*858ea5e5SAndroid Build Coastguard Worker char *endptr;
710*858ea5e5SAndroid Build Coastguard Worker int fd;
711*858ea5e5SAndroid Build Coastguard Worker
712*858ea5e5SAndroid Build Coastguard Worker if (!is_prefix(*argv[0], "id")) {
713*858ea5e5SAndroid Build Coastguard Worker p_err("expected 'id', got: '%s'?", **argv);
714*858ea5e5SAndroid Build Coastguard Worker return -1;
715*858ea5e5SAndroid Build Coastguard Worker }
716*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
717*858ea5e5SAndroid Build Coastguard Worker
718*858ea5e5SAndroid Build Coastguard Worker id = strtoul(**argv, &endptr, 0);
719*858ea5e5SAndroid Build Coastguard Worker if (*endptr) {
720*858ea5e5SAndroid Build Coastguard Worker p_err("can't parse %s as ID", **argv);
721*858ea5e5SAndroid Build Coastguard Worker return -1;
722*858ea5e5SAndroid Build Coastguard Worker }
723*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
724*858ea5e5SAndroid Build Coastguard Worker
725*858ea5e5SAndroid Build Coastguard Worker fd = bpf_btf_get_fd_by_id(id);
726*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
727*858ea5e5SAndroid Build Coastguard Worker p_err("can't get BTF object by id (%u): %s",
728*858ea5e5SAndroid Build Coastguard Worker id, strerror(errno));
729*858ea5e5SAndroid Build Coastguard Worker
730*858ea5e5SAndroid Build Coastguard Worker return fd;
731*858ea5e5SAndroid Build Coastguard Worker }
732*858ea5e5SAndroid Build Coastguard Worker
733*858ea5e5SAndroid Build Coastguard Worker static int
build_btf_type_table(struct hashmap * tab,enum bpf_obj_type type,void * info,__u32 * len)734*858ea5e5SAndroid Build Coastguard Worker build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
735*858ea5e5SAndroid Build Coastguard Worker void *info, __u32 *len)
736*858ea5e5SAndroid Build Coastguard Worker {
737*858ea5e5SAndroid Build Coastguard Worker static const char * const names[] = {
738*858ea5e5SAndroid Build Coastguard Worker [BPF_OBJ_UNKNOWN] = "unknown",
739*858ea5e5SAndroid Build Coastguard Worker [BPF_OBJ_PROG] = "prog",
740*858ea5e5SAndroid Build Coastguard Worker [BPF_OBJ_MAP] = "map",
741*858ea5e5SAndroid Build Coastguard Worker };
742*858ea5e5SAndroid Build Coastguard Worker __u32 btf_id, id = 0;
743*858ea5e5SAndroid Build Coastguard Worker int err;
744*858ea5e5SAndroid Build Coastguard Worker int fd;
745*858ea5e5SAndroid Build Coastguard Worker
746*858ea5e5SAndroid Build Coastguard Worker while (true) {
747*858ea5e5SAndroid Build Coastguard Worker switch (type) {
748*858ea5e5SAndroid Build Coastguard Worker case BPF_OBJ_PROG:
749*858ea5e5SAndroid Build Coastguard Worker err = bpf_prog_get_next_id(id, &id);
750*858ea5e5SAndroid Build Coastguard Worker break;
751*858ea5e5SAndroid Build Coastguard Worker case BPF_OBJ_MAP:
752*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_next_id(id, &id);
753*858ea5e5SAndroid Build Coastguard Worker break;
754*858ea5e5SAndroid Build Coastguard Worker default:
755*858ea5e5SAndroid Build Coastguard Worker err = -1;
756*858ea5e5SAndroid Build Coastguard Worker p_err("unexpected object type: %d", type);
757*858ea5e5SAndroid Build Coastguard Worker goto err_free;
758*858ea5e5SAndroid Build Coastguard Worker }
759*858ea5e5SAndroid Build Coastguard Worker if (err) {
760*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT) {
761*858ea5e5SAndroid Build Coastguard Worker err = 0;
762*858ea5e5SAndroid Build Coastguard Worker break;
763*858ea5e5SAndroid Build Coastguard Worker }
764*858ea5e5SAndroid Build Coastguard Worker p_err("can't get next %s: %s%s", names[type],
765*858ea5e5SAndroid Build Coastguard Worker strerror(errno),
766*858ea5e5SAndroid Build Coastguard Worker errno == EINVAL ? " -- kernel too old?" : "");
767*858ea5e5SAndroid Build Coastguard Worker goto err_free;
768*858ea5e5SAndroid Build Coastguard Worker }
769*858ea5e5SAndroid Build Coastguard Worker
770*858ea5e5SAndroid Build Coastguard Worker switch (type) {
771*858ea5e5SAndroid Build Coastguard Worker case BPF_OBJ_PROG:
772*858ea5e5SAndroid Build Coastguard Worker fd = bpf_prog_get_fd_by_id(id);
773*858ea5e5SAndroid Build Coastguard Worker break;
774*858ea5e5SAndroid Build Coastguard Worker case BPF_OBJ_MAP:
775*858ea5e5SAndroid Build Coastguard Worker fd = bpf_map_get_fd_by_id(id);
776*858ea5e5SAndroid Build Coastguard Worker break;
777*858ea5e5SAndroid Build Coastguard Worker default:
778*858ea5e5SAndroid Build Coastguard Worker err = -1;
779*858ea5e5SAndroid Build Coastguard Worker p_err("unexpected object type: %d", type);
780*858ea5e5SAndroid Build Coastguard Worker goto err_free;
781*858ea5e5SAndroid Build Coastguard Worker }
782*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
783*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT)
784*858ea5e5SAndroid Build Coastguard Worker continue;
785*858ea5e5SAndroid Build Coastguard Worker p_err("can't get %s by id (%u): %s", names[type], id,
786*858ea5e5SAndroid Build Coastguard Worker strerror(errno));
787*858ea5e5SAndroid Build Coastguard Worker err = -1;
788*858ea5e5SAndroid Build Coastguard Worker goto err_free;
789*858ea5e5SAndroid Build Coastguard Worker }
790*858ea5e5SAndroid Build Coastguard Worker
791*858ea5e5SAndroid Build Coastguard Worker memset(info, 0, *len);
792*858ea5e5SAndroid Build Coastguard Worker if (type == BPF_OBJ_PROG)
793*858ea5e5SAndroid Build Coastguard Worker err = bpf_prog_get_info_by_fd(fd, info, len);
794*858ea5e5SAndroid Build Coastguard Worker else
795*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_info_by_fd(fd, info, len);
796*858ea5e5SAndroid Build Coastguard Worker close(fd);
797*858ea5e5SAndroid Build Coastguard Worker if (err) {
798*858ea5e5SAndroid Build Coastguard Worker p_err("can't get %s info: %s", names[type],
799*858ea5e5SAndroid Build Coastguard Worker strerror(errno));
800*858ea5e5SAndroid Build Coastguard Worker goto err_free;
801*858ea5e5SAndroid Build Coastguard Worker }
802*858ea5e5SAndroid Build Coastguard Worker
803*858ea5e5SAndroid Build Coastguard Worker switch (type) {
804*858ea5e5SAndroid Build Coastguard Worker case BPF_OBJ_PROG:
805*858ea5e5SAndroid Build Coastguard Worker btf_id = ((struct bpf_prog_info *)info)->btf_id;
806*858ea5e5SAndroid Build Coastguard Worker break;
807*858ea5e5SAndroid Build Coastguard Worker case BPF_OBJ_MAP:
808*858ea5e5SAndroid Build Coastguard Worker btf_id = ((struct bpf_map_info *)info)->btf_id;
809*858ea5e5SAndroid Build Coastguard Worker break;
810*858ea5e5SAndroid Build Coastguard Worker default:
811*858ea5e5SAndroid Build Coastguard Worker err = -1;
812*858ea5e5SAndroid Build Coastguard Worker p_err("unexpected object type: %d", type);
813*858ea5e5SAndroid Build Coastguard Worker goto err_free;
814*858ea5e5SAndroid Build Coastguard Worker }
815*858ea5e5SAndroid Build Coastguard Worker if (!btf_id)
816*858ea5e5SAndroid Build Coastguard Worker continue;
817*858ea5e5SAndroid Build Coastguard Worker
818*858ea5e5SAndroid Build Coastguard Worker err = hashmap__append(tab, btf_id, id);
819*858ea5e5SAndroid Build Coastguard Worker if (err) {
820*858ea5e5SAndroid Build Coastguard Worker p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s",
821*858ea5e5SAndroid Build Coastguard Worker btf_id, id, strerror(-err));
822*858ea5e5SAndroid Build Coastguard Worker goto err_free;
823*858ea5e5SAndroid Build Coastguard Worker }
824*858ea5e5SAndroid Build Coastguard Worker }
825*858ea5e5SAndroid Build Coastguard Worker
826*858ea5e5SAndroid Build Coastguard Worker return 0;
827*858ea5e5SAndroid Build Coastguard Worker
828*858ea5e5SAndroid Build Coastguard Worker err_free:
829*858ea5e5SAndroid Build Coastguard Worker hashmap__free(tab);
830*858ea5e5SAndroid Build Coastguard Worker return err;
831*858ea5e5SAndroid Build Coastguard Worker }
832*858ea5e5SAndroid Build Coastguard Worker
833*858ea5e5SAndroid Build Coastguard Worker static int
build_btf_tables(struct hashmap * btf_prog_table,struct hashmap * btf_map_table)834*858ea5e5SAndroid Build Coastguard Worker build_btf_tables(struct hashmap *btf_prog_table,
835*858ea5e5SAndroid Build Coastguard Worker struct hashmap *btf_map_table)
836*858ea5e5SAndroid Build Coastguard Worker {
837*858ea5e5SAndroid Build Coastguard Worker struct bpf_prog_info prog_info;
838*858ea5e5SAndroid Build Coastguard Worker __u32 prog_len = sizeof(prog_info);
839*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info map_info;
840*858ea5e5SAndroid Build Coastguard Worker __u32 map_len = sizeof(map_info);
841*858ea5e5SAndroid Build Coastguard Worker int err = 0;
842*858ea5e5SAndroid Build Coastguard Worker
843*858ea5e5SAndroid Build Coastguard Worker err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info,
844*858ea5e5SAndroid Build Coastguard Worker &prog_len);
845*858ea5e5SAndroid Build Coastguard Worker if (err)
846*858ea5e5SAndroid Build Coastguard Worker return err;
847*858ea5e5SAndroid Build Coastguard Worker
848*858ea5e5SAndroid Build Coastguard Worker err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info,
849*858ea5e5SAndroid Build Coastguard Worker &map_len);
850*858ea5e5SAndroid Build Coastguard Worker if (err) {
851*858ea5e5SAndroid Build Coastguard Worker hashmap__free(btf_prog_table);
852*858ea5e5SAndroid Build Coastguard Worker return err;
853*858ea5e5SAndroid Build Coastguard Worker }
854*858ea5e5SAndroid Build Coastguard Worker
855*858ea5e5SAndroid Build Coastguard Worker return 0;
856*858ea5e5SAndroid Build Coastguard Worker }
857*858ea5e5SAndroid Build Coastguard Worker
858*858ea5e5SAndroid Build Coastguard Worker static void
show_btf_plain(struct bpf_btf_info * info,int fd,struct hashmap * btf_prog_table,struct hashmap * btf_map_table)859*858ea5e5SAndroid Build Coastguard Worker show_btf_plain(struct bpf_btf_info *info, int fd,
860*858ea5e5SAndroid Build Coastguard Worker struct hashmap *btf_prog_table,
861*858ea5e5SAndroid Build Coastguard Worker struct hashmap *btf_map_table)
862*858ea5e5SAndroid Build Coastguard Worker {
863*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
864*858ea5e5SAndroid Build Coastguard Worker const char *name = u64_to_ptr(info->name);
865*858ea5e5SAndroid Build Coastguard Worker int n;
866*858ea5e5SAndroid Build Coastguard Worker
867*858ea5e5SAndroid Build Coastguard Worker printf("%u: ", info->id);
868*858ea5e5SAndroid Build Coastguard Worker if (info->kernel_btf)
869*858ea5e5SAndroid Build Coastguard Worker printf("name [%s] ", name);
870*858ea5e5SAndroid Build Coastguard Worker else if (name && name[0])
871*858ea5e5SAndroid Build Coastguard Worker printf("name %s ", name);
872*858ea5e5SAndroid Build Coastguard Worker else
873*858ea5e5SAndroid Build Coastguard Worker printf("name <anon> ");
874*858ea5e5SAndroid Build Coastguard Worker printf("size %uB", info->btf_size);
875*858ea5e5SAndroid Build Coastguard Worker
876*858ea5e5SAndroid Build Coastguard Worker n = 0;
877*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
878*858ea5e5SAndroid Build Coastguard Worker printf("%s%lu", n++ == 0 ? " prog_ids " : ",", entry->value);
879*858ea5e5SAndroid Build Coastguard Worker }
880*858ea5e5SAndroid Build Coastguard Worker
881*858ea5e5SAndroid Build Coastguard Worker n = 0;
882*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
883*858ea5e5SAndroid Build Coastguard Worker printf("%s%lu", n++ == 0 ? " map_ids " : ",", entry->value);
884*858ea5e5SAndroid Build Coastguard Worker }
885*858ea5e5SAndroid Build Coastguard Worker
886*858ea5e5SAndroid Build Coastguard Worker emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
887*858ea5e5SAndroid Build Coastguard Worker
888*858ea5e5SAndroid Build Coastguard Worker printf("\n");
889*858ea5e5SAndroid Build Coastguard Worker }
890*858ea5e5SAndroid Build Coastguard Worker
891*858ea5e5SAndroid Build Coastguard Worker static void
show_btf_json(struct bpf_btf_info * info,int fd,struct hashmap * btf_prog_table,struct hashmap * btf_map_table)892*858ea5e5SAndroid Build Coastguard Worker show_btf_json(struct bpf_btf_info *info, int fd,
893*858ea5e5SAndroid Build Coastguard Worker struct hashmap *btf_prog_table,
894*858ea5e5SAndroid Build Coastguard Worker struct hashmap *btf_map_table)
895*858ea5e5SAndroid Build Coastguard Worker {
896*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
897*858ea5e5SAndroid Build Coastguard Worker const char *name = u64_to_ptr(info->name);
898*858ea5e5SAndroid Build Coastguard Worker
899*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr); /* btf object */
900*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "id", info->id);
901*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "size", info->btf_size);
902*858ea5e5SAndroid Build Coastguard Worker
903*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "prog_ids");
904*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr); /* prog_ids */
905*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
906*858ea5e5SAndroid Build Coastguard Worker jsonw_uint(json_wtr, entry->value);
907*858ea5e5SAndroid Build Coastguard Worker }
908*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr); /* prog_ids */
909*858ea5e5SAndroid Build Coastguard Worker
910*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "map_ids");
911*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr); /* map_ids */
912*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
913*858ea5e5SAndroid Build Coastguard Worker jsonw_uint(json_wtr, entry->value);
914*858ea5e5SAndroid Build Coastguard Worker }
915*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr); /* map_ids */
916*858ea5e5SAndroid Build Coastguard Worker
917*858ea5e5SAndroid Build Coastguard Worker emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */
918*858ea5e5SAndroid Build Coastguard Worker
919*858ea5e5SAndroid Build Coastguard Worker jsonw_bool_field(json_wtr, "kernel", info->kernel_btf);
920*858ea5e5SAndroid Build Coastguard Worker
921*858ea5e5SAndroid Build Coastguard Worker if (name && name[0])
922*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "name", name);
923*858ea5e5SAndroid Build Coastguard Worker
924*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr); /* btf object */
925*858ea5e5SAndroid Build Coastguard Worker }
926*858ea5e5SAndroid Build Coastguard Worker
927*858ea5e5SAndroid Build Coastguard Worker static int
show_btf(int fd,struct hashmap * btf_prog_table,struct hashmap * btf_map_table)928*858ea5e5SAndroid Build Coastguard Worker show_btf(int fd, struct hashmap *btf_prog_table,
929*858ea5e5SAndroid Build Coastguard Worker struct hashmap *btf_map_table)
930*858ea5e5SAndroid Build Coastguard Worker {
931*858ea5e5SAndroid Build Coastguard Worker struct bpf_btf_info info;
932*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
933*858ea5e5SAndroid Build Coastguard Worker char name[64];
934*858ea5e5SAndroid Build Coastguard Worker int err;
935*858ea5e5SAndroid Build Coastguard Worker
936*858ea5e5SAndroid Build Coastguard Worker memset(&info, 0, sizeof(info));
937*858ea5e5SAndroid Build Coastguard Worker err = bpf_btf_get_info_by_fd(fd, &info, &len);
938*858ea5e5SAndroid Build Coastguard Worker if (err) {
939*858ea5e5SAndroid Build Coastguard Worker p_err("can't get BTF object info: %s", strerror(errno));
940*858ea5e5SAndroid Build Coastguard Worker return -1;
941*858ea5e5SAndroid Build Coastguard Worker }
942*858ea5e5SAndroid Build Coastguard Worker /* if kernel support emitting BTF object name, pass name pointer */
943*858ea5e5SAndroid Build Coastguard Worker if (info.name_len) {
944*858ea5e5SAndroid Build Coastguard Worker memset(&info, 0, sizeof(info));
945*858ea5e5SAndroid Build Coastguard Worker info.name_len = sizeof(name);
946*858ea5e5SAndroid Build Coastguard Worker info.name = ptr_to_u64(name);
947*858ea5e5SAndroid Build Coastguard Worker len = sizeof(info);
948*858ea5e5SAndroid Build Coastguard Worker
949*858ea5e5SAndroid Build Coastguard Worker err = bpf_btf_get_info_by_fd(fd, &info, &len);
950*858ea5e5SAndroid Build Coastguard Worker if (err) {
951*858ea5e5SAndroid Build Coastguard Worker p_err("can't get BTF object info: %s", strerror(errno));
952*858ea5e5SAndroid Build Coastguard Worker return -1;
953*858ea5e5SAndroid Build Coastguard Worker }
954*858ea5e5SAndroid Build Coastguard Worker }
955*858ea5e5SAndroid Build Coastguard Worker
956*858ea5e5SAndroid Build Coastguard Worker if (json_output)
957*858ea5e5SAndroid Build Coastguard Worker show_btf_json(&info, fd, btf_prog_table, btf_map_table);
958*858ea5e5SAndroid Build Coastguard Worker else
959*858ea5e5SAndroid Build Coastguard Worker show_btf_plain(&info, fd, btf_prog_table, btf_map_table);
960*858ea5e5SAndroid Build Coastguard Worker
961*858ea5e5SAndroid Build Coastguard Worker return 0;
962*858ea5e5SAndroid Build Coastguard Worker }
963*858ea5e5SAndroid Build Coastguard Worker
do_show(int argc,char ** argv)964*858ea5e5SAndroid Build Coastguard Worker static int do_show(int argc, char **argv)
965*858ea5e5SAndroid Build Coastguard Worker {
966*858ea5e5SAndroid Build Coastguard Worker struct hashmap *btf_prog_table;
967*858ea5e5SAndroid Build Coastguard Worker struct hashmap *btf_map_table;
968*858ea5e5SAndroid Build Coastguard Worker int err, fd = -1;
969*858ea5e5SAndroid Build Coastguard Worker __u32 id = 0;
970*858ea5e5SAndroid Build Coastguard Worker
971*858ea5e5SAndroid Build Coastguard Worker if (argc == 2) {
972*858ea5e5SAndroid Build Coastguard Worker fd = btf_parse_fd(&argc, &argv);
973*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
974*858ea5e5SAndroid Build Coastguard Worker return -1;
975*858ea5e5SAndroid Build Coastguard Worker }
976*858ea5e5SAndroid Build Coastguard Worker
977*858ea5e5SAndroid Build Coastguard Worker if (argc) {
978*858ea5e5SAndroid Build Coastguard Worker if (fd >= 0)
979*858ea5e5SAndroid Build Coastguard Worker close(fd);
980*858ea5e5SAndroid Build Coastguard Worker return BAD_ARG();
981*858ea5e5SAndroid Build Coastguard Worker }
982*858ea5e5SAndroid Build Coastguard Worker
983*858ea5e5SAndroid Build Coastguard Worker btf_prog_table = hashmap__new(hash_fn_for_key_as_id,
984*858ea5e5SAndroid Build Coastguard Worker equal_fn_for_key_as_id, NULL);
985*858ea5e5SAndroid Build Coastguard Worker btf_map_table = hashmap__new(hash_fn_for_key_as_id,
986*858ea5e5SAndroid Build Coastguard Worker equal_fn_for_key_as_id, NULL);
987*858ea5e5SAndroid Build Coastguard Worker if (IS_ERR(btf_prog_table) || IS_ERR(btf_map_table)) {
988*858ea5e5SAndroid Build Coastguard Worker hashmap__free(btf_prog_table);
989*858ea5e5SAndroid Build Coastguard Worker hashmap__free(btf_map_table);
990*858ea5e5SAndroid Build Coastguard Worker if (fd >= 0)
991*858ea5e5SAndroid Build Coastguard Worker close(fd);
992*858ea5e5SAndroid Build Coastguard Worker p_err("failed to create hashmap for object references");
993*858ea5e5SAndroid Build Coastguard Worker return -1;
994*858ea5e5SAndroid Build Coastguard Worker }
995*858ea5e5SAndroid Build Coastguard Worker err = build_btf_tables(btf_prog_table, btf_map_table);
996*858ea5e5SAndroid Build Coastguard Worker if (err) {
997*858ea5e5SAndroid Build Coastguard Worker if (fd >= 0)
998*858ea5e5SAndroid Build Coastguard Worker close(fd);
999*858ea5e5SAndroid Build Coastguard Worker return err;
1000*858ea5e5SAndroid Build Coastguard Worker }
1001*858ea5e5SAndroid Build Coastguard Worker build_obj_refs_table(&refs_table, BPF_OBJ_BTF);
1002*858ea5e5SAndroid Build Coastguard Worker
1003*858ea5e5SAndroid Build Coastguard Worker if (fd >= 0) {
1004*858ea5e5SAndroid Build Coastguard Worker err = show_btf(fd, btf_prog_table, btf_map_table);
1005*858ea5e5SAndroid Build Coastguard Worker close(fd);
1006*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1007*858ea5e5SAndroid Build Coastguard Worker }
1008*858ea5e5SAndroid Build Coastguard Worker
1009*858ea5e5SAndroid Build Coastguard Worker if (json_output)
1010*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr); /* root array */
1011*858ea5e5SAndroid Build Coastguard Worker
1012*858ea5e5SAndroid Build Coastguard Worker while (true) {
1013*858ea5e5SAndroid Build Coastguard Worker err = bpf_btf_get_next_id(id, &id);
1014*858ea5e5SAndroid Build Coastguard Worker if (err) {
1015*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT) {
1016*858ea5e5SAndroid Build Coastguard Worker err = 0;
1017*858ea5e5SAndroid Build Coastguard Worker break;
1018*858ea5e5SAndroid Build Coastguard Worker }
1019*858ea5e5SAndroid Build Coastguard Worker p_err("can't get next BTF object: %s%s",
1020*858ea5e5SAndroid Build Coastguard Worker strerror(errno),
1021*858ea5e5SAndroid Build Coastguard Worker errno == EINVAL ? " -- kernel too old?" : "");
1022*858ea5e5SAndroid Build Coastguard Worker err = -1;
1023*858ea5e5SAndroid Build Coastguard Worker break;
1024*858ea5e5SAndroid Build Coastguard Worker }
1025*858ea5e5SAndroid Build Coastguard Worker
1026*858ea5e5SAndroid Build Coastguard Worker fd = bpf_btf_get_fd_by_id(id);
1027*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
1028*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT)
1029*858ea5e5SAndroid Build Coastguard Worker continue;
1030*858ea5e5SAndroid Build Coastguard Worker p_err("can't get BTF object by id (%u): %s",
1031*858ea5e5SAndroid Build Coastguard Worker id, strerror(errno));
1032*858ea5e5SAndroid Build Coastguard Worker err = -1;
1033*858ea5e5SAndroid Build Coastguard Worker break;
1034*858ea5e5SAndroid Build Coastguard Worker }
1035*858ea5e5SAndroid Build Coastguard Worker
1036*858ea5e5SAndroid Build Coastguard Worker err = show_btf(fd, btf_prog_table, btf_map_table);
1037*858ea5e5SAndroid Build Coastguard Worker close(fd);
1038*858ea5e5SAndroid Build Coastguard Worker if (err)
1039*858ea5e5SAndroid Build Coastguard Worker break;
1040*858ea5e5SAndroid Build Coastguard Worker }
1041*858ea5e5SAndroid Build Coastguard Worker
1042*858ea5e5SAndroid Build Coastguard Worker if (json_output)
1043*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr); /* root array */
1044*858ea5e5SAndroid Build Coastguard Worker
1045*858ea5e5SAndroid Build Coastguard Worker exit_free:
1046*858ea5e5SAndroid Build Coastguard Worker hashmap__free(btf_prog_table);
1047*858ea5e5SAndroid Build Coastguard Worker hashmap__free(btf_map_table);
1048*858ea5e5SAndroid Build Coastguard Worker delete_obj_refs_table(refs_table);
1049*858ea5e5SAndroid Build Coastguard Worker
1050*858ea5e5SAndroid Build Coastguard Worker return err;
1051*858ea5e5SAndroid Build Coastguard Worker }
1052*858ea5e5SAndroid Build Coastguard Worker
do_help(int argc,char ** argv)1053*858ea5e5SAndroid Build Coastguard Worker static int do_help(int argc, char **argv)
1054*858ea5e5SAndroid Build Coastguard Worker {
1055*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
1056*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1057*858ea5e5SAndroid Build Coastguard Worker return 0;
1058*858ea5e5SAndroid Build Coastguard Worker }
1059*858ea5e5SAndroid Build Coastguard Worker
1060*858ea5e5SAndroid Build Coastguard Worker fprintf(stderr,
1061*858ea5e5SAndroid Build Coastguard Worker "Usage: %1$s %2$s { show | list } [id BTF_ID]\n"
1062*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s dump BTF_SRC [format FORMAT]\n"
1063*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s help\n"
1064*858ea5e5SAndroid Build Coastguard Worker "\n"
1065*858ea5e5SAndroid Build Coastguard Worker " BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n"
1066*858ea5e5SAndroid Build Coastguard Worker " FORMAT := { raw | c }\n"
1067*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_MAP "\n"
1068*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_PROGRAM "\n"
1069*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_OPTIONS " |\n"
1070*858ea5e5SAndroid Build Coastguard Worker " {-B|--base-btf} }\n"
1071*858ea5e5SAndroid Build Coastguard Worker "",
1072*858ea5e5SAndroid Build Coastguard Worker bin_name, "btf");
1073*858ea5e5SAndroid Build Coastguard Worker
1074*858ea5e5SAndroid Build Coastguard Worker return 0;
1075*858ea5e5SAndroid Build Coastguard Worker }
1076*858ea5e5SAndroid Build Coastguard Worker
1077*858ea5e5SAndroid Build Coastguard Worker static const struct cmd cmds[] = {
1078*858ea5e5SAndroid Build Coastguard Worker { "show", do_show },
1079*858ea5e5SAndroid Build Coastguard Worker { "list", do_show },
1080*858ea5e5SAndroid Build Coastguard Worker { "help", do_help },
1081*858ea5e5SAndroid Build Coastguard Worker { "dump", do_dump },
1082*858ea5e5SAndroid Build Coastguard Worker { 0 }
1083*858ea5e5SAndroid Build Coastguard Worker };
1084*858ea5e5SAndroid Build Coastguard Worker
do_btf(int argc,char ** argv)1085*858ea5e5SAndroid Build Coastguard Worker int do_btf(int argc, char **argv)
1086*858ea5e5SAndroid Build Coastguard Worker {
1087*858ea5e5SAndroid Build Coastguard Worker return cmd_select(cmds, argc, argv, do_help);
1088*858ea5e5SAndroid Build Coastguard Worker }
1089