summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/objtool/builtin-check.c3
-rw-r--r--tools/objtool/builtin.h2
-rw-r--r--tools/objtool/check.c18
-rw-r--r--tools/objtool/warn.h8
4 files changed, 25 insertions, 6 deletions
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 694abc628e9b..99f10c585cbe 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -29,7 +29,7 @@
29#include "builtin.h" 29#include "builtin.h"
30#include "check.h" 30#include "check.h"
31 31
32bool no_fp, no_unreachable, retpoline, module; 32bool no_fp, no_unreachable, retpoline, module, backtrace;
33 33
34static const char * const check_usage[] = { 34static const char * const check_usage[] = {
35 "objtool check [<options>] file.o", 35 "objtool check [<options>] file.o",
@@ -41,6 +41,7 @@ const struct option check_options[] = {
41 OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"), 41 OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"),
42 OPT_BOOLEAN('r', "retpoline", &retpoline, "Validate retpoline assumptions"), 42 OPT_BOOLEAN('r', "retpoline", &retpoline, "Validate retpoline assumptions"),
43 OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"), 43 OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"),
44 OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"),
44 OPT_END(), 45 OPT_END(),
45}; 46};
46 47
diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h
index 28ff40e19a14..65fd3cc3c98b 100644
--- a/tools/objtool/builtin.h
+++ b/tools/objtool/builtin.h
@@ -20,7 +20,7 @@
20#include <subcmd/parse-options.h> 20#include <subcmd/parse-options.h>
21 21
22extern const struct option check_options[]; 22extern const struct option check_options[];
23extern bool no_fp, no_unreachable, retpoline, module; 23extern bool no_fp, no_unreachable, retpoline, module, backtrace;
24 24
25extern int cmd_check(int argc, const char **argv); 25extern int cmd_check(int argc, const char **argv);
26extern int cmd_orc(int argc, const char **argv); 26extern int cmd_orc(int argc, const char **argv);
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 8d8191f25381..ccc66af5907f 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1885,8 +1885,11 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1885 if (!insn->ignore_alts) { 1885 if (!insn->ignore_alts) {
1886 list_for_each_entry(alt, &insn->alts, list) { 1886 list_for_each_entry(alt, &insn->alts, list) {
1887 ret = validate_branch(file, alt->insn, state); 1887 ret = validate_branch(file, alt->insn, state);
1888 if (ret) 1888 if (ret) {
1889 return 1; 1889 if (backtrace)
1890 BT_FUNC("(alt)", insn);
1891 return ret;
1892 }
1890 } 1893 }
1891 } 1894 }
1892 1895
@@ -1933,8 +1936,11 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1933 insn->jump_dest->func->pfunc == func)) { 1936 insn->jump_dest->func->pfunc == func)) {
1934 ret = validate_branch(file, insn->jump_dest, 1937 ret = validate_branch(file, insn->jump_dest,
1935 state); 1938 state);
1936 if (ret) 1939 if (ret) {
1937 return 1; 1940 if (backtrace)
1941 BT_FUNC("(branch)", insn);
1942 return ret;
1943 }
1938 1944
1939 } else if (func && has_modified_stack_frame(&state)) { 1945 } else if (func && has_modified_stack_frame(&state)) {
1940 WARN_FUNC("sibling call from callable instruction with modified stack frame", 1946 WARN_FUNC("sibling call from callable instruction with modified stack frame",
@@ -2005,6 +2011,8 @@ static int validate_unwind_hints(struct objtool_file *file)
2005 for_each_insn(file, insn) { 2011 for_each_insn(file, insn) {
2006 if (insn->hint && !insn->visited) { 2012 if (insn->hint && !insn->visited) {
2007 ret = validate_branch(file, insn, state); 2013 ret = validate_branch(file, insn, state);
2014 if (ret && backtrace)
2015 BT_FUNC("<=== (hint)", insn);
2008 warnings += ret; 2016 warnings += ret;
2009 } 2017 }
2010 } 2018 }
@@ -2133,6 +2141,8 @@ static int validate_functions(struct objtool_file *file)
2133 continue; 2141 continue;
2134 2142
2135 ret = validate_branch(file, insn, state); 2143 ret = validate_branch(file, insn, state);
2144 if (ret && backtrace)
2145 BT_FUNC("<=== (func)", insn);
2136 warnings += ret; 2146 warnings += ret;
2137 } 2147 }
2138 } 2148 }
diff --git a/tools/objtool/warn.h b/tools/objtool/warn.h
index afd9f7a05f6d..f4fbb972b611 100644
--- a/tools/objtool/warn.h
+++ b/tools/objtool/warn.h
@@ -64,6 +64,14 @@ static inline char *offstr(struct section *sec, unsigned long offset)
64 free(_str); \ 64 free(_str); \
65}) 65})
66 66
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
67#define WARN_ELF(format, ...) \ 75#define WARN_ELF(format, ...) \
68 WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1)) 76 WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1))
69 77