1*858ea5e5SAndroid Build Coastguard Worker // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*858ea5e5SAndroid Build Coastguard Worker /* Copyright (C) 2018 Netronome Systems, Inc. */
3*858ea5e5SAndroid Build Coastguard Worker
4*858ea5e5SAndroid Build Coastguard Worker #ifndef _GNU_SOURCE
5*858ea5e5SAndroid Build Coastguard Worker #define _GNU_SOURCE
6*858ea5e5SAndroid Build Coastguard Worker #endif
7*858ea5e5SAndroid Build Coastguard Worker #include <stdarg.h>
8*858ea5e5SAndroid Build Coastguard Worker #include <stdio.h>
9*858ea5e5SAndroid Build Coastguard Worker #include <stdlib.h>
10*858ea5e5SAndroid Build Coastguard Worker #include <string.h>
11*858ea5e5SAndroid Build Coastguard Worker #include <sys/types.h>
12*858ea5e5SAndroid Build Coastguard Worker #include <bpf/libbpf.h>
13*858ea5e5SAndroid Build Coastguard Worker #include <bpf/libbpf_internal.h>
14*858ea5e5SAndroid Build Coastguard Worker
15*858ea5e5SAndroid Build Coastguard Worker #include "disasm.h"
16*858ea5e5SAndroid Build Coastguard Worker #include "json_writer.h"
17*858ea5e5SAndroid Build Coastguard Worker #include "main.h"
18*858ea5e5SAndroid Build Coastguard Worker #include "xlated_dumper.h"
19*858ea5e5SAndroid Build Coastguard Worker
kernel_syms_cmp(const void * sym_a,const void * sym_b)20*858ea5e5SAndroid Build Coastguard Worker static int kernel_syms_cmp(const void *sym_a, const void *sym_b)
21*858ea5e5SAndroid Build Coastguard Worker {
22*858ea5e5SAndroid Build Coastguard Worker return ((struct kernel_sym *)sym_a)->address -
23*858ea5e5SAndroid Build Coastguard Worker ((struct kernel_sym *)sym_b)->address;
24*858ea5e5SAndroid Build Coastguard Worker }
25*858ea5e5SAndroid Build Coastguard Worker
kernel_syms_load(struct dump_data * dd)26*858ea5e5SAndroid Build Coastguard Worker void kernel_syms_load(struct dump_data *dd)
27*858ea5e5SAndroid Build Coastguard Worker {
28*858ea5e5SAndroid Build Coastguard Worker struct kernel_sym *sym;
29*858ea5e5SAndroid Build Coastguard Worker char buff[256];
30*858ea5e5SAndroid Build Coastguard Worker void *tmp, *address;
31*858ea5e5SAndroid Build Coastguard Worker FILE *fp;
32*858ea5e5SAndroid Build Coastguard Worker
33*858ea5e5SAndroid Build Coastguard Worker fp = fopen("/proc/kallsyms", "r");
34*858ea5e5SAndroid Build Coastguard Worker if (!fp)
35*858ea5e5SAndroid Build Coastguard Worker return;
36*858ea5e5SAndroid Build Coastguard Worker
37*858ea5e5SAndroid Build Coastguard Worker while (fgets(buff, sizeof(buff), fp)) {
38*858ea5e5SAndroid Build Coastguard Worker tmp = libbpf_reallocarray(dd->sym_mapping, dd->sym_count + 1,
39*858ea5e5SAndroid Build Coastguard Worker sizeof(*dd->sym_mapping));
40*858ea5e5SAndroid Build Coastguard Worker if (!tmp) {
41*858ea5e5SAndroid Build Coastguard Worker out:
42*858ea5e5SAndroid Build Coastguard Worker free(dd->sym_mapping);
43*858ea5e5SAndroid Build Coastguard Worker dd->sym_mapping = NULL;
44*858ea5e5SAndroid Build Coastguard Worker fclose(fp);
45*858ea5e5SAndroid Build Coastguard Worker return;
46*858ea5e5SAndroid Build Coastguard Worker }
47*858ea5e5SAndroid Build Coastguard Worker dd->sym_mapping = tmp;
48*858ea5e5SAndroid Build Coastguard Worker sym = &dd->sym_mapping[dd->sym_count];
49*858ea5e5SAndroid Build Coastguard Worker
50*858ea5e5SAndroid Build Coastguard Worker /* module is optional */
51*858ea5e5SAndroid Build Coastguard Worker sym->module[0] = '\0';
52*858ea5e5SAndroid Build Coastguard Worker /* trim the square brackets around the module name */
53*858ea5e5SAndroid Build Coastguard Worker if (sscanf(buff, "%p %*c %s [%[^]]s", &address, sym->name, sym->module) < 2)
54*858ea5e5SAndroid Build Coastguard Worker continue;
55*858ea5e5SAndroid Build Coastguard Worker sym->address = (unsigned long)address;
56*858ea5e5SAndroid Build Coastguard Worker if (!strcmp(sym->name, "__bpf_call_base")) {
57*858ea5e5SAndroid Build Coastguard Worker dd->address_call_base = sym->address;
58*858ea5e5SAndroid Build Coastguard Worker /* sysctl kernel.kptr_restrict was set */
59*858ea5e5SAndroid Build Coastguard Worker if (!sym->address)
60*858ea5e5SAndroid Build Coastguard Worker goto out;
61*858ea5e5SAndroid Build Coastguard Worker }
62*858ea5e5SAndroid Build Coastguard Worker if (sym->address)
63*858ea5e5SAndroid Build Coastguard Worker dd->sym_count++;
64*858ea5e5SAndroid Build Coastguard Worker }
65*858ea5e5SAndroid Build Coastguard Worker
66*858ea5e5SAndroid Build Coastguard Worker fclose(fp);
67*858ea5e5SAndroid Build Coastguard Worker
68*858ea5e5SAndroid Build Coastguard Worker qsort(dd->sym_mapping, dd->sym_count,
69*858ea5e5SAndroid Build Coastguard Worker sizeof(*dd->sym_mapping), kernel_syms_cmp);
70*858ea5e5SAndroid Build Coastguard Worker }
71*858ea5e5SAndroid Build Coastguard Worker
kernel_syms_destroy(struct dump_data * dd)72*858ea5e5SAndroid Build Coastguard Worker void kernel_syms_destroy(struct dump_data *dd)
73*858ea5e5SAndroid Build Coastguard Worker {
74*858ea5e5SAndroid Build Coastguard Worker free(dd->sym_mapping);
75*858ea5e5SAndroid Build Coastguard Worker }
76*858ea5e5SAndroid Build Coastguard Worker
kernel_syms_search(struct dump_data * dd,unsigned long key)77*858ea5e5SAndroid Build Coastguard Worker struct kernel_sym *kernel_syms_search(struct dump_data *dd,
78*858ea5e5SAndroid Build Coastguard Worker unsigned long key)
79*858ea5e5SAndroid Build Coastguard Worker {
80*858ea5e5SAndroid Build Coastguard Worker struct kernel_sym sym = {
81*858ea5e5SAndroid Build Coastguard Worker .address = key,
82*858ea5e5SAndroid Build Coastguard Worker };
83*858ea5e5SAndroid Build Coastguard Worker
84*858ea5e5SAndroid Build Coastguard Worker return dd->sym_mapping ?
85*858ea5e5SAndroid Build Coastguard Worker bsearch(&sym, dd->sym_mapping, dd->sym_count,
86*858ea5e5SAndroid Build Coastguard Worker sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL;
87*858ea5e5SAndroid Build Coastguard Worker }
88*858ea5e5SAndroid Build Coastguard Worker
print_insn(void * private_data,const char * fmt,...)89*858ea5e5SAndroid Build Coastguard Worker static void __printf(2, 3) print_insn(void *private_data, const char *fmt, ...)
90*858ea5e5SAndroid Build Coastguard Worker {
91*858ea5e5SAndroid Build Coastguard Worker va_list args;
92*858ea5e5SAndroid Build Coastguard Worker
93*858ea5e5SAndroid Build Coastguard Worker va_start(args, fmt);
94*858ea5e5SAndroid Build Coastguard Worker vprintf(fmt, args);
95*858ea5e5SAndroid Build Coastguard Worker va_end(args);
96*858ea5e5SAndroid Build Coastguard Worker }
97*858ea5e5SAndroid Build Coastguard Worker
98*858ea5e5SAndroid Build Coastguard Worker static void __printf(2, 3)
print_insn_for_graph(void * private_data,const char * fmt,...)99*858ea5e5SAndroid Build Coastguard Worker print_insn_for_graph(void *private_data, const char *fmt, ...)
100*858ea5e5SAndroid Build Coastguard Worker {
101*858ea5e5SAndroid Build Coastguard Worker char buf[64], *p;
102*858ea5e5SAndroid Build Coastguard Worker va_list args;
103*858ea5e5SAndroid Build Coastguard Worker
104*858ea5e5SAndroid Build Coastguard Worker va_start(args, fmt);
105*858ea5e5SAndroid Build Coastguard Worker vsnprintf(buf, sizeof(buf), fmt, args);
106*858ea5e5SAndroid Build Coastguard Worker va_end(args);
107*858ea5e5SAndroid Build Coastguard Worker
108*858ea5e5SAndroid Build Coastguard Worker p = buf;
109*858ea5e5SAndroid Build Coastguard Worker while (*p != '\0') {
110*858ea5e5SAndroid Build Coastguard Worker if (*p == '\n') {
111*858ea5e5SAndroid Build Coastguard Worker memmove(p + 3, p, strlen(buf) + 1 - (p - buf));
112*858ea5e5SAndroid Build Coastguard Worker /* Align each instruction dump row left. */
113*858ea5e5SAndroid Build Coastguard Worker *p++ = '\\';
114*858ea5e5SAndroid Build Coastguard Worker *p++ = 'l';
115*858ea5e5SAndroid Build Coastguard Worker /* Output multiline concatenation. */
116*858ea5e5SAndroid Build Coastguard Worker *p++ = '\\';
117*858ea5e5SAndroid Build Coastguard Worker } else if (*p == '<' || *p == '>' || *p == '|' || *p == '&') {
118*858ea5e5SAndroid Build Coastguard Worker memmove(p + 1, p, strlen(buf) + 1 - (p - buf));
119*858ea5e5SAndroid Build Coastguard Worker /* Escape special character. */
120*858ea5e5SAndroid Build Coastguard Worker *p++ = '\\';
121*858ea5e5SAndroid Build Coastguard Worker }
122*858ea5e5SAndroid Build Coastguard Worker
123*858ea5e5SAndroid Build Coastguard Worker p++;
124*858ea5e5SAndroid Build Coastguard Worker }
125*858ea5e5SAndroid Build Coastguard Worker
126*858ea5e5SAndroid Build Coastguard Worker printf("%s", buf);
127*858ea5e5SAndroid Build Coastguard Worker }
128*858ea5e5SAndroid Build Coastguard Worker
129*858ea5e5SAndroid Build Coastguard Worker static void __printf(2, 3)
print_insn_json(void * private_data,const char * fmt,...)130*858ea5e5SAndroid Build Coastguard Worker print_insn_json(void *private_data, const char *fmt, ...)
131*858ea5e5SAndroid Build Coastguard Worker {
132*858ea5e5SAndroid Build Coastguard Worker unsigned int l = strlen(fmt);
133*858ea5e5SAndroid Build Coastguard Worker char chomped_fmt[l];
134*858ea5e5SAndroid Build Coastguard Worker va_list args;
135*858ea5e5SAndroid Build Coastguard Worker
136*858ea5e5SAndroid Build Coastguard Worker va_start(args, fmt);
137*858ea5e5SAndroid Build Coastguard Worker if (l > 0) {
138*858ea5e5SAndroid Build Coastguard Worker strncpy(chomped_fmt, fmt, l - 1);
139*858ea5e5SAndroid Build Coastguard Worker chomped_fmt[l - 1] = '\0';
140*858ea5e5SAndroid Build Coastguard Worker }
141*858ea5e5SAndroid Build Coastguard Worker jsonw_vprintf_enquote(json_wtr, chomped_fmt, args);
142*858ea5e5SAndroid Build Coastguard Worker va_end(args);
143*858ea5e5SAndroid Build Coastguard Worker }
144*858ea5e5SAndroid Build Coastguard Worker
print_call_pcrel(struct dump_data * dd,struct kernel_sym * sym,unsigned long address,const struct bpf_insn * insn)145*858ea5e5SAndroid Build Coastguard Worker static const char *print_call_pcrel(struct dump_data *dd,
146*858ea5e5SAndroid Build Coastguard Worker struct kernel_sym *sym,
147*858ea5e5SAndroid Build Coastguard Worker unsigned long address,
148*858ea5e5SAndroid Build Coastguard Worker const struct bpf_insn *insn)
149*858ea5e5SAndroid Build Coastguard Worker {
150*858ea5e5SAndroid Build Coastguard Worker if (!dd->nr_jited_ksyms)
151*858ea5e5SAndroid Build Coastguard Worker /* Do not show address for interpreted programs */
152*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
153*858ea5e5SAndroid Build Coastguard Worker "%+d", insn->off);
154*858ea5e5SAndroid Build Coastguard Worker else if (sym)
155*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
156*858ea5e5SAndroid Build Coastguard Worker "%+d#%s", insn->off, sym->name);
157*858ea5e5SAndroid Build Coastguard Worker else
158*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
159*858ea5e5SAndroid Build Coastguard Worker "%+d#0x%lx", insn->off, address);
160*858ea5e5SAndroid Build Coastguard Worker return dd->scratch_buff;
161*858ea5e5SAndroid Build Coastguard Worker }
162*858ea5e5SAndroid Build Coastguard Worker
print_call_helper(struct dump_data * dd,struct kernel_sym * sym,unsigned long address)163*858ea5e5SAndroid Build Coastguard Worker static const char *print_call_helper(struct dump_data *dd,
164*858ea5e5SAndroid Build Coastguard Worker struct kernel_sym *sym,
165*858ea5e5SAndroid Build Coastguard Worker unsigned long address)
166*858ea5e5SAndroid Build Coastguard Worker {
167*858ea5e5SAndroid Build Coastguard Worker if (sym)
168*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
169*858ea5e5SAndroid Build Coastguard Worker "%s", sym->name);
170*858ea5e5SAndroid Build Coastguard Worker else
171*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
172*858ea5e5SAndroid Build Coastguard Worker "0x%lx", address);
173*858ea5e5SAndroid Build Coastguard Worker return dd->scratch_buff;
174*858ea5e5SAndroid Build Coastguard Worker }
175*858ea5e5SAndroid Build Coastguard Worker
print_call(void * private_data,const struct bpf_insn * insn)176*858ea5e5SAndroid Build Coastguard Worker static const char *print_call(void *private_data,
177*858ea5e5SAndroid Build Coastguard Worker const struct bpf_insn *insn)
178*858ea5e5SAndroid Build Coastguard Worker {
179*858ea5e5SAndroid Build Coastguard Worker struct dump_data *dd = private_data;
180*858ea5e5SAndroid Build Coastguard Worker unsigned long address = dd->address_call_base + insn->imm;
181*858ea5e5SAndroid Build Coastguard Worker struct kernel_sym *sym;
182*858ea5e5SAndroid Build Coastguard Worker
183*858ea5e5SAndroid Build Coastguard Worker if (insn->src_reg == BPF_PSEUDO_CALL &&
184*858ea5e5SAndroid Build Coastguard Worker (__u32) insn->imm < dd->nr_jited_ksyms && dd->jited_ksyms)
185*858ea5e5SAndroid Build Coastguard Worker address = dd->jited_ksyms[insn->imm];
186*858ea5e5SAndroid Build Coastguard Worker
187*858ea5e5SAndroid Build Coastguard Worker sym = kernel_syms_search(dd, address);
188*858ea5e5SAndroid Build Coastguard Worker if (insn->src_reg == BPF_PSEUDO_CALL)
189*858ea5e5SAndroid Build Coastguard Worker return print_call_pcrel(dd, sym, address, insn);
190*858ea5e5SAndroid Build Coastguard Worker else
191*858ea5e5SAndroid Build Coastguard Worker return print_call_helper(dd, sym, address);
192*858ea5e5SAndroid Build Coastguard Worker }
193*858ea5e5SAndroid Build Coastguard Worker
print_imm(void * private_data,const struct bpf_insn * insn,__u64 full_imm)194*858ea5e5SAndroid Build Coastguard Worker static const char *print_imm(void *private_data,
195*858ea5e5SAndroid Build Coastguard Worker const struct bpf_insn *insn,
196*858ea5e5SAndroid Build Coastguard Worker __u64 full_imm)
197*858ea5e5SAndroid Build Coastguard Worker {
198*858ea5e5SAndroid Build Coastguard Worker struct dump_data *dd = private_data;
199*858ea5e5SAndroid Build Coastguard Worker
200*858ea5e5SAndroid Build Coastguard Worker if (insn->src_reg == BPF_PSEUDO_MAP_FD)
201*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
202*858ea5e5SAndroid Build Coastguard Worker "map[id:%u]", insn->imm);
203*858ea5e5SAndroid Build Coastguard Worker else if (insn->src_reg == BPF_PSEUDO_MAP_VALUE)
204*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
205*858ea5e5SAndroid Build Coastguard Worker "map[id:%u][0]+%u", insn->imm, (insn + 1)->imm);
206*858ea5e5SAndroid Build Coastguard Worker else if (insn->src_reg == BPF_PSEUDO_MAP_IDX_VALUE)
207*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
208*858ea5e5SAndroid Build Coastguard Worker "map[idx:%u]+%u", insn->imm, (insn + 1)->imm);
209*858ea5e5SAndroid Build Coastguard Worker else if (insn->src_reg == BPF_PSEUDO_FUNC)
210*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
211*858ea5e5SAndroid Build Coastguard Worker "subprog[%+d]", insn->imm);
212*858ea5e5SAndroid Build Coastguard Worker else
213*858ea5e5SAndroid Build Coastguard Worker snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
214*858ea5e5SAndroid Build Coastguard Worker "0x%llx", (unsigned long long)full_imm);
215*858ea5e5SAndroid Build Coastguard Worker return dd->scratch_buff;
216*858ea5e5SAndroid Build Coastguard Worker }
217*858ea5e5SAndroid Build Coastguard Worker
dump_xlated_json(struct dump_data * dd,void * buf,unsigned int len,bool opcodes,bool linum)218*858ea5e5SAndroid Build Coastguard Worker void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
219*858ea5e5SAndroid Build Coastguard Worker bool opcodes, bool linum)
220*858ea5e5SAndroid Build Coastguard Worker {
221*858ea5e5SAndroid Build Coastguard Worker const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
222*858ea5e5SAndroid Build Coastguard Worker const struct bpf_insn_cbs cbs = {
223*858ea5e5SAndroid Build Coastguard Worker .cb_print = print_insn_json,
224*858ea5e5SAndroid Build Coastguard Worker .cb_call = print_call,
225*858ea5e5SAndroid Build Coastguard Worker .cb_imm = print_imm,
226*858ea5e5SAndroid Build Coastguard Worker .private_data = dd,
227*858ea5e5SAndroid Build Coastguard Worker };
228*858ea5e5SAndroid Build Coastguard Worker struct bpf_func_info *record;
229*858ea5e5SAndroid Build Coastguard Worker struct bpf_insn *insn = buf;
230*858ea5e5SAndroid Build Coastguard Worker struct btf *btf = dd->btf;
231*858ea5e5SAndroid Build Coastguard Worker bool double_insn = false;
232*858ea5e5SAndroid Build Coastguard Worker unsigned int nr_skip = 0;
233*858ea5e5SAndroid Build Coastguard Worker char func_sig[1024];
234*858ea5e5SAndroid Build Coastguard Worker unsigned int i;
235*858ea5e5SAndroid Build Coastguard Worker
236*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
237*858ea5e5SAndroid Build Coastguard Worker record = dd->func_info;
238*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < len / sizeof(*insn); i++) {
239*858ea5e5SAndroid Build Coastguard Worker if (double_insn) {
240*858ea5e5SAndroid Build Coastguard Worker double_insn = false;
241*858ea5e5SAndroid Build Coastguard Worker continue;
242*858ea5e5SAndroid Build Coastguard Worker }
243*858ea5e5SAndroid Build Coastguard Worker double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
244*858ea5e5SAndroid Build Coastguard Worker
245*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
246*858ea5e5SAndroid Build Coastguard Worker
247*858ea5e5SAndroid Build Coastguard Worker if (btf && record) {
248*858ea5e5SAndroid Build Coastguard Worker if (record->insn_off == i) {
249*858ea5e5SAndroid Build Coastguard Worker btf_dumper_type_only(btf, record->type_id,
250*858ea5e5SAndroid Build Coastguard Worker func_sig,
251*858ea5e5SAndroid Build Coastguard Worker sizeof(func_sig));
252*858ea5e5SAndroid Build Coastguard Worker if (func_sig[0] != '\0') {
253*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "proto");
254*858ea5e5SAndroid Build Coastguard Worker jsonw_string(json_wtr, func_sig);
255*858ea5e5SAndroid Build Coastguard Worker }
256*858ea5e5SAndroid Build Coastguard Worker record = (void *)record + dd->finfo_rec_size;
257*858ea5e5SAndroid Build Coastguard Worker }
258*858ea5e5SAndroid Build Coastguard Worker }
259*858ea5e5SAndroid Build Coastguard Worker
260*858ea5e5SAndroid Build Coastguard Worker if (prog_linfo) {
261*858ea5e5SAndroid Build Coastguard Worker const struct bpf_line_info *linfo;
262*858ea5e5SAndroid Build Coastguard Worker
263*858ea5e5SAndroid Build Coastguard Worker linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip);
264*858ea5e5SAndroid Build Coastguard Worker if (linfo) {
265*858ea5e5SAndroid Build Coastguard Worker btf_dump_linfo_json(btf, linfo, linum);
266*858ea5e5SAndroid Build Coastguard Worker nr_skip++;
267*858ea5e5SAndroid Build Coastguard Worker }
268*858ea5e5SAndroid Build Coastguard Worker }
269*858ea5e5SAndroid Build Coastguard Worker
270*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "disasm");
271*858ea5e5SAndroid Build Coastguard Worker print_bpf_insn(&cbs, insn + i, true);
272*858ea5e5SAndroid Build Coastguard Worker
273*858ea5e5SAndroid Build Coastguard Worker if (opcodes) {
274*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "opcodes");
275*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
276*858ea5e5SAndroid Build Coastguard Worker
277*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "code");
278*858ea5e5SAndroid Build Coastguard Worker jsonw_printf(json_wtr, "\"0x%02hhx\"", insn[i].code);
279*858ea5e5SAndroid Build Coastguard Worker
280*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "src_reg");
281*858ea5e5SAndroid Build Coastguard Worker jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].src_reg);
282*858ea5e5SAndroid Build Coastguard Worker
283*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "dst_reg");
284*858ea5e5SAndroid Build Coastguard Worker jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].dst_reg);
285*858ea5e5SAndroid Build Coastguard Worker
286*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "off");
287*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json((uint8_t *)(&insn[i].off), 2);
288*858ea5e5SAndroid Build Coastguard Worker
289*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "imm");
290*858ea5e5SAndroid Build Coastguard Worker if (double_insn && i < len - 1)
291*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json((uint8_t *)(&insn[i].imm),
292*858ea5e5SAndroid Build Coastguard Worker 12);
293*858ea5e5SAndroid Build Coastguard Worker else
294*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json((uint8_t *)(&insn[i].imm),
295*858ea5e5SAndroid Build Coastguard Worker 4);
296*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
297*858ea5e5SAndroid Build Coastguard Worker }
298*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
299*858ea5e5SAndroid Build Coastguard Worker }
300*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
301*858ea5e5SAndroid Build Coastguard Worker }
302*858ea5e5SAndroid Build Coastguard Worker
dump_xlated_plain(struct dump_data * dd,void * buf,unsigned int len,bool opcodes,bool linum)303*858ea5e5SAndroid Build Coastguard Worker void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
304*858ea5e5SAndroid Build Coastguard Worker bool opcodes, bool linum)
305*858ea5e5SAndroid Build Coastguard Worker {
306*858ea5e5SAndroid Build Coastguard Worker const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
307*858ea5e5SAndroid Build Coastguard Worker const struct bpf_insn_cbs cbs = {
308*858ea5e5SAndroid Build Coastguard Worker .cb_print = print_insn,
309*858ea5e5SAndroid Build Coastguard Worker .cb_call = print_call,
310*858ea5e5SAndroid Build Coastguard Worker .cb_imm = print_imm,
311*858ea5e5SAndroid Build Coastguard Worker .private_data = dd,
312*858ea5e5SAndroid Build Coastguard Worker };
313*858ea5e5SAndroid Build Coastguard Worker struct bpf_func_info *record;
314*858ea5e5SAndroid Build Coastguard Worker struct bpf_insn *insn = buf;
315*858ea5e5SAndroid Build Coastguard Worker struct btf *btf = dd->btf;
316*858ea5e5SAndroid Build Coastguard Worker unsigned int nr_skip = 0;
317*858ea5e5SAndroid Build Coastguard Worker bool double_insn = false;
318*858ea5e5SAndroid Build Coastguard Worker char func_sig[1024];
319*858ea5e5SAndroid Build Coastguard Worker unsigned int i;
320*858ea5e5SAndroid Build Coastguard Worker
321*858ea5e5SAndroid Build Coastguard Worker record = dd->func_info;
322*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < len / sizeof(*insn); i++) {
323*858ea5e5SAndroid Build Coastguard Worker if (double_insn) {
324*858ea5e5SAndroid Build Coastguard Worker double_insn = false;
325*858ea5e5SAndroid Build Coastguard Worker continue;
326*858ea5e5SAndroid Build Coastguard Worker }
327*858ea5e5SAndroid Build Coastguard Worker
328*858ea5e5SAndroid Build Coastguard Worker if (btf && record) {
329*858ea5e5SAndroid Build Coastguard Worker if (record->insn_off == i) {
330*858ea5e5SAndroid Build Coastguard Worker btf_dumper_type_only(btf, record->type_id,
331*858ea5e5SAndroid Build Coastguard Worker func_sig,
332*858ea5e5SAndroid Build Coastguard Worker sizeof(func_sig));
333*858ea5e5SAndroid Build Coastguard Worker if (func_sig[0] != '\0')
334*858ea5e5SAndroid Build Coastguard Worker printf("%s:\n", func_sig);
335*858ea5e5SAndroid Build Coastguard Worker record = (void *)record + dd->finfo_rec_size;
336*858ea5e5SAndroid Build Coastguard Worker }
337*858ea5e5SAndroid Build Coastguard Worker }
338*858ea5e5SAndroid Build Coastguard Worker
339*858ea5e5SAndroid Build Coastguard Worker if (prog_linfo) {
340*858ea5e5SAndroid Build Coastguard Worker const struct bpf_line_info *linfo;
341*858ea5e5SAndroid Build Coastguard Worker
342*858ea5e5SAndroid Build Coastguard Worker linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip);
343*858ea5e5SAndroid Build Coastguard Worker if (linfo) {
344*858ea5e5SAndroid Build Coastguard Worker btf_dump_linfo_plain(btf, linfo, "; ",
345*858ea5e5SAndroid Build Coastguard Worker linum);
346*858ea5e5SAndroid Build Coastguard Worker nr_skip++;
347*858ea5e5SAndroid Build Coastguard Worker }
348*858ea5e5SAndroid Build Coastguard Worker }
349*858ea5e5SAndroid Build Coastguard Worker
350*858ea5e5SAndroid Build Coastguard Worker double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
351*858ea5e5SAndroid Build Coastguard Worker
352*858ea5e5SAndroid Build Coastguard Worker printf("% 4d: ", i);
353*858ea5e5SAndroid Build Coastguard Worker print_bpf_insn(&cbs, insn + i, true);
354*858ea5e5SAndroid Build Coastguard Worker
355*858ea5e5SAndroid Build Coastguard Worker if (opcodes) {
356*858ea5e5SAndroid Build Coastguard Worker printf(" ");
357*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, insn + i, 8, " ");
358*858ea5e5SAndroid Build Coastguard Worker if (double_insn && i < len - 1) {
359*858ea5e5SAndroid Build Coastguard Worker printf(" ");
360*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, insn + i + 1, 8, " ");
361*858ea5e5SAndroid Build Coastguard Worker }
362*858ea5e5SAndroid Build Coastguard Worker printf("\n");
363*858ea5e5SAndroid Build Coastguard Worker }
364*858ea5e5SAndroid Build Coastguard Worker }
365*858ea5e5SAndroid Build Coastguard Worker }
366*858ea5e5SAndroid Build Coastguard Worker
dump_xlated_for_graph(struct dump_data * dd,void * buf_start,void * buf_end,unsigned int start_idx,bool opcodes,bool linum)367*858ea5e5SAndroid Build Coastguard Worker void dump_xlated_for_graph(struct dump_data *dd, void *buf_start, void *buf_end,
368*858ea5e5SAndroid Build Coastguard Worker unsigned int start_idx,
369*858ea5e5SAndroid Build Coastguard Worker bool opcodes, bool linum)
370*858ea5e5SAndroid Build Coastguard Worker {
371*858ea5e5SAndroid Build Coastguard Worker const struct bpf_insn_cbs cbs = {
372*858ea5e5SAndroid Build Coastguard Worker .cb_print = print_insn_for_graph,
373*858ea5e5SAndroid Build Coastguard Worker .cb_call = print_call,
374*858ea5e5SAndroid Build Coastguard Worker .cb_imm = print_imm,
375*858ea5e5SAndroid Build Coastguard Worker .private_data = dd,
376*858ea5e5SAndroid Build Coastguard Worker };
377*858ea5e5SAndroid Build Coastguard Worker const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
378*858ea5e5SAndroid Build Coastguard Worker const struct bpf_line_info *last_linfo = NULL;
379*858ea5e5SAndroid Build Coastguard Worker struct bpf_func_info *record = dd->func_info;
380*858ea5e5SAndroid Build Coastguard Worker struct bpf_insn *insn_start = buf_start;
381*858ea5e5SAndroid Build Coastguard Worker struct bpf_insn *insn_end = buf_end;
382*858ea5e5SAndroid Build Coastguard Worker struct bpf_insn *cur = insn_start;
383*858ea5e5SAndroid Build Coastguard Worker struct btf *btf = dd->btf;
384*858ea5e5SAndroid Build Coastguard Worker bool double_insn = false;
385*858ea5e5SAndroid Build Coastguard Worker char func_sig[1024];
386*858ea5e5SAndroid Build Coastguard Worker
387*858ea5e5SAndroid Build Coastguard Worker for (; cur <= insn_end; cur++) {
388*858ea5e5SAndroid Build Coastguard Worker unsigned int insn_off;
389*858ea5e5SAndroid Build Coastguard Worker
390*858ea5e5SAndroid Build Coastguard Worker if (double_insn) {
391*858ea5e5SAndroid Build Coastguard Worker double_insn = false;
392*858ea5e5SAndroid Build Coastguard Worker continue;
393*858ea5e5SAndroid Build Coastguard Worker }
394*858ea5e5SAndroid Build Coastguard Worker double_insn = cur->code == (BPF_LD | BPF_IMM | BPF_DW);
395*858ea5e5SAndroid Build Coastguard Worker
396*858ea5e5SAndroid Build Coastguard Worker insn_off = (unsigned int)(cur - insn_start + start_idx);
397*858ea5e5SAndroid Build Coastguard Worker if (btf && record) {
398*858ea5e5SAndroid Build Coastguard Worker if (record->insn_off == insn_off) {
399*858ea5e5SAndroid Build Coastguard Worker btf_dumper_type_only(btf, record->type_id,
400*858ea5e5SAndroid Build Coastguard Worker func_sig,
401*858ea5e5SAndroid Build Coastguard Worker sizeof(func_sig));
402*858ea5e5SAndroid Build Coastguard Worker if (func_sig[0] != '\0')
403*858ea5e5SAndroid Build Coastguard Worker printf("; %s:\\l\\\n", func_sig);
404*858ea5e5SAndroid Build Coastguard Worker record = (void *)record + dd->finfo_rec_size;
405*858ea5e5SAndroid Build Coastguard Worker }
406*858ea5e5SAndroid Build Coastguard Worker }
407*858ea5e5SAndroid Build Coastguard Worker
408*858ea5e5SAndroid Build Coastguard Worker if (prog_linfo) {
409*858ea5e5SAndroid Build Coastguard Worker const struct bpf_line_info *linfo;
410*858ea5e5SAndroid Build Coastguard Worker
411*858ea5e5SAndroid Build Coastguard Worker linfo = bpf_prog_linfo__lfind(prog_linfo, insn_off, 0);
412*858ea5e5SAndroid Build Coastguard Worker if (linfo && linfo != last_linfo) {
413*858ea5e5SAndroid Build Coastguard Worker btf_dump_linfo_dotlabel(btf, linfo, linum);
414*858ea5e5SAndroid Build Coastguard Worker last_linfo = linfo;
415*858ea5e5SAndroid Build Coastguard Worker }
416*858ea5e5SAndroid Build Coastguard Worker }
417*858ea5e5SAndroid Build Coastguard Worker
418*858ea5e5SAndroid Build Coastguard Worker printf("%d: ", insn_off);
419*858ea5e5SAndroid Build Coastguard Worker print_bpf_insn(&cbs, cur, true);
420*858ea5e5SAndroid Build Coastguard Worker
421*858ea5e5SAndroid Build Coastguard Worker if (opcodes) {
422*858ea5e5SAndroid Build Coastguard Worker printf("\\ \\ \\ \\ ");
423*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, cur, 8, " ");
424*858ea5e5SAndroid Build Coastguard Worker if (double_insn && cur <= insn_end - 1) {
425*858ea5e5SAndroid Build Coastguard Worker printf(" ");
426*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, cur + 1, 8, " ");
427*858ea5e5SAndroid Build Coastguard Worker }
428*858ea5e5SAndroid Build Coastguard Worker printf("\\l\\\n");
429*858ea5e5SAndroid Build Coastguard Worker }
430*858ea5e5SAndroid Build Coastguard Worker
431*858ea5e5SAndroid Build Coastguard Worker if (cur != insn_end)
432*858ea5e5SAndroid Build Coastguard Worker printf("| ");
433*858ea5e5SAndroid Build Coastguard Worker }
434*858ea5e5SAndroid Build Coastguard Worker }
435