~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/disasm_bpf.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 }
196 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php