objtool: Add option to print section addresses
authorJosh Poimboeuf <jpoimboe@redhat.com>
Mon, 18 Apr 2022 16:50:31 +0000 (09:50 -0700)
committerPeter Zijlstra <peterz@infradead.org>
Fri, 22 Apr 2022 10:32:02 +0000 (12:32 +0200)
To help prevent objtool users from having to do math to convert function
addresses to section addresses, and to help out with finding data
addresses reported by IBT validation, add an option to print the section
address in addition to the function address.

Normal:

  vmlinux.o: warning: objtool: fixup_exception()+0x2d1: unreachable instruction

With '--sec-address':

  vmlinux.o: warning: objtool: fixup_exception()+0x2d1 (.text+0x76c51): unreachable instruction

Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Link: https://lkml.kernel.org/r/2cea4d5299d53d1a4c09212a6ad7820aa46fda7a.1650300597.git.jpoimboe@redhat.com
tools/objtool/builtin-check.c
tools/objtool/include/objtool/builtin.h
tools/objtool/include/objtool/warn.h

index 8c3eed5b67e4bee93f7713492451bb754f5f1323..6acfebd2c6ca1ad4e55778af22195ec6a07d2f70 100644 (file)
@@ -50,6 +50,7 @@ const struct option check_options[] = {
        OPT_BOOLEAN(0, "module", &opts.module, "object is part of a kernel module"),
        OPT_BOOLEAN(0, "no-fp", &opts.no_fp, "skip frame pointer validation"),
        OPT_BOOLEAN(0, "no-unreachable", &opts.no_unreachable, "skip 'unreachable instruction' warnings"),
+       OPT_BOOLEAN(0, "sec-address", &opts.sec_address, "print section addresses in warnings"),
        OPT_BOOLEAN(0, "stats", &opts.stats, "print statistics"),
        OPT_BOOLEAN(0, "vmlinux", &opts.vmlinux, "vmlinux.o validation"),
 
index 44548e24473c706fc1ab9866f1fca9ef352ab224..e0972fbfa09eca9362d07ce15c755a14d455b4ac 100644 (file)
@@ -28,6 +28,7 @@ struct opts {
        bool module;
        bool no_fp;
        bool no_unreachable;
+       bool sec_address;
        bool stats;
        bool vmlinux;
 };
index c4bde3e2a79c2e069d2fe8656e7595a90e55b30b..a3e79ae75f2e8f4f55c84898e1ff81a4a10f93a9 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <objtool/builtin.h>
 #include <objtool/elf.h>
 
 extern const char *objname;
 
 static inline char *offstr(struct section *sec, unsigned long offset)
 {
-       struct symbol *func;
-       char *name, *str;
-       unsigned long name_off;
+       bool is_text = (sec->sh.sh_flags & SHF_EXECINSTR);
+       struct symbol *sym = NULL;
+       char *str;
+       int len;
 
-       func = find_func_containing(sec, offset);
-       if (!func)
-               func = find_symbol_containing(sec, offset);
-       if (func) {
-               name = func->name;
-               name_off = offset - func->offset;
+       if (is_text)
+               sym = find_func_containing(sec, offset);
+       if (!sym)
+               sym = find_symbol_containing(sec, offset);
+
+       if (sym) {
+               str = malloc(strlen(sym->name) + strlen(sec->name) + 40);
+               len = sprintf(str, "%s+0x%lx", sym->name, offset - sym->offset);
+               if (opts.sec_address)
+                       sprintf(str+len, " (%s+0x%lx)", sec->name, offset);
        } else {
-               name = sec->name;
-               name_off = offset;
+               str = malloc(strlen(sec->name) + 20);
+               sprintf(str, "%s+0x%lx", sec->name, offset);
        }
 
-       str = malloc(strlen(name) + 20);
-       sprintf(str, "%s+0x%lx", name, name_off);
-
        return str;
 }