brintos

brintos / linux-shallow public Read only

0
0
Text · 54.9 KiB · f05ba77 Raw
2274 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2#include <ctype.h>3#include <errno.h>4#include <fcntl.h>5#include <inttypes.h>6#include <libgen.h>7#include <regex.h>8#include <stdlib.h>9#include <unistd.h>10 11#include <linux/string.h>12#include <subcmd/run-command.h>13 14#include "annotate.h"15#include "annotate-data.h"16#include "build-id.h"17#include "debug.h"18#include "disasm.h"19#include "disasm_bpf.h"20#include "dso.h"21#include "env.h"22#include "evsel.h"23#include "map.h"24#include "maps.h"25#include "namespaces.h"26#include "srcline.h"27#include "symbol.h"28#include "util.h"29 30static regex_t	 file_lineno;31 32/* These can be referred from the arch-dependent code */33static struct ins_ops call_ops;34static struct ins_ops dec_ops;35static struct ins_ops jump_ops;36static struct ins_ops mov_ops;37static struct ins_ops nop_ops;38static struct ins_ops lock_ops;39static struct ins_ops ret_ops;40static struct ins_ops load_store_ops;41static struct ins_ops arithmetic_ops;42 43static int jump__scnprintf(struct ins *ins, char *bf, size_t size,44			   struct ins_operands *ops, int max_ins_name);45static int call__scnprintf(struct ins *ins, char *bf, size_t size,46			   struct ins_operands *ops, int max_ins_name);47 48static void ins__sort(struct arch *arch);49static int disasm_line__parse(char *line, const char **namep, char **rawp);50static int disasm_line__parse_powerpc(struct disasm_line *dl);51static char *expand_tabs(char *line, char **storage, size_t *storage_len);52 53static __attribute__((constructor)) void symbol__init_regexpr(void)54{55	regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);56}57 58static int arch__grow_instructions(struct arch *arch)59{60	struct ins *new_instructions;61	size_t new_nr_allocated;62 63	if (arch->nr_instructions_allocated == 0 && arch->instructions)64		goto grow_from_non_allocated_table;65 66	new_nr_allocated = arch->nr_instructions_allocated + 128;67	new_instructions = realloc(arch->instructions, new_nr_allocated * sizeof(struct ins));68	if (new_instructions == NULL)69		return -1;70 71out_update_instructions:72	arch->instructions = new_instructions;73	arch->nr_instructions_allocated = new_nr_allocated;74	return 0;75 76grow_from_non_allocated_table:77	new_nr_allocated = arch->nr_instructions + 128;78	new_instructions = calloc(new_nr_allocated, sizeof(struct ins));79	if (new_instructions == NULL)80		return -1;81 82	memcpy(new_instructions, arch->instructions, arch->nr_instructions);83	goto out_update_instructions;84}85 86static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops)87{88	struct ins *ins;89 90	if (arch->nr_instructions == arch->nr_instructions_allocated &&91	    arch__grow_instructions(arch))92		return -1;93 94	ins = &arch->instructions[arch->nr_instructions];95	ins->name = strdup(name);96	if (!ins->name)97		return -1;98 99	ins->ops  = ops;100	arch->nr_instructions++;101 102	ins__sort(arch);103	return 0;104}105 106#include "arch/arc/annotate/instructions.c"107#include "arch/arm/annotate/instructions.c"108#include "arch/arm64/annotate/instructions.c"109#include "arch/csky/annotate/instructions.c"110#include "arch/loongarch/annotate/instructions.c"111#include "arch/mips/annotate/instructions.c"112#include "arch/x86/annotate/instructions.c"113#include "arch/powerpc/annotate/instructions.c"114#include "arch/riscv64/annotate/instructions.c"115#include "arch/s390/annotate/instructions.c"116#include "arch/sparc/annotate/instructions.c"117 118static struct arch architectures[] = {119	{120		.name = "arc",121		.init = arc__annotate_init,122	},123	{124		.name = "arm",125		.init = arm__annotate_init,126	},127	{128		.name = "arm64",129		.init = arm64__annotate_init,130	},131	{132		.name = "csky",133		.init = csky__annotate_init,134	},135	{136		.name = "mips",137		.init = mips__annotate_init,138		.objdump = {139			.comment_char = '#',140		},141	},142	{143		.name = "x86",144		.init = x86__annotate_init,145		.instructions = x86__instructions,146		.nr_instructions = ARRAY_SIZE(x86__instructions),147		.insn_suffix = "bwlq",148		.objdump =  {149			.comment_char = '#',150			.register_char = '%',151			.memory_ref_char = '(',152			.imm_char = '$',153		},154#ifdef HAVE_DWARF_SUPPORT155		.update_insn_state = update_insn_state_x86,156#endif157	},158	{159		.name = "powerpc",160		.init = powerpc__annotate_init,161#ifdef HAVE_DWARF_SUPPORT162		.update_insn_state = update_insn_state_powerpc,163#endif164	},165	{166		.name = "riscv64",167		.init = riscv64__annotate_init,168	},169	{170		.name = "s390",171		.init = s390__annotate_init,172		.objdump =  {173			.comment_char = '#',174		},175	},176	{177		.name = "sparc",178		.init = sparc__annotate_init,179		.objdump = {180			.comment_char = '#',181		},182	},183	{184		.name = "loongarch",185		.init = loongarch__annotate_init,186		.objdump = {187			.comment_char = '#',188		},189	},190};191 192static int arch__key_cmp(const void *name, const void *archp)193{194	const struct arch *arch = archp;195 196	return strcmp(name, arch->name);197}198 199static int arch__cmp(const void *a, const void *b)200{201	const struct arch *aa = a;202	const struct arch *ab = b;203 204	return strcmp(aa->name, ab->name);205}206 207static void arch__sort(void)208{209	const int nmemb = ARRAY_SIZE(architectures);210 211	qsort(architectures, nmemb, sizeof(struct arch), arch__cmp);212}213 214struct arch *arch__find(const char *name)215{216	const int nmemb = ARRAY_SIZE(architectures);217	static bool sorted;218 219	if (!sorted) {220		arch__sort();221		sorted = true;222	}223 224	return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);225}226 227bool arch__is(struct arch *arch, const char *name)228{229	return !strcmp(arch->name, name);230}231 232static void ins_ops__delete(struct ins_operands *ops)233{234	if (ops == NULL)235		return;236	zfree(&ops->source.raw);237	zfree(&ops->source.name);238	zfree(&ops->target.raw);239	zfree(&ops->target.name);240}241 242static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,243			      struct ins_operands *ops, int max_ins_name)244{245	return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw);246}247 248int ins__scnprintf(struct ins *ins, char *bf, size_t size,249		   struct ins_operands *ops, int max_ins_name)250{251	if (ins->ops->scnprintf)252		return ins->ops->scnprintf(ins, bf, size, ops, max_ins_name);253 254	return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);255}256 257bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)258{259	if (!arch || !arch->ins_is_fused)260		return false;261 262	return arch->ins_is_fused(arch, ins1, ins2);263}264 265static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,266		struct disasm_line *dl __maybe_unused)267{268	char *endptr, *tok, *name;269	struct map *map = ms->map;270	struct addr_map_symbol target = {271		.ms = { .map = map, },272	};273 274	ops->target.addr = strtoull(ops->raw, &endptr, 16);275 276	name = strchr(endptr, '<');277	if (name == NULL)278		goto indirect_call;279 280	name++;281 282	if (arch->objdump.skip_functions_char &&283	    strchr(name, arch->objdump.skip_functions_char))284		return -1;285 286	tok = strchr(name, '>');287	if (tok == NULL)288		return -1;289 290	*tok = '\0';291	ops->target.name = strdup(name);292	*tok = '>';293 294	if (ops->target.name == NULL)295		return -1;296find_target:297	target.addr = map__objdump_2mem(map, ops->target.addr);298 299	if (maps__find_ams(ms->maps, &target) == 0 &&300	    map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)301		ops->target.sym = target.ms.sym;302 303	return 0;304 305indirect_call:306	tok = strchr(endptr, '*');307	if (tok != NULL) {308		endptr++;309 310		/* Indirect call can use a non-rip register and offset: callq  *0x8(%rbx).311		 * Do not parse such instruction.  */312		if (strstr(endptr, "(%r") == NULL)313			ops->target.addr = strtoull(endptr, NULL, 16);314	}315	goto find_target;316}317 318static int call__scnprintf(struct ins *ins, char *bf, size_t size,319			   struct ins_operands *ops, int max_ins_name)320{321	if (ops->target.sym)322		return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);323 324	if (ops->target.addr == 0)325		return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);326 327	if (ops->target.name)328		return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.name);329 330	return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr);331}332 333static struct ins_ops call_ops = {334	.parse	   = call__parse,335	.scnprintf = call__scnprintf,336};337 338bool ins__is_call(const struct ins *ins)339{340	return ins->ops == &call_ops || ins->ops == &s390_call_ops || ins->ops == &loongarch_call_ops;341}342 343/*344 * Prevents from matching commas in the comment section, e.g.:345 * ffff200008446e70:       b.cs    ffff2000084470f4 <generic_exec_single+0x314>  // b.hs, b.nlast346 *347 * and skip comma as part of function arguments, e.g.:348 * 1d8b4ac <linemap_lookup(line_maps const*, unsigned int)+0xcc>349 */350static inline const char *validate_comma(const char *c, struct ins_operands *ops)351{352	if (ops->jump.raw_comment && c > ops->jump.raw_comment)353		return NULL;354 355	if (ops->jump.raw_func_start && c > ops->jump.raw_func_start)356		return NULL;357 358	return c;359}360 361static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,362		struct disasm_line *dl __maybe_unused)363{364	struct map *map = ms->map;365	struct symbol *sym = ms->sym;366	struct addr_map_symbol target = {367		.ms = { .map = map, },368	};369	const char *c = strchr(ops->raw, ',');370	u64 start, end;371 372	ops->jump.raw_comment = strchr(ops->raw, arch->objdump.comment_char);373	ops->jump.raw_func_start = strchr(ops->raw, '<');374 375	c = validate_comma(c, ops);376 377	/*378	 * Examples of lines to parse for the _cpp_lex_token@@Base379	 * function:380	 *381	 * 1159e6c: jne    115aa32 <_cpp_lex_token@@Base+0xf92>382	 * 1159e8b: jne    c469be <cpp_named_operator2name@@Base+0xa72>383	 *384	 * The first is a jump to an offset inside the same function,385	 * the second is to another function, i.e. that 0xa72 is an386	 * offset in the cpp_named_operator2name@@base function.387	 */388	/*389	 * skip over possible up to 2 operands to get to address, e.g.:390	 * tbnz	 w0, #26, ffff0000083cd190 <security_file_permission+0xd0>391	 */392	if (c++ != NULL) {393		ops->target.addr = strtoull(c, NULL, 16);394		if (!ops->target.addr) {395			c = strchr(c, ',');396			c = validate_comma(c, ops);397			if (c++ != NULL)398				ops->target.addr = strtoull(c, NULL, 16);399		}400	} else {401		ops->target.addr = strtoull(ops->raw, NULL, 16);402	}403 404	target.addr = map__objdump_2mem(map, ops->target.addr);405	start = map__unmap_ip(map, sym->start);406	end = map__unmap_ip(map, sym->end);407 408	ops->target.outside = target.addr < start || target.addr > end;409 410	/*411	 * FIXME: things like this in _cpp_lex_token (gcc's cc1 program):412 413		cpp_named_operator2name@@Base+0xa72414 415	 * Point to a place that is after the cpp_named_operator2name416	 * boundaries, i.e.  in the ELF symbol table for cc1417	 * cpp_named_operator2name is marked as being 32-bytes long, but it in418	 * fact is much larger than that, so we seem to need a symbols__find()419	 * routine that looks for >= current->start and  < next_symbol->start,420	 * possibly just for C++ objects?421	 *422	 * For now lets just make some progress by marking jumps to outside the423	 * current function as call like.424	 *425	 * Actual navigation will come next, with further understanding of how426	 * the symbol searching and disassembly should be done.427	 */428	if (maps__find_ams(ms->maps, &target) == 0 &&429	    map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)430		ops->target.sym = target.ms.sym;431 432	if (!ops->target.outside) {433		ops->target.offset = target.addr - start;434		ops->target.offset_avail = true;435	} else {436		ops->target.offset_avail = false;437	}438 439	return 0;440}441 442static int jump__scnprintf(struct ins *ins, char *bf, size_t size,443			   struct ins_operands *ops, int max_ins_name)444{445	const char *c;446 447	if (!ops->target.addr || ops->target.offset < 0)448		return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);449 450	if (ops->target.outside && ops->target.sym != NULL)451		return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);452 453	c = strchr(ops->raw, ',');454	c = validate_comma(c, ops);455 456	if (c != NULL) {457		const char *c2 = strchr(c + 1, ',');458 459		c2 = validate_comma(c2, ops);460		/* check for 3-op insn */461		if (c2 != NULL)462			c = c2;463		c++;464 465		/* mirror arch objdump's space-after-comma style */466		if (*c == ' ')467			c++;468	}469 470	return scnprintf(bf, size, "%-*s %.*s%" PRIx64, max_ins_name,471			 ins->name, c ? c - ops->raw : 0, ops->raw,472			 ops->target.offset);473}474 475static void jump__delete(struct ins_operands *ops __maybe_unused)476{477	/*478	 * The ops->jump.raw_comment and ops->jump.raw_func_start belong to the479	 * raw string, don't free them.480	 */481}482 483static struct ins_ops jump_ops = {484	.free	   = jump__delete,485	.parse	   = jump__parse,486	.scnprintf = jump__scnprintf,487};488 489bool ins__is_jump(const struct ins *ins)490{491	return ins->ops == &jump_ops || ins->ops == &loongarch_jump_ops;492}493 494static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)495{496	char *endptr, *name, *t;497 498	if (strstr(raw, "(%rip)") == NULL)499		return 0;500 501	*addrp = strtoull(comment, &endptr, 16);502	if (endptr == comment)503		return 0;504	name = strchr(endptr, '<');505	if (name == NULL)506		return -1;507 508	name++;509 510	t = strchr(name, '>');511	if (t == NULL)512		return 0;513 514	*t = '\0';515	*namep = strdup(name);516	*t = '>';517 518	return 0;519}520 521static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,522		struct disasm_line *dl __maybe_unused)523{524	ops->locked.ops = zalloc(sizeof(*ops->locked.ops));525	if (ops->locked.ops == NULL)526		return 0;527 528	if (disasm_line__parse(ops->raw, &ops->locked.ins.name, &ops->locked.ops->raw) < 0)529		goto out_free_ops;530 531	ops->locked.ins.ops = ins__find(arch, ops->locked.ins.name, 0);532 533	if (ops->locked.ins.ops == NULL)534		goto out_free_ops;535 536	if (ops->locked.ins.ops->parse &&537	    ops->locked.ins.ops->parse(arch, ops->locked.ops, ms, NULL) < 0)538		goto out_free_ops;539 540	return 0;541 542out_free_ops:543	zfree(&ops->locked.ops);544	return 0;545}546 547static int lock__scnprintf(struct ins *ins, char *bf, size_t size,548			   struct ins_operands *ops, int max_ins_name)549{550	int printed;551 552	if (ops->locked.ins.ops == NULL)553		return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);554 555	printed = scnprintf(bf, size, "%-*s ", max_ins_name, ins->name);556	return printed + ins__scnprintf(&ops->locked.ins, bf + printed,557					size - printed, ops->locked.ops, max_ins_name);558}559 560static void lock__delete(struct ins_operands *ops)561{562	struct ins *ins = &ops->locked.ins;563 564	if (ins->ops && ins->ops->free)565		ins->ops->free(ops->locked.ops);566	else567		ins_ops__delete(ops->locked.ops);568 569	zfree(&ops->locked.ops);570	zfree(&ops->locked.ins.name);571	zfree(&ops->target.raw);572	zfree(&ops->target.name);573}574 575static struct ins_ops lock_ops = {576	.free	   = lock__delete,577	.parse	   = lock__parse,578	.scnprintf = lock__scnprintf,579};580 581/*582 * Check if the operand has more than one registers like x86 SIB addressing:583 *   0x1234(%rax, %rbx, 8)584 *585 * But it doesn't care segment selectors like %gs:0x5678(%rcx), so just check586 * the input string after 'memory_ref_char' if exists.587 */588static bool check_multi_regs(struct arch *arch, const char *op)589{590	int count = 0;591 592	if (arch->objdump.register_char == 0)593		return false;594 595	if (arch->objdump.memory_ref_char) {596		op = strchr(op, arch->objdump.memory_ref_char);597		if (op == NULL)598			return false;599	}600 601	while ((op = strchr(op, arch->objdump.register_char)) != NULL) {602		count++;603		op++;604	}605 606	return count > 1;607}608 609static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused,610		struct disasm_line *dl __maybe_unused)611{612	char *s = strchr(ops->raw, ','), *target, *comment, prev;613 614	if (s == NULL)615		return -1;616 617	*s = '\0';618 619	/*620	 * x86 SIB addressing has something like 0x8(%rax, %rcx, 1)621	 * then it needs to have the closing parenthesis.622	 */623	if (strchr(ops->raw, '(')) {624		*s = ',';625		s = strchr(ops->raw, ')');626		if (s == NULL || s[1] != ',')627			return -1;628		*++s = '\0';629	}630 631	ops->source.raw = strdup(ops->raw);632	*s = ',';633 634	if (ops->source.raw == NULL)635		return -1;636 637	ops->source.multi_regs = check_multi_regs(arch, ops->source.raw);638 639	target = skip_spaces(++s);640	comment = strchr(s, arch->objdump.comment_char);641 642	if (comment != NULL)643		s = comment - 1;644	else645		s = strchr(s, '\0') - 1;646 647	while (s > target && isspace(s[0]))648		--s;649	s++;650	prev = *s;651	*s = '\0';652 653	ops->target.raw = strdup(target);654	*s = prev;655 656	if (ops->target.raw == NULL)657		goto out_free_source;658 659	ops->target.multi_regs = check_multi_regs(arch, ops->target.raw);660 661	if (comment == NULL)662		return 0;663 664	comment = skip_spaces(comment);665	comment__symbol(ops->source.raw, comment + 1, &ops->source.addr, &ops->source.name);666	comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);667 668	return 0;669 670out_free_source:671	zfree(&ops->source.raw);672	return -1;673}674 675static int mov__scnprintf(struct ins *ins, char *bf, size_t size,676			   struct ins_operands *ops, int max_ins_name)677{678	return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,679			 ops->source.name ?: ops->source.raw,680			 ops->target.name ?: ops->target.raw);681}682 683static struct ins_ops mov_ops = {684	.parse	   = mov__parse,685	.scnprintf = mov__scnprintf,686};687 688#define PPC_22_30(R)    (((R) >> 1) & 0x1ff)689#define MINUS_EXT_XO_FORM	234690#define SUB_EXT_XO_FORM		232691#define	ADD_ZERO_EXT_XO_FORM	202692#define	SUB_ZERO_EXT_XO_FORM	200693 694static int arithmetic__scnprintf(struct ins *ins, char *bf, size_t size,695		struct ins_operands *ops, int max_ins_name)696{697	return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,698			ops->raw);699}700 701/*702 * Sets the fields: multi_regs and "mem_ref".703 * "mem_ref" is set for ops->source which is later used to704 * fill the objdump->memory_ref-char field. This ops is currently705 * used by powerpc and since binary instruction code is used to706 * extract opcode, regs and offset, no other parsing is needed here.707 *708 * Dont set multi regs for 4 cases since it has only one operand709 * for source:710 * - Add to Minus One Extended XO-form ( Ex: addme, addmeo )711 * - Subtract From Minus One Extended XO-form ( Ex: subfme )712 * - Add to Zero Extended XO-form ( Ex: addze, addzeo )713 * - Subtract From Zero Extended XO-form ( Ex: subfze )714 */715static int arithmetic__parse(struct arch *arch __maybe_unused, struct ins_operands *ops,716		struct map_symbol *ms __maybe_unused, struct disasm_line *dl)717{718	int opcode = PPC_OP(dl->raw.raw_insn);719 720	ops->source.mem_ref = false;721	if (opcode == 31) {722		if ((opcode != MINUS_EXT_XO_FORM) && (opcode != SUB_EXT_XO_FORM) \723				&& (opcode != ADD_ZERO_EXT_XO_FORM) && (opcode != SUB_ZERO_EXT_XO_FORM))724			ops->source.multi_regs = true;725	}726 727	ops->target.mem_ref = false;728	ops->target.multi_regs = false;729 730	return 0;731}732 733static struct ins_ops arithmetic_ops = {734	.parse     = arithmetic__parse,735	.scnprintf = arithmetic__scnprintf,736};737 738static int load_store__scnprintf(struct ins *ins, char *bf, size_t size,739		struct ins_operands *ops, int max_ins_name)740{741	return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,742			ops->raw);743}744 745/*746 * Sets the fields: multi_regs and "mem_ref".747 * "mem_ref" is set for ops->source which is later used to748 * fill the objdump->memory_ref-char field. This ops is currently749 * used by powerpc and since binary instruction code is used to750 * extract opcode, regs and offset, no other parsing is needed here751 */752static int load_store__parse(struct arch *arch __maybe_unused, struct ins_operands *ops,753		struct map_symbol *ms __maybe_unused, struct disasm_line *dl __maybe_unused)754{755	ops->source.mem_ref = true;756	ops->source.multi_regs = false;757	/* opcode 31 is of X form */758	if (PPC_OP(dl->raw.raw_insn) == 31)759		ops->source.multi_regs = true;760 761	ops->target.mem_ref = false;762	ops->target.multi_regs = false;763 764	return 0;765}766 767static struct ins_ops load_store_ops = {768	.parse     = load_store__parse,769	.scnprintf = load_store__scnprintf,770};771 772static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused,773		struct disasm_line *dl __maybe_unused)774{775	char *target, *comment, *s, prev;776 777	target = s = ops->raw;778 779	while (s[0] != '\0' && !isspace(s[0]))780		++s;781	prev = *s;782	*s = '\0';783 784	ops->target.raw = strdup(target);785	*s = prev;786 787	if (ops->target.raw == NULL)788		return -1;789 790	comment = strchr(s, arch->objdump.comment_char);791	if (comment == NULL)792		return 0;793 794	comment = skip_spaces(comment);795	comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);796 797	return 0;798}799 800static int dec__scnprintf(struct ins *ins, char *bf, size_t size,801			   struct ins_operands *ops, int max_ins_name)802{803	return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,804			 ops->target.name ?: ops->target.raw);805}806 807static struct ins_ops dec_ops = {808	.parse	   = dec__parse,809	.scnprintf = dec__scnprintf,810};811 812static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,813			  struct ins_operands *ops __maybe_unused, int max_ins_name)814{815	return scnprintf(bf, size, "%-*s", max_ins_name, "nop");816}817 818static struct ins_ops nop_ops = {819	.scnprintf = nop__scnprintf,820};821 822static struct ins_ops ret_ops = {823	.scnprintf = ins__raw_scnprintf,824};825 826bool ins__is_nop(const struct ins *ins)827{828	return ins->ops == &nop_ops;829}830 831bool ins__is_ret(const struct ins *ins)832{833	return ins->ops == &ret_ops;834}835 836bool ins__is_lock(const struct ins *ins)837{838	return ins->ops == &lock_ops;839}840 841static int ins__key_cmp(const void *name, const void *insp)842{843	const struct ins *ins = insp;844 845	return strcmp(name, ins->name);846}847 848static int ins__cmp(const void *a, const void *b)849{850	const struct ins *ia = a;851	const struct ins *ib = b;852 853	return strcmp(ia->name, ib->name);854}855 856static void ins__sort(struct arch *arch)857{858	const int nmemb = arch->nr_instructions;859 860	qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);861}862 863static struct ins_ops *__ins__find(struct arch *arch, const char *name, struct disasm_line *dl)864{865	struct ins *ins;866	const int nmemb = arch->nr_instructions;867 868	if (arch__is(arch, "powerpc")) {869		/*870		 * For powerpc, identify the instruction ops871		 * from the opcode using raw_insn.872		 */873		struct ins_ops *ops;874 875		ops = check_ppc_insn(dl);876		if (ops)877			return ops;878	}879 880	if (!arch->sorted_instructions) {881		ins__sort(arch);882		arch->sorted_instructions = true;883	}884 885	ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);886	if (ins)887		return ins->ops;888 889	if (arch->insn_suffix) {890		char tmp[32];891		char suffix;892		size_t len = strlen(name);893 894		if (len == 0 || len >= sizeof(tmp))895			return NULL;896 897		suffix = name[len - 1];898		if (strchr(arch->insn_suffix, suffix) == NULL)899			return NULL;900 901		strcpy(tmp, name);902		tmp[len - 1] = '\0'; /* remove the suffix and check again */903 904		ins = bsearch(tmp, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);905	}906	return ins ? ins->ops : NULL;907}908 909struct ins_ops *ins__find(struct arch *arch, const char *name, struct disasm_line *dl)910{911	struct ins_ops *ops = __ins__find(arch, name, dl);912 913	if (!ops && arch->associate_instruction_ops)914		ops = arch->associate_instruction_ops(arch, name);915 916	return ops;917}918 919static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)920{921	dl->ins.ops = ins__find(arch, dl->ins.name, dl);922 923	if (!dl->ins.ops)924		return;925 926	if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, ms, dl) < 0)927		dl->ins.ops = NULL;928}929 930static int disasm_line__parse(char *line, const char **namep, char **rawp)931{932	char tmp, *name = skip_spaces(line);933 934	if (name[0] == '\0')935		return -1;936 937	*rawp = name + 1;938 939	while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))940		++*rawp;941 942	tmp = (*rawp)[0];943	(*rawp)[0] = '\0';944	*namep = strdup(name);945 946	if (*namep == NULL)947		goto out;948 949	(*rawp)[0] = tmp;950	*rawp = strim(*rawp);951 952	return 0;953 954out:955	return -1;956}957 958/*959 * Parses the result captured from symbol__disassemble_*960 * Example, line read from DSO file in powerpc:961 * line:    38 01 81 e8962 * opcode: fetched from arch specific get_opcode_insn963 * rawp_insn: e8810138964 *965 * rawp_insn is used later to extract the reg/offset fields966 */967#define	PPC_OP(op)	(((op) >> 26) & 0x3F)968#define	RAW_BYTES	11969 970static int disasm_line__parse_powerpc(struct disasm_line *dl)971{972	char *line = dl->al.line;973	const char **namep = &dl->ins.name;974	char **rawp = &dl->ops.raw;975	char *tmp_raw_insn, *name_raw_insn = skip_spaces(line);976	char *name = skip_spaces(name_raw_insn + RAW_BYTES);977	int objdump = 0;978 979	if (strlen(line) > RAW_BYTES)980		objdump = 1;981 982	if (name_raw_insn[0] == '\0')983		return -1;984 985	if (objdump) {986		disasm_line__parse(name, namep, rawp);987	} else988		*namep = "";989 990	tmp_raw_insn = strndup(name_raw_insn, 11);991	if (tmp_raw_insn == NULL)992		return -1;993 994	remove_spaces(tmp_raw_insn);995 996	sscanf(tmp_raw_insn, "%x", &dl->raw.raw_insn);997	if (objdump)998		dl->raw.raw_insn = be32_to_cpu(dl->raw.raw_insn);999 1000	return 0;1001}1002 1003static void annotation_line__init(struct annotation_line *al,1004				  struct annotate_args *args,1005				  int nr)1006{1007	al->offset = args->offset;1008	al->line = strdup(args->line);1009	al->line_nr = args->line_nr;1010	al->fileloc = args->fileloc;1011	al->data_nr = nr;1012}1013 1014static void annotation_line__exit(struct annotation_line *al)1015{1016	zfree_srcline(&al->path);1017	zfree(&al->line);1018	zfree(&al->cycles);1019	zfree(&al->br_cntr);1020}1021 1022static size_t disasm_line_size(int nr)1023{1024	struct annotation_line *al;1025 1026	return (sizeof(struct disasm_line) + (sizeof(al->data[0]) * nr));1027}1028 1029/*1030 * Allocating the disasm annotation line data with1031 * following structure:1032 *1033 *    -------------------------------------------1034 *    struct disasm_line | struct annotation_line1035 *    -------------------------------------------1036 *1037 * We have 'struct annotation_line' member as last member1038 * of 'struct disasm_line' to have an easy access.1039 */1040struct disasm_line *disasm_line__new(struct annotate_args *args)1041{1042	struct disasm_line *dl = NULL;1043	struct annotation *notes = symbol__annotation(args->ms.sym);1044	int nr = notes->src->nr_events;1045 1046	dl = zalloc(disasm_line_size(nr));1047	if (!dl)1048		return NULL;1049 1050	annotation_line__init(&dl->al, args, nr);1051	if (dl->al.line == NULL)1052		goto out_delete;1053 1054	if (args->offset != -1) {1055		if (arch__is(args->arch, "powerpc")) {1056			if (disasm_line__parse_powerpc(dl) < 0)1057				goto out_free_line;1058		} else if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)1059			goto out_free_line;1060 1061		disasm_line__init_ins(dl, args->arch, &args->ms);1062	}1063 1064	return dl;1065 1066out_free_line:1067	zfree(&dl->al.line);1068out_delete:1069	free(dl);1070	return NULL;1071}1072 1073void disasm_line__free(struct disasm_line *dl)1074{1075	if (dl->ins.ops && dl->ins.ops->free)1076		dl->ins.ops->free(&dl->ops);1077	else1078		ins_ops__delete(&dl->ops);1079	zfree(&dl->ins.name);1080	annotation_line__exit(&dl->al);1081	free(dl);1082}1083 1084int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name)1085{1086	if (raw || !dl->ins.ops)1087		return scnprintf(bf, size, "%-*s %s", max_ins_name, dl->ins.name, dl->ops.raw);1088 1089	return ins__scnprintf(&dl->ins, bf, size, &dl->ops, max_ins_name);1090}1091 1092/*1093 * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw)1094 * which looks like following1095 *1096 *  0000000000415500 <_init>:1097 *    415500:       sub    $0x8,%rsp1098 *    415504:       mov    0x2f5ad5(%rip),%rax        # 70afe0 <_DYNAMIC+0x2f8>1099 *    41550b:       test   %rax,%rax1100 *    41550e:       je     415515 <_init+0x15>1101 *    415510:       callq  416e70 <__gmon_start__@plt>1102 *    415515:       add    $0x8,%rsp1103 *    415519:       retq1104 *1105 * it will be parsed and saved into struct disasm_line as1106 *  <offset>       <name>  <ops.raw>1107 *1108 * The offset will be a relative offset from the start of the symbol and -11109 * means that it's not a disassembly line so should be treated differently.1110 * The ops.raw part will be parsed further according to type of the instruction.1111 */1112static int symbol__parse_objdump_line(struct symbol *sym,1113				      struct annotate_args *args,1114				      char *parsed_line, int *line_nr, char **fileloc)1115{1116	struct map *map = args->ms.map;1117	struct annotation *notes = symbol__annotation(sym);1118	struct disasm_line *dl;1119	char *tmp;1120	s64 line_ip, offset = -1;1121	regmatch_t match[2];1122 1123	/* /filename:linenr ? Save line number and ignore. */1124	if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) {1125		*line_nr = atoi(parsed_line + match[1].rm_so);1126		free(*fileloc);1127		*fileloc = strdup(parsed_line);1128		return 0;1129	}1130 1131	/* Process hex address followed by ':'. */1132	line_ip = strtoull(parsed_line, &tmp, 16);1133	if (parsed_line != tmp && tmp[0] == ':' && tmp[1] != '\0') {1134		u64 start = map__rip_2objdump(map, sym->start),1135		    end = map__rip_2objdump(map, sym->end);1136 1137		offset = line_ip - start;1138		if ((u64)line_ip < start || (u64)line_ip >= end)1139			offset = -1;1140		else1141			parsed_line = tmp + 1;1142	}1143 1144	args->offset  = offset;1145	args->line    = parsed_line;1146	args->line_nr = *line_nr;1147	args->fileloc = *fileloc;1148	args->ms.sym  = sym;1149 1150	dl = disasm_line__new(args);1151	(*line_nr)++;1152 1153	if (dl == NULL)1154		return -1;1155 1156	if (!disasm_line__has_local_offset(dl)) {1157		dl->ops.target.offset = dl->ops.target.addr -1158					map__rip_2objdump(map, sym->start);1159		dl->ops.target.offset_avail = true;1160	}1161 1162	/* kcore has no symbols, so add the call target symbol */1163	if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {1164		struct addr_map_symbol target = {1165			.addr = dl->ops.target.addr,1166			.ms = { .map = map, },1167		};1168 1169		if (!maps__find_ams(args->ms.maps, &target) &&1170		    target.ms.sym->start == target.al_addr)1171			dl->ops.target.sym = target.ms.sym;1172	}1173 1174	annotation_line__add(&dl->al, &notes->src->source);1175	return 0;1176}1177 1178static void delete_last_nop(struct symbol *sym)1179{1180	struct annotation *notes = symbol__annotation(sym);1181	struct list_head *list = &notes->src->source;1182	struct disasm_line *dl;1183 1184	while (!list_empty(list)) {1185		dl = list_entry(list->prev, struct disasm_line, al.node);1186 1187		if (dl->ins.ops) {1188			if (!ins__is_nop(&dl->ins))1189				return;1190		} else {1191			if (!strstr(dl->al.line, " nop ") &&1192			    !strstr(dl->al.line, " nopl ") &&1193			    !strstr(dl->al.line, " nopw "))1194				return;1195		}1196 1197		list_del_init(&dl->al.node);1198		disasm_line__free(dl);1199	}1200}1201 1202int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen)1203{1204	struct dso *dso = map__dso(ms->map);1205 1206	BUG_ON(buflen == 0);1207 1208	if (errnum >= 0) {1209		str_error_r(errnum, buf, buflen);1210		return 0;1211	}1212 1213	switch (errnum) {1214	case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {1215		char bf[SBUILD_ID_SIZE + 15] = " with build id ";1216		char *build_id_msg = NULL;1217 1218		if (dso__has_build_id(dso)) {1219			build_id__sprintf(dso__bid(dso), bf + 15);1220			build_id_msg = bf;1221		}1222		scnprintf(buf, buflen,1223			  "No vmlinux file%s\nwas found in the path.\n\n"1224			  "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"1225			  "Please use:\n\n"1226			  "  perf buildid-cache -vu vmlinux\n\n"1227			  "or:\n\n"1228			  "  --vmlinux vmlinux\n", build_id_msg ?: "");1229	}1230		break;1231	case SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF:1232		scnprintf(buf, buflen, "Please link with binutils's libopcode to enable BPF annotation");1233		break;1234	case SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP:1235		scnprintf(buf, buflen, "Problems with arch specific instruction name regular expressions.");1236		break;1237	case SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING:1238		scnprintf(buf, buflen, "Problems while parsing the CPUID in the arch specific initialization.");1239		break;1240	case SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE:1241		scnprintf(buf, buflen, "Invalid BPF file: %s.", dso__long_name(dso));1242		break;1243	case SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF:1244		scnprintf(buf, buflen, "The %s BPF file has no BTF section, compile with -g or use pahole -J.",1245			  dso__long_name(dso));1246		break;1247	default:1248		scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);1249		break;1250	}1251 1252	return 0;1253}1254 1255static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filename_size)1256{1257	char linkname[PATH_MAX];1258	char *build_id_filename;1259	char *build_id_path = NULL;1260	char *pos;1261	int len;1262 1263	if (dso__symtab_type(dso) == DSO_BINARY_TYPE__KALLSYMS &&1264	    !dso__is_kcore(dso))1265		return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;1266 1267	build_id_filename = dso__build_id_filename(dso, NULL, 0, false);1268	if (build_id_filename) {1269		__symbol__join_symfs(filename, filename_size, build_id_filename);1270		free(build_id_filename);1271	} else {1272		if (dso__has_build_id(dso))1273			return ENOMEM;1274		goto fallback;1275	}1276 1277	build_id_path = strdup(filename);1278	if (!build_id_path)1279		return ENOMEM;1280 1281	/*1282	 * old style build-id cache has name of XX/XXXXXXX.. while1283	 * new style has XX/XXXXXXX../{elf,kallsyms,vdso}.1284	 * extract the build-id part of dirname in the new style only.1285	 */1286	pos = strrchr(build_id_path, '/');1287	if (pos && strlen(pos) < SBUILD_ID_SIZE - 2)1288		dirname(build_id_path);1289 1290	if (dso__is_kcore(dso))1291		goto fallback;1292 1293	len = readlink(build_id_path, linkname, sizeof(linkname) - 1);1294	if (len < 0)1295		goto fallback;1296 1297	linkname[len] = '\0';1298	if (strstr(linkname, DSO__NAME_KALLSYMS) ||1299		access(filename, R_OK)) {1300fallback:1301		/*1302		 * If we don't have build-ids or the build-id file isn't in the1303		 * cache, or is just a kallsyms file, well, lets hope that this1304		 * DSO is the same as when 'perf record' ran.1305		 */1306		if (dso__kernel(dso) && dso__long_name(dso)[0] == '/')1307			snprintf(filename, filename_size, "%s", dso__long_name(dso));1308		else1309			__symbol__join_symfs(filename, filename_size, dso__long_name(dso));1310 1311		mutex_lock(dso__lock(dso));1312		if (access(filename, R_OK) && errno == ENOENT && dso__nsinfo(dso)) {1313			char *new_name = dso__filename_with_chroot(dso, filename);1314			if (new_name) {1315				strlcpy(filename, new_name, filename_size);1316				free(new_name);1317			}1318		}1319		mutex_unlock(dso__lock(dso));1320	} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) {1321		dso__set_binary_type(dso, DSO_BINARY_TYPE__BUILD_ID_CACHE);1322	}1323 1324	free(build_id_path);1325	return 0;1326}1327 1328#ifdef HAVE_LIBCAPSTONE_SUPPORT1329#include <capstone/capstone.h>1330 1331int capstone_init(struct machine *machine, csh *cs_handle, bool is64, bool disassembler_style);1332 1333static int open_capstone_handle(struct annotate_args *args, bool is_64bit,1334				csh *handle)1335{1336	struct annotation_options *opt = args->options;1337	cs_mode mode = is_64bit ? CS_MODE_64 : CS_MODE_32;1338 1339	/* TODO: support more architectures */1340	if (!arch__is(args->arch, "x86"))1341		return -1;1342 1343	if (cs_open(CS_ARCH_X86, mode, handle) != CS_ERR_OK)1344		return -1;1345 1346	if (!opt->disassembler_style ||1347	    !strcmp(opt->disassembler_style, "att"))1348		cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);1349 1350	/*1351	 * Resolving address operands to symbols is implemented1352	 * on x86 by investigating instruction details.1353	 */1354	cs_option(*handle, CS_OPT_DETAIL, CS_OPT_ON);1355 1356	return 0;1357}1358#endif1359 1360#if defined(HAVE_LIBCAPSTONE_SUPPORT) || defined(HAVE_LIBLLVM_SUPPORT)1361struct find_file_offset_data {1362	u64 ip;1363	u64 offset;1364};1365 1366/* This will be called for each PHDR in an ELF binary */1367static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg)1368{1369	struct find_file_offset_data *data = arg;1370 1371	if (start <= data->ip && data->ip < start + len) {1372		data->offset = pgoff + data->ip - start;1373		return 1;1374	}1375	return 0;1376}1377 1378static u8 *1379read_symbol(const char *filename, struct map *map, struct symbol *sym,1380	    u64 *len, bool *is_64bit)1381{1382	struct dso *dso = map__dso(map);1383	struct nscookie nsc;1384	u64 start = map__rip_2objdump(map, sym->start);1385	u64 end = map__rip_2objdump(map, sym->end);1386	int fd, count;1387	u8 *buf = NULL;1388	struct find_file_offset_data data = {1389		.ip = start,1390	};1391 1392	*is_64bit = false;1393 1394	nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);1395	fd = open(filename, O_RDONLY);1396	nsinfo__mountns_exit(&nsc);1397	if (fd < 0)1398		return NULL;1399 1400	if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data,1401			    is_64bit) == 0)1402		goto err;1403 1404	*len = end - start;1405	buf = malloc(*len);1406	if (buf == NULL)1407		goto err;1408 1409	count = pread(fd, buf, *len, data.offset);1410	close(fd);1411	fd = -1;1412 1413	if ((u64)count != *len)1414		goto err;1415 1416	return buf;1417 1418err:1419	if (fd >= 0)1420		close(fd);1421	free(buf);1422	return NULL;1423}1424#endif1425 1426#ifdef HAVE_LIBCAPSTONE_SUPPORT1427static void print_capstone_detail(cs_insn *insn, char *buf, size_t len,1428				  struct annotate_args *args, u64 addr)1429{1430	int i;1431	struct map *map = args->ms.map;1432	struct symbol *sym;1433 1434	/* TODO: support more architectures */1435	if (!arch__is(args->arch, "x86"))1436		return;1437 1438	if (insn->detail == NULL)1439		return;1440 1441	for (i = 0; i < insn->detail->x86.op_count; i++) {1442		cs_x86_op *op = &insn->detail->x86.operands[i];1443		u64 orig_addr;1444 1445		if (op->type != X86_OP_MEM)1446			continue;1447 1448		/* only print RIP-based global symbols for now */1449		if (op->mem.base != X86_REG_RIP)1450			continue;1451 1452		/* get the target address */1453		orig_addr = addr + insn->size + op->mem.disp;1454		addr = map__objdump_2mem(map, orig_addr);1455 1456		if (dso__kernel(map__dso(map))) {1457			/*1458			 * The kernel maps can be splitted into sections,1459			 * let's find the map first and the search the symbol.1460			 */1461			map = maps__find(map__kmaps(map), addr);1462			if (map == NULL)1463				continue;1464		}1465 1466		/* convert it to map-relative address for search */1467		addr = map__map_ip(map, addr);1468 1469		sym = map__find_symbol(map, addr);1470		if (sym == NULL)1471			continue;1472 1473		if (addr == sym->start) {1474			scnprintf(buf, len, "\t# %"PRIx64" <%s>",1475				  orig_addr, sym->name);1476		} else {1477			scnprintf(buf, len, "\t# %"PRIx64" <%s+%#"PRIx64">",1478				  orig_addr, sym->name, addr - sym->start);1479		}1480		break;1481	}1482}1483 1484static int symbol__disassemble_capstone_powerpc(char *filename, struct symbol *sym,1485					struct annotate_args *args)1486{1487	struct annotation *notes = symbol__annotation(sym);1488	struct map *map = args->ms.map;1489	struct dso *dso = map__dso(map);1490	struct nscookie nsc;1491	u64 start = map__rip_2objdump(map, sym->start);1492	u64 end = map__rip_2objdump(map, sym->end);1493	u64 len = end - start;1494	u64 offset;1495	int i, fd, count;1496	bool is_64bit = false;1497	bool needs_cs_close = false;1498	u8 *buf = NULL;1499	struct find_file_offset_data data = {1500		.ip = start,1501	};1502	csh handle;1503	char disasm_buf[512];1504	struct disasm_line *dl;1505	u32 *line;1506	bool disassembler_style = false;1507 1508	if (args->options->objdump_path)1509		return -1;1510 1511	nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);1512	fd = open(filename, O_RDONLY);1513	nsinfo__mountns_exit(&nsc);1514	if (fd < 0)1515		return -1;1516 1517	if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data,1518			    &is_64bit) == 0)1519		goto err;1520 1521	if (!args->options->disassembler_style ||1522			!strcmp(args->options->disassembler_style, "att"))1523		disassembler_style = true;1524 1525	if (capstone_init(maps__machine(args->ms.maps), &handle, is_64bit, disassembler_style) < 0)1526		goto err;1527 1528	needs_cs_close = true;1529 1530	buf = malloc(len);1531	if (buf == NULL)1532		goto err;1533 1534	count = pread(fd, buf, len, data.offset);1535	close(fd);1536	fd = -1;1537 1538	if ((u64)count != len)1539		goto err;1540 1541	line = (u32 *)buf;1542 1543	/* add the function address and name */1544	scnprintf(disasm_buf, sizeof(disasm_buf), "%#"PRIx64" <%s>:",1545		  start, sym->name);1546 1547	args->offset = -1;1548	args->line = disasm_buf;1549	args->line_nr = 0;1550	args->fileloc = NULL;1551	args->ms.sym = sym;1552 1553	dl = disasm_line__new(args);1554	if (dl == NULL)1555		goto err;1556 1557	annotation_line__add(&dl->al, &notes->src->source);1558 1559	/*1560	 * TODO: enable disassm for powerpc1561	 * count = cs_disasm(handle, buf, len, start, len, &insn);1562	 *1563	 * For now, only binary code is saved in disassembled line1564	 * to be used in "type" and "typeoff" sort keys. Each raw code1565	 * is 32 bit instruction. So use "len/4" to get the number of1566	 * entries.1567	 */1568	count = len/4;1569 1570	for (i = 0, offset = 0; i < count; i++) {1571		args->offset = offset;1572		sprintf(args->line, "%x", line[i]);1573 1574		dl = disasm_line__new(args);1575		if (dl == NULL)1576			goto err;1577 1578		annotation_line__add(&dl->al, &notes->src->source);1579 1580		offset += 4;1581	}1582 1583	/* It failed in the middle */1584	if (offset != len) {1585		struct list_head *list = &notes->src->source;1586 1587		/* Discard all lines and fallback to objdump */1588		while (!list_empty(list)) {1589			dl = list_first_entry(list, struct disasm_line, al.node);1590 1591			list_del_init(&dl->al.node);1592			disasm_line__free(dl);1593		}1594		count = -1;1595	}1596 1597out:1598	if (needs_cs_close)1599		cs_close(&handle);1600	free(buf);1601	return count < 0 ? count : 0;1602 1603err:1604	if (fd >= 0)1605		close(fd);1606	if (needs_cs_close) {1607		struct disasm_line *tmp;1608 1609		/*1610		 * It probably failed in the middle of the above loop.1611		 * Release any resources it might add.1612		 */1613		list_for_each_entry_safe(dl, tmp, &notes->src->source, al.node) {1614			list_del(&dl->al.node);1615			free(dl);1616		}1617	}1618	count = -1;1619	goto out;1620}1621 1622static int symbol__disassemble_capstone(char *filename, struct symbol *sym,1623					struct annotate_args *args)1624{1625	struct annotation *notes = symbol__annotation(sym);1626	struct map *map = args->ms.map;1627	u64 start = map__rip_2objdump(map, sym->start);1628	u64 len;1629	u64 offset;1630	int i, count;1631	bool is_64bit = false;1632	bool needs_cs_close = false;1633	u8 *buf = NULL;1634	csh handle;1635	cs_insn *insn;1636	char disasm_buf[512];1637	struct disasm_line *dl;1638 1639	if (args->options->objdump_path)1640		return -1;1641 1642	buf = read_symbol(filename, map, sym, &len, &is_64bit);1643	if (buf == NULL)1644		return -1;1645 1646	/* add the function address and name */1647	scnprintf(disasm_buf, sizeof(disasm_buf), "%#"PRIx64" <%s>:",1648		  start, sym->name);1649 1650	args->offset = -1;1651	args->line = disasm_buf;1652	args->line_nr = 0;1653	args->fileloc = NULL;1654	args->ms.sym = sym;1655 1656	dl = disasm_line__new(args);1657	if (dl == NULL)1658		goto err;1659 1660	annotation_line__add(&dl->al, &notes->src->source);1661 1662	if (open_capstone_handle(args, is_64bit, &handle) < 0)1663		goto err;1664 1665	needs_cs_close = true;1666 1667	count = cs_disasm(handle, buf, len, start, len, &insn);1668	for (i = 0, offset = 0; i < count; i++) {1669		int printed;1670 1671		printed = scnprintf(disasm_buf, sizeof(disasm_buf),1672				    "       %-7s %s",1673				    insn[i].mnemonic, insn[i].op_str);1674		print_capstone_detail(&insn[i], disasm_buf + printed,1675				      sizeof(disasm_buf) - printed, args,1676				      start + offset);1677 1678		args->offset = offset;1679		args->line = disasm_buf;1680 1681		dl = disasm_line__new(args);1682		if (dl == NULL)1683			goto err;1684 1685		annotation_line__add(&dl->al, &notes->src->source);1686 1687		offset += insn[i].size;1688	}1689 1690	/* It failed in the middle: probably due to unknown instructions */1691	if (offset != len) {1692		struct list_head *list = &notes->src->source;1693 1694		/* Discard all lines and fallback to objdump */1695		while (!list_empty(list)) {1696			dl = list_first_entry(list, struct disasm_line, al.node);1697 1698			list_del_init(&dl->al.node);1699			disasm_line__free(dl);1700		}1701		count = -1;1702	}1703 1704out:1705	if (needs_cs_close)1706		cs_close(&handle);1707	free(buf);1708	return count < 0 ? count : 0;1709 1710err:1711	if (needs_cs_close) {1712		struct disasm_line *tmp;1713 1714		/*1715		 * It probably failed in the middle of the above loop.1716		 * Release any resources it might add.1717		 */1718		list_for_each_entry_safe(dl, tmp, &notes->src->source, al.node) {1719			list_del(&dl->al.node);1720			free(dl);1721		}1722	}1723	count = -1;1724	goto out;1725}1726#endif1727 1728static int symbol__disassemble_raw(char *filename, struct symbol *sym,1729					struct annotate_args *args)1730{1731	struct annotation *notes = symbol__annotation(sym);1732	struct map *map = args->ms.map;1733	struct dso *dso = map__dso(map);1734	u64 start = map__rip_2objdump(map, sym->start);1735	u64 end = map__rip_2objdump(map, sym->end);1736	u64 len = end - start;1737	u64 offset;1738	int i, count;1739	u8 *buf = NULL;1740	char disasm_buf[512];1741	struct disasm_line *dl;1742	u32 *line;1743 1744	/* Return if objdump is specified explicitly */1745	if (args->options->objdump_path)1746		return -1;1747 1748	pr_debug("Reading raw instruction from : %s using dso__data_read_offset\n", filename);1749 1750	buf = malloc(len);1751	if (buf == NULL)1752		goto err;1753 1754	count = dso__data_read_offset(dso, NULL, sym->start, buf, len);1755 1756	line = (u32 *)buf;1757 1758	if ((u64)count != len)1759		goto err;1760 1761	/* add the function address and name */1762	scnprintf(disasm_buf, sizeof(disasm_buf), "%#"PRIx64" <%s>:",1763		  start, sym->name);1764 1765	args->offset = -1;1766	args->line = disasm_buf;1767	args->line_nr = 0;1768	args->fileloc = NULL;1769	args->ms.sym = sym;1770 1771	dl = disasm_line__new(args);1772	if (dl == NULL)1773		goto err;1774 1775	annotation_line__add(&dl->al, &notes->src->source);1776 1777	/* Each raw instruction is 4 byte */1778	count = len/4;1779 1780	for (i = 0, offset = 0; i < count; i++) {1781		args->offset = offset;1782		sprintf(args->line, "%x", line[i]);1783		dl = disasm_line__new(args);1784		if (dl == NULL)1785			goto err;1786 1787		annotation_line__add(&dl->al, &notes->src->source);1788		offset += 4;1789	}1790 1791	/* It failed in the middle */1792	if (offset != len) {1793		struct list_head *list = &notes->src->source;1794 1795		/* Discard all lines and fallback to objdump */1796		while (!list_empty(list)) {1797			dl = list_first_entry(list, struct disasm_line, al.node);1798 1799			list_del_init(&dl->al.node);1800			disasm_line__free(dl);1801		}1802		count = -1;1803	}1804 1805out:1806	free(buf);1807	return count < 0 ? count : 0;1808 1809err:1810	count = -1;1811	goto out;1812}1813 1814#ifdef HAVE_LIBLLVM_SUPPORT1815#include <llvm-c/Disassembler.h>1816#include <llvm-c/Target.h>1817#include "util/llvm-c-helpers.h"1818 1819struct symbol_lookup_storage {1820	u64 branch_addr;1821	u64 pcrel_load_addr;1822};1823 1824/*1825 * Whenever LLVM wants to resolve an address into a symbol, it calls this1826 * callback. We don't ever actually _return_ anything (in particular, because1827 * it puts quotation marks around what we return), but we use this as a hint1828 * that there is a branch or PC-relative address in the expression that we1829 * should add some textual annotation for after the instruction. The caller1830 * will use this information to add the actual annotation.1831 */1832static const char *1833symbol_lookup_callback(void *disinfo, uint64_t value,1834		       uint64_t *ref_type,1835		       uint64_t address __maybe_unused,1836		       const char **ref __maybe_unused)1837{1838	struct symbol_lookup_storage *storage = disinfo;1839 1840	if (*ref_type == LLVMDisassembler_ReferenceType_In_Branch)1841		storage->branch_addr = value;1842	else if (*ref_type == LLVMDisassembler_ReferenceType_In_PCrel_Load)1843		storage->pcrel_load_addr = value;1844	*ref_type = LLVMDisassembler_ReferenceType_InOut_None;1845	return NULL;1846}1847 1848static int symbol__disassemble_llvm(char *filename, struct symbol *sym,1849				    struct annotate_args *args)1850{1851	struct annotation *notes = symbol__annotation(sym);1852	struct map *map = args->ms.map;1853	struct dso *dso = map__dso(map);1854	u64 start = map__rip_2objdump(map, sym->start);1855	u8 *buf;1856	u64 len;1857	u64 pc;1858	bool is_64bit;1859	char triplet[64];1860	char disasm_buf[2048];1861	size_t disasm_len;1862	struct disasm_line *dl;1863	LLVMDisasmContextRef disasm = NULL;1864	struct symbol_lookup_storage storage;1865	char *line_storage = NULL;1866	size_t line_storage_len = 0;1867	int ret = -1;1868 1869	if (args->options->objdump_path)1870		return -1;1871 1872	LLVMInitializeAllTargetInfos();1873	LLVMInitializeAllTargetMCs();1874	LLVMInitializeAllDisassemblers();1875 1876	buf = read_symbol(filename, map, sym, &len, &is_64bit);1877	if (buf == NULL)1878		return -1;1879 1880	if (arch__is(args->arch, "x86")) {1881		if (is_64bit)1882			scnprintf(triplet, sizeof(triplet), "x86_64-pc-linux");1883		else1884			scnprintf(triplet, sizeof(triplet), "i686-pc-linux");1885	} else {1886		scnprintf(triplet, sizeof(triplet), "%s-linux-gnu",1887			  args->arch->name);1888	}1889 1890	disasm = LLVMCreateDisasm(triplet, &storage, 0, NULL,1891				  symbol_lookup_callback);1892	if (disasm == NULL)1893		goto err;1894 1895	if (args->options->disassembler_style &&1896	    !strcmp(args->options->disassembler_style, "intel"))1897		LLVMSetDisasmOptions(disasm,1898				     LLVMDisassembler_Option_AsmPrinterVariant);1899 1900	/*1901	 * This needs to be set after AsmPrinterVariant, due to a bug in LLVM;1902	 * setting AsmPrinterVariant makes a new instruction printer, making it1903	 * forget about the PrintImmHex flag (which is applied before if both1904	 * are given to the same call).1905	 */1906	LLVMSetDisasmOptions(disasm, LLVMDisassembler_Option_PrintImmHex);1907 1908	/* add the function address and name */1909	scnprintf(disasm_buf, sizeof(disasm_buf), "%#"PRIx64" <%s>:",1910		  start, sym->name);1911 1912	args->offset = -1;1913	args->line = disasm_buf;1914	args->line_nr = 0;1915	args->fileloc = NULL;1916	args->ms.sym = sym;1917 1918	dl = disasm_line__new(args);1919	if (dl == NULL)1920		goto err;1921 1922	annotation_line__add(&dl->al, &notes->src->source);1923 1924	pc = start;1925	for (u64 offset = 0; offset < len; ) {1926		unsigned int ins_len;1927 1928		storage.branch_addr = 0;1929		storage.pcrel_load_addr = 0;1930 1931		ins_len = LLVMDisasmInstruction(disasm, buf + offset,1932						len - offset, pc,1933						disasm_buf, sizeof(disasm_buf));1934		if (ins_len == 0)1935			goto err;1936		disasm_len = strlen(disasm_buf);1937 1938		if (storage.branch_addr != 0) {1939			char *name = llvm_name_for_code(dso, filename,1940							storage.branch_addr);1941			if (name != NULL) {1942				disasm_len += scnprintf(disasm_buf + disasm_len,1943							sizeof(disasm_buf) -1944								disasm_len,1945							" <%s>", name);1946				free(name);1947			}1948		}1949		if (storage.pcrel_load_addr != 0) {1950			char *name = llvm_name_for_data(dso, filename,1951							storage.pcrel_load_addr);1952			disasm_len += scnprintf(disasm_buf + disasm_len,1953						sizeof(disasm_buf) - disasm_len,1954						"  # %#"PRIx64,1955						storage.pcrel_load_addr);1956			if (name) {1957				disasm_len += scnprintf(disasm_buf + disasm_len,1958							sizeof(disasm_buf) -1959							disasm_len,1960							" <%s>", name);1961				free(name);1962			}1963		}1964 1965		args->offset = offset;1966		args->line = expand_tabs(disasm_buf, &line_storage,1967					 &line_storage_len);1968		args->line_nr = 0;1969		args->fileloc = NULL;1970		args->ms.sym = sym;1971 1972		llvm_addr2line(filename, pc, &args->fileloc,1973			       (unsigned int *)&args->line_nr, false, NULL);1974 1975		dl = disasm_line__new(args);1976		if (dl == NULL)1977			goto err;1978 1979		annotation_line__add(&dl->al, &notes->src->source);1980 1981		free(args->fileloc);1982		pc += ins_len;1983		offset += ins_len;1984	}1985 1986	ret = 0;1987 1988err:1989	LLVMDisasmDispose(disasm);1990	free(buf);1991	free(line_storage);1992	return ret;1993}1994#endif1995 1996/*1997 * Possibly create a new version of line with tabs expanded. Returns the1998 * existing or new line, storage is updated if a new line is allocated. If1999 * allocation fails then NULL is returned.2000 */2001static char *expand_tabs(char *line, char **storage, size_t *storage_len)2002{2003	size_t i, src, dst, len, new_storage_len, num_tabs;2004	char *new_line;2005	size_t line_len = strlen(line);2006 2007	for (num_tabs = 0, i = 0; i < line_len; i++)2008		if (line[i] == '\t')2009			num_tabs++;2010 2011	if (num_tabs == 0)2012		return line;2013 2014	/*2015	 * Space for the line and '\0', less the leading and trailing2016	 * spaces. Each tab may introduce 7 additional spaces.2017	 */2018	new_storage_len = line_len + 1 + (num_tabs * 7);2019 2020	new_line = malloc(new_storage_len);2021	if (new_line == NULL) {2022		pr_err("Failure allocating memory for tab expansion\n");2023		return NULL;2024	}2025 2026	/*2027	 * Copy regions starting at src and expand tabs. If there are two2028	 * adjacent tabs then 'src == i', the memcpy is of size 0 and the spaces2029	 * are inserted.2030	 */2031	for (i = 0, src = 0, dst = 0; i < line_len && num_tabs; i++) {2032		if (line[i] == '\t') {2033			len = i - src;2034			memcpy(&new_line[dst], &line[src], len);2035			dst += len;2036			new_line[dst++] = ' ';2037			while (dst % 8 != 0)2038				new_line[dst++] = ' ';2039			src = i + 1;2040			num_tabs--;2041		}2042	}2043 2044	/* Expand the last region. */2045	len = line_len - src;2046	memcpy(&new_line[dst], &line[src], len);2047	dst += len;2048	new_line[dst] = '\0';2049 2050	free(*storage);2051	*storage = new_line;2052	*storage_len = new_storage_len;2053	return new_line;2054}2055 2056int symbol__disassemble(struct symbol *sym, struct annotate_args *args)2057{2058	struct annotation_options *opts = &annotate_opts;2059	struct map *map = args->ms.map;2060	struct dso *dso = map__dso(map);2061	char *command;2062	FILE *file;2063	char symfs_filename[PATH_MAX];2064	struct kcore_extract kce;2065	bool delete_extract = false;2066	bool decomp = false;2067	int lineno = 0;2068	char *fileloc = NULL;2069	int nline;2070	char *line;2071	size_t line_len;2072	const char *objdump_argv[] = {2073		"/bin/sh",2074		"-c",2075		NULL, /* Will be the objdump command to run. */2076		"--",2077		NULL, /* Will be the symfs path. */2078		NULL,2079	};2080	struct child_process objdump_process;2081	int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));2082 2083	if (err)2084		return err;2085 2086	pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,2087		 symfs_filename, sym->name, map__unmap_ip(map, sym->start),2088		 map__unmap_ip(map, sym->end));2089 2090	pr_debug("annotating [%p] %30s : [%p] %30s\n",2091		 dso, dso__long_name(dso), sym, sym->name);2092 2093	if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {2094		return symbol__disassemble_bpf(sym, args);2095	} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) {2096		return symbol__disassemble_bpf_image(sym, args);2097	} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) {2098		return -1;2099	} else if (dso__is_kcore(dso)) {2100		kce.kcore_filename = symfs_filename;2101		kce.addr = map__rip_2objdump(map, sym->start);2102		kce.offs = sym->start;2103		kce.len = sym->end - sym->start;2104		if (!kcore_extract__create(&kce)) {2105			delete_extract = true;2106			strlcpy(symfs_filename, kce.extract_filename,2107				sizeof(symfs_filename));2108		}2109	} else if (dso__needs_decompress(dso)) {2110		char tmp[KMOD_DECOMP_LEN];2111 2112		if (dso__decompress_kmodule_path(dso, symfs_filename,2113						 tmp, sizeof(tmp)) < 0)2114			return -1;2115 2116		decomp = true;2117		strcpy(symfs_filename, tmp);2118	}2119 2120	/*2121	 * For powerpc data type profiling, use the dso__data_read_offset2122	 * to read raw instruction directly and interpret the binary code2123	 * to understand instructions and register fields. For sort keys as2124	 * type and typeoff, disassemble to mnemonic notation is2125	 * not required in case of powerpc.2126	 */2127	if (arch__is(args->arch, "powerpc")) {2128		extern const char *sort_order;2129 2130		if (sort_order && !strstr(sort_order, "sym")) {2131			err = symbol__disassemble_raw(symfs_filename, sym, args);2132			if (err == 0)2133				goto out_remove_tmp;2134#ifdef HAVE_LIBCAPSTONE_SUPPORT2135			err = symbol__disassemble_capstone_powerpc(symfs_filename, sym, args);2136			if (err == 0)2137				goto out_remove_tmp;2138#endif2139		}2140	}2141 2142#ifdef HAVE_LIBLLVM_SUPPORT2143	err = symbol__disassemble_llvm(symfs_filename, sym, args);2144	if (err == 0)2145		goto out_remove_tmp;2146#endif2147#ifdef HAVE_LIBCAPSTONE_SUPPORT2148	err = symbol__disassemble_capstone(symfs_filename, sym, args);2149	if (err == 0)2150		goto out_remove_tmp;2151#endif2152 2153	err = asprintf(&command,2154		 "%s %s%s --start-address=0x%016" PRIx642155		 " --stop-address=0x%016" PRIx642156		 " %s -d %s %s %s %c%s%c %s%s -C \"$1\"",2157		 opts->objdump_path ?: "objdump",2158		 opts->disassembler_style ? "-M " : "",2159		 opts->disassembler_style ?: "",2160		 map__rip_2objdump(map, sym->start),2161		 map__rip_2objdump(map, sym->end),2162		 opts->show_linenr ? "-l" : "",2163		 opts->show_asm_raw ? "" : "--no-show-raw-insn",2164		 opts->annotate_src ? "-S" : "",2165		 opts->prefix ? "--prefix " : "",2166		 opts->prefix ? '"' : ' ',2167		 opts->prefix ?: "",2168		 opts->prefix ? '"' : ' ',2169		 opts->prefix_strip ? "--prefix-strip=" : "",2170		 opts->prefix_strip ?: "");2171 2172	if (err < 0) {2173		pr_err("Failure allocating memory for the command to run\n");2174		goto out_remove_tmp;2175	}2176 2177	pr_debug("Executing: %s\n", command);2178 2179	objdump_argv[2] = command;2180	objdump_argv[4] = symfs_filename;2181 2182	/* Create a pipe to read from for stdout */2183	memset(&objdump_process, 0, sizeof(objdump_process));2184	objdump_process.argv = objdump_argv;2185	objdump_process.out = -1;2186	objdump_process.err = -1;2187	objdump_process.no_stderr = 1;2188	if (start_command(&objdump_process)) {2189		pr_err("Failure starting to run %s\n", command);2190		err = -1;2191		goto out_free_command;2192	}2193 2194	file = fdopen(objdump_process.out, "r");2195	if (!file) {2196		pr_err("Failure creating FILE stream for %s\n", command);2197		/*2198		 * If we were using debug info should retry with2199		 * original binary.2200		 */2201		err = -1;2202		goto out_close_stdout;2203	}2204 2205	/* Storage for getline. */2206	line = NULL;2207	line_len = 0;2208 2209	nline = 0;2210	while (!feof(file)) {2211		const char *match;2212		char *expanded_line;2213 2214		if (getline(&line, &line_len, file) < 0 || !line)2215			break;2216 2217		/* Skip lines containing "filename:" */2218		match = strstr(line, symfs_filename);2219		if (match && match[strlen(symfs_filename)] == ':')2220			continue;2221 2222		expanded_line = strim(line);2223		expanded_line = expand_tabs(expanded_line, &line, &line_len);2224		if (!expanded_line)2225			break;2226 2227		/*2228		 * The source code line number (lineno) needs to be kept in2229		 * across calls to symbol__parse_objdump_line(), so that it2230		 * can associate it with the instructions till the next one.2231		 * See disasm_line__new() and struct disasm_line::line_nr.2232		 */2233		if (symbol__parse_objdump_line(sym, args, expanded_line,2234					       &lineno, &fileloc) < 0)2235			break;2236		nline++;2237	}2238	free(line);2239	free(fileloc);2240 2241	err = finish_command(&objdump_process);2242	if (err)2243		pr_err("Error running %s\n", command);2244 2245	if (nline == 0) {2246		err = -1;2247		pr_err("No output from %s\n", command);2248	}2249 2250	/*2251	 * kallsyms does not have symbol sizes so there may a nop at the end.2252	 * Remove it.2253	 */2254	if (dso__is_kcore(dso))2255		delete_last_nop(sym);2256 2257	fclose(file);2258 2259out_close_stdout:2260	close(objdump_process.out);2261 2262out_free_command:2263	free(command);2264 2265out_remove_tmp:2266	if (decomp)2267		unlink(symfs_filename);2268 2269	if (delete_extract)2270		kcore_extract__delete(&kce);2271 2272	return err;2273}2274