History

objtool: Disassemble instruction on warning or backtrace

When an instruction warning (WARN_INSN) or backtrace (BT_INSN) is issued, disassemble the instruction to provide more context.

Alexandre Chartre committed 11 months ago

Commit 0bb080b1 parent d4e13c25 files · +58 −14Browse files

Unified · Split

5 files
  1. tools/objtool/check.c +30 −6
  2. tools/objtool/disas.c +2 −3
  3. tools/objtool/include/objtool/check.h +2 −0
  4. tools/objtool/include/objtool/disas.h +13 −0
  5. tools/objtool/include/objtool/warn.h +11 −5
tools/objtool/check.c+30−6
@@ -4792,11 +4792,34 @@ static void free_insns(struct objtool_file *file) · 4791 unmodified lines
47924792 free(chunk->addr);
47934793 }
47944794
4795+static struct disas_context *objtool_disas_ctx;
4796+
4797+const char *objtool_disas_insn(struct instruction *insn)
4798+{
4799+ struct disas_context *dctx = objtool_disas_ctx;
4800+
4801+ if (!dctx)
4802+ return "";
4803+
4804+ disas_insn(dctx, insn);
4805+ return disas_result(dctx);
4806+}
4807+
47954808 int check(struct objtool_file *file)
47964809 {
4797− struct disas_context *disas_ctx;
4810+ struct disas_context *disas_ctx = NULL;
47984811 int ret = 0, warnings = 0;
47994812
4813+ /*
4814+ * If the verbose or backtrace option is used then we need a
4815+ * disassembly context to disassemble instruction or function
4816+ * on warning or backtrace.
4817+ */
4818+ if (opts.verbose || opts.backtrace) {
4819+ disas_ctx = disas_context_create(file);
4820+ objtool_disas_ctx = disas_ctx;
4821+ }
4822+
48004823 arch_initial_func_cfi_state(&initial_func_cfi);
48014824 init_cfi_state(&init_cfi);
48024825 init_cfi_state(&func_cfi);
@@ -4936,11 +4959,12 @@ out: · 133 unmodified lines
49364959 if (opts.verbose) {
49374960 if (opts.werror && warnings)
49384961 WARN("%d warning(s) upgraded to errors", warnings);
4939− disas_ctx = disas_context_create(file);
4940− if (disas_ctx) {
4941− disas_warned_funcs(disas_ctx);
4942− disas_context_destroy(disas_ctx);
4943− }
4962+ disas_warned_funcs(disas_ctx);
4963+ }
4964+
4965+ if (disas_ctx) {
4966+ disas_context_destroy(disas_ctx);
4967+ objtool_disas_ctx = NULL;
49444968 }
49454969
49464970 free_insns(file);
tools/objtool/disas.c+2−3
@@ -303,7 +303,7 @@ void disas_context_destroy(struct disas_context *dctx) · 302 unmodified lines
303303 free(dctx);
304304 }
305305
306−static char *disas_result(struct disas_context *dctx)
306+char *disas_result(struct disas_context *dctx)
307307 {
308308 return dctx->result;
309309 }
@@ -311,8 +311,7 @@ static char *disas_result(struct disas_context *dctx) · 1 unmodified line
311311 /*
312312 * Disassemble a single instruction. Return the size of the instruction.
313313 */
314−static size_t disas_insn(struct disas_context *dctx,
315− struct instruction *insn)
314+size_t disas_insn(struct disas_context *dctx, struct instruction *insn)
316315 {
317316 disassembler_ftype disasm = dctx->disassembler;
318317 struct disassemble_info *dinfo = &dctx->info;
tools/objtool/include/objtool/check.h+2−0
@@ -141,4 +141,6 @@ struct instruction *next_insn_same_sec(struct objtool_file *file, struct instruc · 140 unmodified lines
141141 insn && insn->offset < sym->offset + sym->len; \
142142 insn = next_insn_same_sec(file, insn))
143143
144+const char *objtool_disas_insn(struct instruction *insn);
145+
144146 #endif /* _CHECK_H */
tools/objtool/include/objtool/disas.h+13−0
@@ -17,6 +17,8 @@ void disas_warned_funcs(struct disas_context *dctx); · 16 unmodified lines
1717 int disas_info_init(struct disassemble_info *dinfo,
1818 int arch, int mach32, int mach64,
1919 const char *options);
20+size_t disas_insn(struct disas_context *dctx, struct instruction *insn);
21+char *disas_result(struct disas_context *dctx);
2022
2123 #else /* DISAS */
2224
@@ -38,6 +40,17 @@ static inline int disas_info_init(struct disassemble_info *dinfo, · 15 unmodified lines
3840 return -1;
3941 }
4042
43+static inline size_t disas_insn(struct disas_context *dctx,
44+ struct instruction *insn)
45+{
46+ return -1;
47+}
48+
49+static inline char *disas_result(struct disas_context *dctx)
50+{
51+ return NULL;
52+}
53+
4154 #endif /* DISAS */
4255
4356 #endif /* _DISAS_H */
tools/objtool/include/objtool/warn.h+11−5
@@ -77,9 +77,11 @@ static inline char *offstr(struct section *sec, unsigned long offset) · 76 unmodified lines
7777 #define WARN_INSN(insn, format, ...) \
7878 ({ \
7979 struct instruction *_insn = (insn); \
80− if (!_insn->sym || !_insn->sym->warned) \
80+ if (!_insn->sym || !_insn->sym->warned) { \
8181 WARN_FUNC(_insn->sec, _insn->offset, format, \
8282 ##__VA_ARGS__); \
83+ BT_INSN(_insn, ""); \
84+ } \
8385 if (_insn->sym) \
8486 _insn->sym->warned = 1; \
8587 })
@@ -87,10 +89,14 @@ static inline char *offstr(struct section *sec, unsigned long offset) · 1 unmodified line
8789 #define BT_INSN(insn, format, ...) \
8890 ({ \
8991 if (opts.verbose || opts.backtrace) { \
90− struct instruction *_insn = (insn); \
91− char *_str = offstr(_insn->sec, _insn->offset); \
92− WARN(" %s: " format, _str, ##__VA_ARGS__); \
93− free(_str); \
92+ struct instruction *__insn = (insn); \
93+ char *_str = offstr(__insn->sec, __insn->offset); \
94+ const char *_istr = objtool_disas_insn(__insn); \
95+ int _len; \
96+ _len = snprintf(NULL, 0, " %s: " format, _str, ##__VA_ARGS__); \
97+ _len = (_len < 50) ? 50 - _len : 0; \
98+ WARN(" %s: " format " %*s%s", _str, ##__VA_ARGS__, _len, "", _istr); \
99+ free(_str); \
94100 } \
95101 })
96102

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t