hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/tools/bpf/bpftool/xlated_dumper.c
....@@ -1,39 +1,5 @@
11 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2
-/*
3
- * Copyright (C) 2018 Netronome Systems, Inc.
4
- *
5
- * This software is dual licensed under the GNU General License Version 2,
6
- * June 1991 as shown in the file COPYING in the top-level directory of this
7
- * source tree or the BSD 2-Clause License provided below. You have the
8
- * option to license this software under the complete terms of either license.
9
- *
10
- * The BSD 2-Clause License:
11
- *
12
- * Redistribution and use in source and binary forms, with or
13
- * without modification, are permitted provided that the following
14
- * conditions are met:
15
- *
16
- * 1. Redistributions of source code must retain the above
17
- * copyright notice, this list of conditions and the following
18
- * disclaimer.
19
- *
20
- * 2. Redistributions in binary form must reproduce the above
21
- * copyright notice, this list of conditions and the following
22
- * disclaimer in the documentation and/or other materials
23
- * provided with the distribution.
24
- *
25
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
- * POSSIBILITY OF SUCH DAMAGE.
36
- */
2
+/* Copyright (C) 2018 Netronome Systems, Inc. */
373
384 #define _GNU_SOURCE
395 #include <stdarg.h>
....@@ -41,6 +7,7 @@
417 #include <stdlib.h>
428 #include <string.h>
439 #include <sys/types.h>
10
+#include <bpf/libbpf.h>
4411
4512 #include "disasm.h"
4613 #include "json_writer.h"
....@@ -64,9 +31,7 @@
6431 if (!fp)
6532 return;
6633
67
- while (!feof(fp)) {
68
- if (!fgets(buff, sizeof(buff), fp))
69
- break;
34
+ while (fgets(buff, sizeof(buff), fp)) {
7035 tmp = reallocarray(dd->sym_mapping, dd->sym_count + 1,
7136 sizeof(*dd->sym_mapping));
7237 if (!tmp) {
....@@ -114,7 +79,7 @@
11479 sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL;
11580 }
11681
117
-static void print_insn(void *private_data, const char *fmt, ...)
82
+static void __printf(2, 3) print_insn(void *private_data, const char *fmt, ...)
11883 {
11984 va_list args;
12085
....@@ -123,7 +88,7 @@
12388 va_end(args);
12489 }
12590
126
-static void
91
+static void __printf(2, 3)
12792 print_insn_for_graph(void *private_data, const char *fmt, ...)
12893 {
12994 char buf[64], *p;
....@@ -154,7 +119,8 @@
154119 printf("%s", buf);
155120 }
156121
157
-static void print_insn_json(void *private_data, const char *fmt, ...)
122
+static void __printf(2, 3)
123
+print_insn_json(void *private_data, const char *fmt, ...)
158124 {
159125 unsigned int l = strlen(fmt);
160126 char chomped_fmt[l];
....@@ -208,7 +174,7 @@
208174 struct kernel_sym *sym;
209175
210176 if (insn->src_reg == BPF_PSEUDO_CALL &&
211
- (__u32) insn->imm < dd->nr_jited_ksyms)
177
+ (__u32) insn->imm < dd->nr_jited_ksyms && dd->jited_ksyms)
212178 address = dd->jited_ksyms[insn->imm];
213179
214180 sym = kernel_syms_search(dd, address);
....@@ -227,6 +193,9 @@
227193 if (insn->src_reg == BPF_PSEUDO_MAP_FD)
228194 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
229195 "map[id:%u]", insn->imm);
196
+ else if (insn->src_reg == BPF_PSEUDO_MAP_VALUE)
197
+ snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
198
+ "map[id:%u][0]+%u", insn->imm, (insn + 1)->imm);
230199 else
231200 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
232201 "0x%llx", (unsigned long long)full_imm);
....@@ -234,19 +203,25 @@
234203 }
235204
236205 void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
237
- bool opcodes)
206
+ bool opcodes, bool linum)
238207 {
208
+ const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
239209 const struct bpf_insn_cbs cbs = {
240210 .cb_print = print_insn_json,
241211 .cb_call = print_call,
242212 .cb_imm = print_imm,
243213 .private_data = dd,
244214 };
215
+ struct bpf_func_info *record;
245216 struct bpf_insn *insn = buf;
217
+ struct btf *btf = dd->btf;
246218 bool double_insn = false;
219
+ unsigned int nr_skip = 0;
220
+ char func_sig[1024];
247221 unsigned int i;
248222
249223 jsonw_start_array(json_wtr);
224
+ record = dd->func_info;
250225 for (i = 0; i < len / sizeof(*insn); i++) {
251226 if (double_insn) {
252227 double_insn = false;
....@@ -255,6 +230,30 @@
255230 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
256231
257232 jsonw_start_object(json_wtr);
233
+
234
+ if (btf && record) {
235
+ if (record->insn_off == i) {
236
+ btf_dumper_type_only(btf, record->type_id,
237
+ func_sig,
238
+ sizeof(func_sig));
239
+ if (func_sig[0] != '\0') {
240
+ jsonw_name(json_wtr, "proto");
241
+ jsonw_string(json_wtr, func_sig);
242
+ }
243
+ record = (void *)record + dd->finfo_rec_size;
244
+ }
245
+ }
246
+
247
+ if (prog_linfo) {
248
+ const struct bpf_line_info *linfo;
249
+
250
+ linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip);
251
+ if (linfo) {
252
+ btf_dump_linfo_json(btf, linfo, linum);
253
+ nr_skip++;
254
+ }
255
+ }
256
+
258257 jsonw_name(json_wtr, "disasm");
259258 print_bpf_insn(&cbs, insn + i, true);
260259
....@@ -289,22 +288,50 @@
289288 }
290289
291290 void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
292
- bool opcodes)
291
+ bool opcodes, bool linum)
293292 {
293
+ const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
294294 const struct bpf_insn_cbs cbs = {
295295 .cb_print = print_insn,
296296 .cb_call = print_call,
297297 .cb_imm = print_imm,
298298 .private_data = dd,
299299 };
300
+ struct bpf_func_info *record;
300301 struct bpf_insn *insn = buf;
302
+ struct btf *btf = dd->btf;
303
+ unsigned int nr_skip = 0;
301304 bool double_insn = false;
305
+ char func_sig[1024];
302306 unsigned int i;
303307
308
+ record = dd->func_info;
304309 for (i = 0; i < len / sizeof(*insn); i++) {
305310 if (double_insn) {
306311 double_insn = false;
307312 continue;
313
+ }
314
+
315
+ if (btf && record) {
316
+ if (record->insn_off == i) {
317
+ btf_dumper_type_only(btf, record->type_id,
318
+ func_sig,
319
+ sizeof(func_sig));
320
+ if (func_sig[0] != '\0')
321
+ printf("%s:\n", func_sig);
322
+ record = (void *)record + dd->finfo_rec_size;
323
+ }
324
+ }
325
+
326
+ if (prog_linfo) {
327
+ const struct bpf_line_info *linfo;
328
+
329
+ linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip);
330
+ if (linfo) {
331
+ btf_dump_linfo_plain(btf, linfo, "; ",
332
+ linum);
333
+ nr_skip++;
334
+ }
308335 }
309336
310337 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
....@@ -336,8 +363,15 @@
336363 struct bpf_insn *insn_start = buf_start;
337364 struct bpf_insn *insn_end = buf_end;
338365 struct bpf_insn *cur = insn_start;
366
+ bool double_insn = false;
339367
340368 for (; cur <= insn_end; cur++) {
369
+ if (double_insn) {
370
+ double_insn = false;
371
+ continue;
372
+ }
373
+ double_insn = cur->code == (BPF_LD | BPF_IMM | BPF_DW);
374
+
341375 printf("% 4d: ", (int)(cur - insn_start + start_idx));
342376 print_bpf_insn(&cbs, cur, true);
343377 if (cur != insn_end)