summaryrefslogtreecommitdiff
path: root/tools/bpf/bpftool/xlated_dumper.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/bpf/bpftool/xlated_dumper.c')
-rw-r--r--tools/bpf/bpftool/xlated_dumper.c88
1 files changed, 75 insertions, 13 deletions
diff --git a/tools/bpf/bpftool/xlated_dumper.c b/tools/bpf/bpftool/xlated_dumper.c
index 7073dbe1ff27..5e7cb8b36fef 100644
--- a/tools/bpf/bpftool/xlated_dumper.c
+++ b/tools/bpf/bpftool/xlated_dumper.c
@@ -1,13 +1,16 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2018 Netronome Systems, Inc. */
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
-#include <libbpf.h>
+#include <bpf/libbpf.h>
+#include <bpf/libbpf_internal.h>
#include "disasm.h"
#include "json_writer.h"
@@ -31,11 +34,9 @@ void kernel_syms_load(struct dump_data *dd)
if (!fp)
return;
- while (!feof(fp)) {
- if (!fgets(buff, sizeof(buff), fp))
- break;
- tmp = reallocarray(dd->sym_mapping, dd->sym_count + 1,
- sizeof(*dd->sym_mapping));
+ while (fgets(buff, sizeof(buff), fp)) {
+ tmp = libbpf_reallocarray(dd->sym_mapping, dd->sym_count + 1,
+ sizeof(*dd->sym_mapping));
if (!tmp) {
out:
free(dd->sym_mapping);
@@ -45,7 +46,11 @@ out:
}
dd->sym_mapping = tmp;
sym = &dd->sym_mapping[dd->sym_count];
- if (sscanf(buff, "%p %*c %s", &address, sym->name) != 2)
+
+ /* module is optional */
+ sym->module[0] = '\0';
+ /* trim the square brackets around the module name */
+ if (sscanf(buff, "%p %*c %s [%[^]]s", &address, sym->name, sym->module) < 2)
continue;
sym->address = (unsigned long)address;
if (!strcmp(sym->name, "__bpf_call_base")) {
@@ -176,7 +181,7 @@ static const char *print_call(void *private_data,
struct kernel_sym *sym;
if (insn->src_reg == BPF_PSEUDO_CALL &&
- (__u32) insn->imm < dd->nr_jited_ksyms)
+ (__u32) insn->imm < dd->nr_jited_ksyms && dd->jited_ksyms)
address = dd->jited_ksyms[insn->imm];
sym = kernel_syms_search(dd, address);
@@ -194,7 +199,16 @@ static const char *print_imm(void *private_data,
if (insn->src_reg == BPF_PSEUDO_MAP_FD)
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
- "map[id:%u]", insn->imm);
+ "map[id:%d]", insn->imm);
+ else if (insn->src_reg == BPF_PSEUDO_MAP_VALUE)
+ snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
+ "map[id:%d][0]+%d", insn->imm, (insn + 1)->imm);
+ else if (insn->src_reg == BPF_PSEUDO_MAP_IDX_VALUE)
+ snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
+ "map[idx:%d]+%d", insn->imm, (insn + 1)->imm);
+ else if (insn->src_reg == BPF_PSEUDO_FUNC)
+ snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
+ "subprog[%+d]", insn->imm);
else
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
"0x%llx", (unsigned long long)full_imm);
@@ -335,7 +349,7 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
- printf("% 4d: ", i);
+ printf("%4u: ", i);
print_bpf_insn(&cbs, insn + i, true);
if (opcodes) {
@@ -351,7 +365,8 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
}
void dump_xlated_for_graph(struct dump_data *dd, void *buf_start, void *buf_end,
- unsigned int start_idx)
+ unsigned int start_idx,
+ bool opcodes, bool linum)
{
const struct bpf_insn_cbs cbs = {
.cb_print = print_insn_for_graph,
@@ -359,14 +374,61 @@ void dump_xlated_for_graph(struct dump_data *dd, void *buf_start, void *buf_end,
.cb_imm = print_imm,
.private_data = dd,
};
+ const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
+ const struct bpf_line_info *last_linfo = NULL;
+ struct bpf_func_info *record = dd->func_info;
struct bpf_insn *insn_start = buf_start;
struct bpf_insn *insn_end = buf_end;
struct bpf_insn *cur = insn_start;
+ struct btf *btf = dd->btf;
+ bool double_insn = false;
+ char func_sig[1024];
for (; cur <= insn_end; cur++) {
- printf("% 4d: ", (int)(cur - insn_start + start_idx));
+ unsigned int insn_off;
+
+ if (double_insn) {
+ double_insn = false;
+ continue;
+ }
+ double_insn = cur->code == (BPF_LD | BPF_IMM | BPF_DW);
+
+ insn_off = (unsigned int)(cur - insn_start + start_idx);
+ if (btf && record) {
+ if (record->insn_off == insn_off) {
+ btf_dumper_type_only(btf, record->type_id,
+ func_sig,
+ sizeof(func_sig));
+ if (func_sig[0] != '\0')
+ printf("; %s:\\l\\\n", func_sig);
+ record = (void *)record + dd->finfo_rec_size;
+ }
+ }
+
+ if (prog_linfo) {
+ const struct bpf_line_info *linfo;
+
+ linfo = bpf_prog_linfo__lfind(prog_linfo, insn_off, 0);
+ if (linfo && linfo != last_linfo) {
+ btf_dump_linfo_dotlabel(btf, linfo, linum);
+ last_linfo = linfo;
+ }
+ }
+
+ printf("%u: ", insn_off);
print_bpf_insn(&cbs, cur, true);
+
+ if (opcodes) {
+ printf("\\ \\ \\ \\ ");
+ fprint_hex(stdout, cur, 8, " ");
+ if (double_insn && cur <= insn_end - 1) {
+ printf(" ");
+ fprint_hex(stdout, cur + 1, 8, " ");
+ }
+ printf("\\l\\\n");
+ }
+
if (cur != insn_end)
- printf(" | ");
+ printf("| ");
}
}