brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · 1fee71c Raw
196 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 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 28int 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_SIGNATURE104	disassemble = disassembler(info.arch,105				   bfd_big_endian(bfdf),106				   info.mach,107				   bfdf);108#else109	disassemble = disassembler(bfdf);110#endif111	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		} else134			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;166out: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)174int 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 180int 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