Skip to content

Commit 7697eee

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
objtool: Add --backtrace support
For when you want to know the path that reached your fail state: $ ./objtool check --no-fp --backtrace arch/x86/lib/usercopy_64.o arch/x86/lib/usercopy_64.o: warning: objtool: .altinstr_replacement+0x3: UACCESS disable without MEMOPs: __clear_user() arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x3a: (alt) arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x2e: (branch) arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x18: (branch) arch/x86/lib/usercopy_64.o: warning: objtool: .altinstr_replacement+0xffffffffffffffff: (branch) arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x5: (alt) arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x0: <=== (func) 0000000000000000 <__clear_user>: 0: e8 00 00 00 00 callq 5 <__clear_user+0x5> 1: R_X86_64_PLT32 __fentry__-0x4 5: 90 nop 6: 90 nop 7: 90 nop 8: 48 89 f0 mov %rsi,%rax b: 48 c1 ee 03 shr $0x3,%rsi f: 83 e0 07 and $0x7,%eax 12: 48 89 f1 mov %rsi,%rcx 15: 48 85 c9 test %rcx,%rcx 18: 74 0f je 29 <__clear_user+0x29> 1a: 48 c7 07 00 00 00 00 movq $0x0,(%rdi) 21: 48 83 c7 08 add $0x8,%rdi 25: ff c9 dec %ecx 27: 75 f1 jne 1a <__clear_user+0x1a> 29: 48 89 c1 mov %rax,%rcx 2c: 85 c9 test %ecx,%ecx 2e: 74 0a je 3a <__clear_user+0x3a> 30: c6 07 00 movb $0x0,(%rdi) 33: 48 ff c7 inc %rdi 36: ff c9 dec %ecx 38: 75 f6 jne 30 <__clear_user+0x30> 3a: 90 nop 3b: 90 nop 3c: 90 nop 3d: 48 89 c8 mov %rcx,%rax 40: c3 retq Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent aaf5c62 commit 7697eee

File tree

4 files changed

+25
-6
lines changed

4 files changed

+25
-6
lines changed

tools/objtool/builtin-check.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "builtin.h"
3030
#include "check.h"
3131

32-
bool no_fp, no_unreachable, retpoline, module;
32+
bool no_fp, no_unreachable, retpoline, module, backtrace;
3333

3434
static const char * const check_usage[] = {
3535
"objtool check [<options>] file.o",
@@ -41,6 +41,7 @@ const struct option check_options[] = {
4141
OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"),
4242
OPT_BOOLEAN('r', "retpoline", &retpoline, "Validate retpoline assumptions"),
4343
OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"),
44+
OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"),
4445
OPT_END(),
4546
};
4647

tools/objtool/builtin.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <subcmd/parse-options.h>
2121

2222
extern const struct option check_options[];
23-
extern bool no_fp, no_unreachable, retpoline, module;
23+
extern bool no_fp, no_unreachable, retpoline, module, backtrace;
2424

2525
extern int cmd_check(int argc, const char **argv);
2626
extern int cmd_orc(int argc, const char **argv);

tools/objtool/check.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,8 +1885,11 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
18851885
if (!insn->ignore_alts) {
18861886
list_for_each_entry(alt, &insn->alts, list) {
18871887
ret = validate_branch(file, alt->insn, state);
1888-
if (ret)
1889-
return 1;
1888+
if (ret) {
1889+
if (backtrace)
1890+
BT_FUNC("(alt)", insn);
1891+
return ret;
1892+
}
18901893
}
18911894
}
18921895

@@ -1933,8 +1936,11 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
19331936
insn->jump_dest->func->pfunc == func)) {
19341937
ret = validate_branch(file, insn->jump_dest,
19351938
state);
1936-
if (ret)
1937-
return 1;
1939+
if (ret) {
1940+
if (backtrace)
1941+
BT_FUNC("(branch)", insn);
1942+
return ret;
1943+
}
19381944

19391945
} else if (func && has_modified_stack_frame(&state)) {
19401946
WARN_FUNC("sibling call from callable instruction with modified stack frame",
@@ -2005,6 +2011,8 @@ static int validate_unwind_hints(struct objtool_file *file)
20052011
for_each_insn(file, insn) {
20062012
if (insn->hint && !insn->visited) {
20072013
ret = validate_branch(file, insn, state);
2014+
if (ret && backtrace)
2015+
BT_FUNC("<=== (hint)", insn);
20082016
warnings += ret;
20092017
}
20102018
}
@@ -2133,6 +2141,8 @@ static int validate_functions(struct objtool_file *file)
21332141
continue;
21342142

21352143
ret = validate_branch(file, insn, state);
2144+
if (ret && backtrace)
2145+
BT_FUNC("<=== (func)", insn);
21362146
warnings += ret;
21372147
}
21382148
}

tools/objtool/warn.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@ static inline char *offstr(struct section *sec, unsigned long offset)
6464
free(_str); \
6565
})
6666

67+
#define BT_FUNC(format, insn, ...) \
68+
({ \
69+
struct instruction *_insn = (insn); \
70+
char *_str = offstr(_insn->sec, _insn->offset); \
71+
WARN(" %s: " format, _str, ##__VA_ARGS__); \
72+
free(_str); \
73+
})
74+
6775
#define WARN_ELF(format, ...) \
6876
WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1))
6977

0 commit comments

Comments
 (0)