diff options
Diffstat (limited to 'tools/perf/util/annotate.c')
| -rw-r--r-- | tools/perf/util/annotate.c | 82 | 
1 files changed, 51 insertions, 31 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 683f8340460c..be1caabb9290 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -239,10 +239,20 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op  	const char *s = strchr(ops->raw, '+');  	const char *c = strchr(ops->raw, ','); -	if (c++ != NULL) +	/* +	 * skip over possible up to 2 operands to get to address, e.g.: +	 * tbnz	 w0, #26, ffff0000083cd190 <security_file_permission+0xd0> +	 */ +	if (c++ != NULL) {  		ops->target.addr = strtoull(c, NULL, 16); -	else +		if (!ops->target.addr) { +			c = strchr(c, ','); +			if (c++ != NULL) +				ops->target.addr = strtoull(c, NULL, 16); +		} +	} else {  		ops->target.addr = strtoull(ops->raw, NULL, 16); +	}  	if (s++ != NULL) {  		ops->target.offset = strtoull(s, NULL, 16); @@ -257,10 +267,27 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op  static int jump__scnprintf(struct ins *ins, char *bf, size_t size,  			   struct ins_operands *ops)  { +	const char *c = strchr(ops->raw, ','); +  	if (!ops->target.addr || ops->target.offset < 0)  		return ins__raw_scnprintf(ins, bf, size, ops); -	return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); +	if (c != NULL) { +		const char *c2 = strchr(c + 1, ','); + +		/* check for 3-op insn */ +		if (c2 != NULL) +			c = c2; +		c++; + +		/* mirror arch objdump's space-after-comma style */ +		if (*c == ' ') +			c++; +	} + +	return scnprintf(bf, size, "%-6.6s %.*s%" PRIx64, +			 ins->name, c ? c - ops->raw : 0, ops->raw, +			 ops->target.offset);  }  static struct ins_ops jump_ops = { @@ -1294,6 +1321,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil  	char linkname[PATH_MAX];  	char *build_id_filename;  	char *build_id_path = NULL; +	char *pos;  	if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&  	    !dso__is_kcore(dso)) @@ -1313,7 +1341,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil  	if (!build_id_path)  		return -1; -	dirname(build_id_path); +	/* +	 * old style build-id cache has name of XX/XXXXXXX.. while +	 * new style has XX/XXXXXXX../{elf,kallsyms,vdso}. +	 * extract the build-id part of dirname in the new style only. +	 */ +	pos = strrchr(build_id_path, '/'); +	if (pos && strlen(pos) < SBUILD_ID_SIZE - 2) +		dirname(build_id_path);  	if (dso__is_kcore(dso) ||  	    readlink(build_id_path, linkname, sizeof(linkname)) < 0 || @@ -1344,7 +1379,9 @@ static const char *annotate__norm_arch(const char *arch_name)  	return normalize_arch((char *)arch_name);  } -int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize) +int symbol__disassemble(struct symbol *sym, struct map *map, +			const char *arch_name, size_t privsize, +			struct arch **parch)  {  	struct dso *dso = map->dso;  	char command[PATH_MAX * 2]; @@ -1370,6 +1407,9 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na  	if (arch == NULL)  		return -ENOTSUP; +	if (parch) +		*parch = arch; +  	if (arch->init) {  		err = arch->init(arch);  		if (err) { @@ -1396,31 +1436,10 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na  				sizeof(symfs_filename));  		}  	} else if (dso__needs_decompress(dso)) { -		char tmp[PATH_MAX]; -		struct kmod_path m; -		int fd; -		bool ret; - -		if (kmod_path__parse_ext(&m, symfs_filename)) -			goto out; - -		snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX"); - -		fd = mkstemp(tmp); -		if (fd < 0) { -			free(m.ext); -			goto out; -		} - -		ret = decompress_to_file(m.ext, symfs_filename, fd); - -		if (ret) -			pr_err("Cannot decompress %s %s\n", m.ext, symfs_filename); - -		free(m.ext); -		close(fd); +		char tmp[KMOD_DECOMP_LEN]; -		if (!ret) +		if (dso__decompress_kmodule_path(dso, symfs_filename, +						 tmp, sizeof(tmp)) < 0)  			goto out;  		strcpy(symfs_filename, tmp); @@ -1429,7 +1448,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na  	snprintf(command, sizeof(command),  		 "%s %s%s --start-address=0x%016" PRIx64  		 " --stop-address=0x%016" PRIx64 -		 " -l -d %s %s -C %s 2>/dev/null|grep -v %s:|expand", +		 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",  		 objdump_path ? objdump_path : "objdump",  		 disassembler_style ? "-M " : "",  		 disassembler_style ? disassembler_style : "", @@ -1887,7 +1906,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,  	struct rb_root source_line = RB_ROOT;  	u64 len; -	if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 0) < 0) +	if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), +				0, NULL) < 0)  		return -1;  	len = symbol__size(sym);  |