X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=tools%2Fperf%2Futil%2Fannotate.c;h=4024d309bb00adaa2dbdb0a6e80afa2e6a5935a9;hb=f282f7a0ecc3e0b8fd8532a6c3e9401534cb907c;hp=e9825fe825fd65088ef807a3b54ca4a4a198ead7;hpb=396d10993f8d2ef410a6ca6a42724dc0211a8b42;p=cascardo%2Flinux.git diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index e9825fe825fd..4024d309bb00 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1123,7 +1123,46 @@ static void delete_last_nop(struct symbol *sym) } } -int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) +int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map, + int errnum, char *buf, size_t buflen) +{ + struct dso *dso = map->dso; + + BUG_ON(buflen == 0); + + if (errnum >= 0) { + str_error_r(errnum, buf, buflen); + return 0; + } + + switch (errnum) { + case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: { + char bf[SBUILD_ID_SIZE + 15] = " with build id "; + char *build_id_msg = NULL; + + if (dso->has_build_id) { + build_id__sprintf(dso->build_id, + sizeof(dso->build_id), bf + 15); + build_id_msg = bf; + } + scnprintf(buf, buflen, + "No vmlinux file%s\nwas found in the path.\n\n" + "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" + "Please use:\n\n" + " perf buildid-cache -vu vmlinux\n\n" + "or:\n\n" + " --vmlinux vmlinux\n", build_id_msg ?: ""); + } + break; + default: + scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum); + break; + } + + return 0; +} + +int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) { struct dso *dso = map->dso; char *filename = dso__build_id_filename(dso, NULL, 0); @@ -1134,22 +1173,20 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) char symfs_filename[PATH_MAX]; struct kcore_extract kce; bool delete_extract = false; + int stdout_fd[2]; int lineno = 0; int nline; + pid_t pid; if (filename) symbol__join_symfs(symfs_filename, filename); if (filename == NULL) { - if (dso->has_build_id) { - pr_err("Can't annotate %s: not enough memory\n", - sym->name); - return -ENOMEM; - } + if (dso->has_build_id) + return ENOMEM; goto fallback; - } else if (dso__is_kcore(dso)) { - goto fallback; - } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || + } else if (dso__is_kcore(dso) || + readlink(symfs_filename, command, sizeof(command)) < 0 || strstr(command, DSO__NAME_KALLSYMS) || access(symfs_filename, R_OK)) { free(filename); @@ -1166,27 +1203,7 @@ fallback: if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && !dso__is_kcore(dso)) { - char bf[SBUILD_ID_SIZE + 15] = " with build id "; - char *build_id_msg = NULL; - - if (dso->annotate_warned) - goto out_free_filename; - - if (dso->has_build_id) { - build_id__sprintf(dso->build_id, - sizeof(dso->build_id), bf + 15); - build_id_msg = bf; - } - err = -ENOENT; - dso->annotate_warned = 1; - pr_err("Can't annotate %s:\n\n" - "No vmlinux file%s\nwas found in the path.\n\n" - "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" - "Please use:\n\n" - " perf buildid-cache -vu vmlinux\n\n" - "or:\n\n" - " --vmlinux vmlinux\n", - sym->name, build_id_msg ?: ""); + err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; goto out_free_filename; } @@ -1258,9 +1275,32 @@ fallback: pr_debug("Executing: %s\n", command); - file = popen(command, "r"); + err = -1; + if (pipe(stdout_fd) < 0) { + pr_err("Failure creating the pipe to run %s\n", command); + goto out_remove_tmp; + } + + pid = fork(); + if (pid < 0) { + pr_err("Failure forking to run %s\n", command); + goto out_close_stdout; + } + + if (pid == 0) { + close(stdout_fd[0]); + dup2(stdout_fd[1], 1); + close(stdout_fd[1]); + execl("/bin/sh", "sh", "-c", command, NULL); + perror(command); + exit(-1); + } + + close(stdout_fd[1]); + + file = fdopen(stdout_fd[0], "r"); if (!file) { - pr_err("Failure running %s\n", command); + pr_err("Failure creating FILE stream for %s\n", command); /* * If we were using debug info should retry with * original binary. @@ -1286,9 +1326,11 @@ fallback: if (dso__is_kcore(dso)) delete_last_nop(sym); - pclose(file); - + fclose(file); + err = 0; out_remove_tmp: + close(stdout_fd[0]); + if (dso__needs_decompress(dso)) unlink(symfs_filename); out_free_filename: @@ -1297,6 +1339,10 @@ out_free_filename: if (free_filename) free(filename); return err; + +out_close_stdout: + close(stdout_fd[1]); + goto out_remove_tmp; } static void insert_source_line(struct rb_root *root, struct source_line *src_line) @@ -1663,7 +1709,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, struct rb_root source_line = RB_ROOT; u64 len; - if (symbol__annotate(sym, map, 0) < 0) + if (symbol__disassemble(sym, map, 0) < 0) return -1; len = symbol__size(sym);