Skip to content

Commit

Permalink
perf disasm: Introduce symbol__disassemble_objdump()
Browse files Browse the repository at this point in the history
With the first disassemble method in perf, the parsing of objdump
output, just like we have for llvm and capstone.

This paves the way to allow the user to specify what disassemblers are
preferred and to also to at some point allow building without the
objdump method.

Acked-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steinar H. Gunderson <sesse@google.com>
Link: https://lore.kernel.org/r/20241111151734.1018476-2-acme@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Arnaldo Carvalho de Melo committed Nov 11, 2024
1 parent ddbfb6f commit 4c1d8f0
Showing 1 changed file with 88 additions and 80 deletions.
168 changes: 88 additions & 80 deletions tools/perf/util/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2045,17 +2045,14 @@ static char *expand_tabs(char *line, char **storage, size_t *storage_len)
return new_line;
}

int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
struct annotate_args *args)
{
struct annotation_options *opts = &annotate_opts;
struct map *map = args->ms.map;
struct dso *dso = map__dso(map);
char *command;
FILE *file;
char symfs_filename[PATH_MAX];
struct kcore_extract kce;
bool delete_extract = false;
bool decomp = false;
int lineno = 0;
char *fileloc = NULL;
int nline;
Expand All @@ -2070,77 +2067,7 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
NULL,
};
struct child_process objdump_process;
int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));

if (err)
return err;

pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
symfs_filename, sym->name, map__unmap_ip(map, sym->start),
map__unmap_ip(map, sym->end));

pr_debug("annotating [%p] %30s : [%p] %30s\n",
dso, dso__long_name(dso), sym, sym->name);

if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
return symbol__disassemble_bpf(sym, args);
} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) {
return symbol__disassemble_bpf_image(sym, args);
} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) {
return -1;
} else if (dso__is_kcore(dso)) {
kce.kcore_filename = symfs_filename;
kce.addr = map__rip_2objdump(map, sym->start);
kce.offs = sym->start;
kce.len = sym->end - sym->start;
if (!kcore_extract__create(&kce)) {
delete_extract = true;
strlcpy(symfs_filename, kce.extract_filename,
sizeof(symfs_filename));
}
} else if (dso__needs_decompress(dso)) {
char tmp[KMOD_DECOMP_LEN];

if (dso__decompress_kmodule_path(dso, symfs_filename,
tmp, sizeof(tmp)) < 0)
return -1;

decomp = true;
strcpy(symfs_filename, tmp);
}

/*
* For powerpc data type profiling, use the dso__data_read_offset
* to read raw instruction directly and interpret the binary code
* to understand instructions and register fields. For sort keys as
* type and typeoff, disassemble to mnemonic notation is
* not required in case of powerpc.
*/
if (arch__is(args->arch, "powerpc")) {
extern const char *sort_order;

if (sort_order && !strstr(sort_order, "sym")) {
err = symbol__disassemble_raw(symfs_filename, sym, args);
if (err == 0)
goto out_remove_tmp;
#ifdef HAVE_LIBCAPSTONE_SUPPORT
err = symbol__disassemble_capstone_powerpc(symfs_filename, sym, args);
if (err == 0)
goto out_remove_tmp;
#endif
}
}

#ifdef HAVE_LIBLLVM_SUPPORT
err = symbol__disassemble_llvm(symfs_filename, sym, args);
if (err == 0)
goto out_remove_tmp;
#endif
#ifdef HAVE_LIBCAPSTONE_SUPPORT
err = symbol__disassemble_capstone(symfs_filename, sym, args);
if (err == 0)
goto out_remove_tmp;
#endif
int err;

err = asprintf(&command,
"%s %s%s --start-address=0x%016" PRIx64
Expand All @@ -2163,13 +2090,13 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)

if (err < 0) {
pr_err("Failure allocating memory for the command to run\n");
goto out_remove_tmp;
return err;
}

pr_debug("Executing: %s\n", command);

objdump_argv[2] = command;
objdump_argv[4] = symfs_filename;
objdump_argv[4] = filename;

/* Create a pipe to read from for stdout */
memset(&objdump_process, 0, sizeof(objdump_process));
Expand Down Expand Up @@ -2207,8 +2134,8 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
break;

/* Skip lines containing "filename:" */
match = strstr(line, symfs_filename);
if (match && match[strlen(symfs_filename)] == ':')
match = strstr(line, filename);
if (match && match[strlen(filename)] == ':')
continue;

expanded_line = strim(line);
Expand Down Expand Up @@ -2253,6 +2180,87 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)

out_free_command:
free(command);
return err;
}

int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
{
struct map *map = args->ms.map;
struct dso *dso = map__dso(map);
char symfs_filename[PATH_MAX];
bool delete_extract = false;
struct kcore_extract kce;
bool decomp = false;
int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));

if (err)
return err;

pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
symfs_filename, sym->name, map__unmap_ip(map, sym->start),
map__unmap_ip(map, sym->end));

pr_debug("annotating [%p] %30s : [%p] %30s\n", dso, dso__long_name(dso), sym, sym->name);

if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
return symbol__disassemble_bpf(sym, args);
} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) {
return symbol__disassemble_bpf_image(sym, args);
} else if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) {
return -1;
} else if (dso__is_kcore(dso)) {
kce.addr = map__rip_2objdump(map, sym->start);
kce.kcore_filename = symfs_filename;
kce.len = sym->end - sym->start;
kce.offs = sym->start;

if (!kcore_extract__create(&kce)) {
delete_extract = true;
strlcpy(symfs_filename, kce.extract_filename, sizeof(symfs_filename));
}
} else if (dso__needs_decompress(dso)) {
char tmp[KMOD_DECOMP_LEN];

if (dso__decompress_kmodule_path(dso, symfs_filename, tmp, sizeof(tmp)) < 0)
return -1;

decomp = true;
strcpy(symfs_filename, tmp);
}

/*
* For powerpc data type profiling, use the dso__data_read_offset to
* read raw instruction directly and interpret the binary code to
* understand instructions and register fields. For sort keys as type
* and typeoff, disassemble to mnemonic notation is not required in
* case of powerpc.
*/
if (arch__is(args->arch, "powerpc")) {
extern const char *sort_order;

if (sort_order && !strstr(sort_order, "sym")) {
err = symbol__disassemble_raw(symfs_filename, sym, args);
if (err == 0)
goto out_remove_tmp;
#ifdef HAVE_LIBCAPSTONE_SUPPORT
err = symbol__disassemble_capstone_powerpc(symfs_filename, sym, args);
if (err == 0)
goto out_remove_tmp;
#endif
}
}

#ifdef HAVE_LIBLLVM_SUPPORT
err = symbol__disassemble_llvm(symfs_filename, sym, args);
if (err == 0)
goto out_remove_tmp;
#endif
#ifdef HAVE_LIBCAPSTONE_SUPPORT
err = symbol__disassemble_capstone(symfs_filename, sym, args);
if (err == 0)
goto out_remove_tmp;
#endif
err = symbol__disassemble_objdump(symfs_filename, sym, args);

out_remove_tmp:
if (decomp)
Expand Down

0 comments on commit 4c1d8f0

Please sign in to comment.