]> Git Repo - J-linux.git/blob - tools/perf/util/disasm_bpf.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / perf / util / disasm_bpf.c
1 // SPDX-License-Identifier: GPL-2.0-only
2
3 #include "util/annotate.h"
4 #include "util/disasm_bpf.h"
5 #include "util/symbol.h"
6 #include <linux/zalloc.h>
7 #include <string.h>
8
9 #if defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
10 #define PACKAGE "perf"
11 #include <bfd.h>
12 #include <bpf/bpf.h>
13 #include <bpf/btf.h>
14 #include <bpf/libbpf.h>
15 #include <dis-asm.h>
16 #include <errno.h>
17 #include <linux/btf.h>
18 #include <tools/dis-asm-compat.h>
19
20 #include "util/bpf-event.h"
21 #include "util/bpf-utils.h"
22 #include "util/debug.h"
23 #include "util/dso.h"
24 #include "util/map.h"
25 #include "util/env.h"
26 #include "util/util.h"
27
28 int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args)
29 {
30         struct annotation *notes = symbol__annotation(sym);
31         struct bpf_prog_linfo *prog_linfo = NULL;
32         struct bpf_prog_info_node *info_node;
33         int len = sym->end - sym->start;
34         disassembler_ftype disassemble;
35         struct map *map = args->ms.map;
36         struct perf_bpil *info_linear;
37         struct disassemble_info info;
38         struct dso *dso = map__dso(map);
39         int pc = 0, count, sub_id;
40         struct btf *btf = NULL;
41         char tpath[PATH_MAX];
42         size_t buf_size;
43         int nr_skip = 0;
44         char *buf;
45         bfd *bfdf;
46         int ret;
47         FILE *s;
48
49         if (dso__binary_type(dso) != DSO_BINARY_TYPE__BPF_PROG_INFO)
50                 return SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE;
51
52         pr_debug("%s: handling sym %s addr %" PRIx64 " len %" PRIx64 "\n", __func__,
53                   sym->name, sym->start, sym->end - sym->start);
54
55         memset(tpath, 0, sizeof(tpath));
56         perf_exe(tpath, sizeof(tpath));
57
58         bfdf = bfd_openr(tpath, NULL);
59         if (bfdf == NULL)
60                 abort();
61
62         if (!bfd_check_format(bfdf, bfd_object))
63                 abort();
64
65         s = open_memstream(&buf, &buf_size);
66         if (!s) {
67                 ret = errno;
68                 goto out;
69         }
70         init_disassemble_info_compat(&info, s,
71                                      (fprintf_ftype) fprintf,
72                                      fprintf_styled);
73         info.arch = bfd_get_arch(bfdf);
74         info.mach = bfd_get_mach(bfdf);
75
76         info_node = perf_env__find_bpf_prog_info(dso__bpf_prog(dso)->env,
77                                                  dso__bpf_prog(dso)->id);
78         if (!info_node) {
79                 ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
80                 goto out;
81         }
82         info_linear = info_node->info_linear;
83         sub_id = dso__bpf_prog(dso)->sub_id;
84
85         info.buffer = (void *)(uintptr_t)(info_linear->info.jited_prog_insns);
86         info.buffer_length = info_linear->info.jited_prog_len;
87
88         if (info_linear->info.nr_line_info)
89                 prog_linfo = bpf_prog_linfo__new(&info_linear->info);
90
91         if (info_linear->info.btf_id) {
92                 struct btf_node *node;
93
94                 node = perf_env__find_btf(dso__bpf_prog(dso)->env,
95                                           info_linear->info.btf_id);
96                 if (node)
97                         btf = btf__new((__u8 *)(node->data),
98                                        node->data_size);
99         }
100
101         disassemble_init_for_target(&info);
102
103 #ifdef DISASM_FOUR_ARGS_SIGNATURE
104         disassemble = disassembler(info.arch,
105                                    bfd_big_endian(bfdf),
106                                    info.mach,
107                                    bfdf);
108 #else
109         disassemble = disassembler(bfdf);
110 #endif
111         if (disassemble == NULL)
112                 abort();
113
114         fflush(s);
115         do {
116                 const struct bpf_line_info *linfo = NULL;
117                 struct disasm_line *dl;
118                 size_t prev_buf_size;
119                 const char *srcline;
120                 u64 addr;
121
122                 addr = pc + ((u64 *)(uintptr_t)(info_linear->info.jited_ksyms))[sub_id];
123                 count = disassemble(pc, &info);
124
125                 if (prog_linfo)
126                         linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
127                                                                 addr, sub_id,
128                                                                 nr_skip);
129
130                 if (linfo && btf) {
131                         srcline = btf__name_by_offset(btf, linfo->line_off);
132                         nr_skip++;
133                 } else
134                         srcline = NULL;
135
136                 fprintf(s, "\n");
137                 prev_buf_size = buf_size;
138                 fflush(s);
139
140                 if (!annotate_opts.hide_src_code && srcline) {
141                         args->offset = -1;
142                         args->line = strdup(srcline);
143                         args->line_nr = 0;
144                         args->fileloc = NULL;
145                         args->ms.sym  = sym;
146                         dl = disasm_line__new(args);
147                         if (dl) {
148                                 annotation_line__add(&dl->al,
149                                                      &notes->src->source);
150                         }
151                 }
152
153                 args->offset = pc;
154                 args->line = buf + prev_buf_size;
155                 args->line_nr = 0;
156                 args->fileloc = NULL;
157                 args->ms.sym  = sym;
158                 dl = disasm_line__new(args);
159                 if (dl)
160                         annotation_line__add(&dl->al, &notes->src->source);
161
162                 pc += count;
163         } while (count > 0 && pc < len);
164
165         ret = 0;
166 out:
167         free(prog_linfo);
168         btf__free(btf);
169         fclose(s);
170         bfd_close(bfdf);
171         return ret;
172 }
173 #else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
174 int symbol__disassemble_bpf(struct symbol *sym __maybe_unused, struct annotate_args *args __maybe_unused)
175 {
176         return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
177 }
178 #endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
179
180 int symbol__disassemble_bpf_image(struct symbol *sym, struct annotate_args *args)
181 {
182         struct annotation *notes = symbol__annotation(sym);
183         struct disasm_line *dl;
184
185         args->offset = -1;
186         args->line = strdup("to be implemented");
187         args->line_nr = 0;
188         args->fileloc = NULL;
189         dl = disasm_line__new(args);
190         if (dl)
191                 annotation_line__add(&dl->al, &notes->src->source);
192
193         zfree(&args->line);
194         return 0;
195 }
This page took 0.037331 seconds and 4 git commands to generate.