[PATCH] perf annotate: check that objdump correctly works
From: Alexis Berlemont
Date: Wed Nov 30 2016 - 19:09:40 EST
Before disassembling, the tool objdump is called just to be sure:
* objdump is available in the path;
* objdump is an executable binary;
* objdump has no dependency issue or anything else.
This objdump "pre-"command is only necessary because the real objdump
command is followed by some " | grep ..."; this prevents the shell
from returning the exit code of objdump execution.
Signed-off-by: Alexis Berlemont <alexis.berlemont@xxxxxxxxx>
---
tools/perf/util/annotate.c | 79 +++++++++++++++++++++++++++++++++++++++++++++-
tools/perf/util/annotate.h | 3 ++
2 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 3e34ee0..9d6c3a0 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -20,9 +20,12 @@
#include "block-range.h"
#include "arch/common.h"
#include <regex.h>
+#include <unistd.h>
#include <pthread.h>
#include <linux/bitops.h>
#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/wait.h>
const char *disassembler_style;
const char *objdump_path;
@@ -1278,6 +1281,21 @@ int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *
" --vmlinux vmlinux\n", build_id_msg ?: "");
}
break;
+
+ case SYMBOL_ANNOTATE_ERRNO__NO_OBJDUMP:
+ scnprintf(buf, buflen, "No objdump tool available in $PATH\n");
+ break;
+
+ case SYMBOL_ANNOTATE_ERRNO__NO_EXEC_OBJDUMP:
+ scnprintf(buf, buflen,
+ "The objdump tool found in $PATH cannot be executed\n");
+ break;
+
+ case SYMBOL_ANNOTATE_ERRNO__NO_OUTPUT:
+ scnprintf(buf, buflen,
+ "The objdump tool returned no disassembled code\n");
+ break;
+
default:
scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
break;
@@ -1321,6 +1339,61 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
return 0;
}
+static int annotate__check_objdump(void)
+{
+ char command[PATH_MAX * 2];
+ int wstatus, err;
+ pid_t pid;
+
+ snprintf(command, sizeof(command),
+ "%s -v > /dev/null 2>&1",
+ objdump_path ? objdump_path : "objdump");
+
+ pid = fork();
+ if (pid < 0) {
+ pr_err("Failure forking to run %s\n", command);
+ return -1;
+ }
+
+ if (pid == 0) {
+ execl("/bin/sh", "sh", "-c", command, NULL);
+ exit(-1);
+ }
+
+ err = waitpid(pid, &wstatus, 0);
+ if (err < 0) {
+ pr_err("Failure calling waitpid: %s: (%s)\n",
+ strerror(errno), command);
+ return -1;
+ }
+
+ pr_err("%s: %d %d\n", command, pid, WEXITSTATUS(wstatus));
+
+ switch (WEXITSTATUS(wstatus)) {
+ case 0:
+ /* Success */
+ err = 0;
+ break;
+ case 127:
+ /* The shell did not find objdump in the path */
+ err = SYMBOL_ANNOTATE_ERRNO__NO_OBJDUMP;
+ break;
+ default:
+ /*
+ * In the default case, we consider that objdump
+ * cannot be executed; so it gathers many fault
+ * scenarii:
+ * - objdump is not an executable (126);
+ * - objdump has some dependency issue;
+ * - ...
+ */
+ err = SYMBOL_ANNOTATE_ERRNO__NO_EXEC_OBJDUMP;
+ break;
+ }
+
+ return err;
+}
+
static const char *annotate__norm_arch(const char *arch_name)
{
struct utsname uts;
@@ -1351,6 +1424,10 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
if (err)
return err;
+ err = annotate__check_objdump();
+ if (err)
+ return err;
+
arch_name = annotate__norm_arch(arch_name);
if (!arch_name)
return -1;
@@ -1482,7 +1559,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
delete_last_nop(sym);
fclose(file);
- err = 0;
+ err = nline == 0 ? SYMBOL_ANNOTATE_ERRNO__NO_OUTPUT : 0;
out_remove_tmp:
close(stdout_fd[0]);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 87e4cad..123f60c 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -172,6 +172,9 @@ enum symbol_disassemble_errno {
__SYMBOL_ANNOTATE_ERRNO__START = -10000,
SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START,
+ SYMBOL_ANNOTATE_ERRNO__NO_EXEC_OBJDUMP,
+ SYMBOL_ANNOTATE_ERRNO__NO_OBJDUMP,
+ SYMBOL_ANNOTATE_ERRNO__NO_OUTPUT,
__SYMBOL_ANNOTATE_ERRNO__END,
};
--
2.10.2