Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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.

Signed-off-by: Alexandre Chartre <alexandre.chartre@oracle.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
Link: https://patch.msgid.link/20251121095340.464045-8-alexandre.chartre@oracle.com

authored by

Alexandre Chartre and committed by
Peter Zijlstra
0bb080ba d4e13c21

+58 -14
+30 -6
tools/objtool/check.c
··· 4792 4792 free(chunk->addr); 4793 4793 } 4794 4794 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 + 4795 4808 int check(struct objtool_file *file) 4796 4809 { 4797 - struct disas_context *disas_ctx; 4810 + struct disas_context *disas_ctx = NULL; 4798 4811 int ret = 0, warnings = 0; 4812 + 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 + } 4799 4822 4800 4823 arch_initial_func_cfi_state(&initial_func_cfi); 4801 4824 init_cfi_state(&init_cfi); ··· 4959 4936 if (opts.verbose) { 4960 4937 if (opts.werror && warnings) 4961 4938 WARN("%d warning(s) upgraded to errors", warnings); 4962 - disas_ctx = disas_context_create(file); 4963 - if (disas_ctx) { 4964 - disas_warned_funcs(disas_ctx); 4965 - disas_context_destroy(disas_ctx); 4966 - } 4939 + disas_warned_funcs(disas_ctx); 4940 + } 4941 + 4942 + if (disas_ctx) { 4943 + disas_context_destroy(disas_ctx); 4944 + objtool_disas_ctx = NULL; 4967 4945 } 4968 4946 4969 4947 free_insns(file);
+2 -3
tools/objtool/disas.c
··· 303 303 free(dctx); 304 304 } 305 305 306 - static char *disas_result(struct disas_context *dctx) 306 + char *disas_result(struct disas_context *dctx) 307 307 { 308 308 return dctx->result; 309 309 } ··· 311 311 /* 312 312 * Disassemble a single instruction. Return the size of the instruction. 313 313 */ 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) 316 315 { 317 316 disassembler_ftype disasm = dctx->disassembler; 318 317 struct disassemble_info *dinfo = &dctx->info;
+2
tools/objtool/include/objtool/check.h
··· 141 141 insn && insn->offset < sym->offset + sym->len; \ 142 142 insn = next_insn_same_sec(file, insn)) 143 143 144 + const char *objtool_disas_insn(struct instruction *insn); 145 + 144 146 #endif /* _CHECK_H */
+13
tools/objtool/include/objtool/disas.h
··· 17 17 int disas_info_init(struct disassemble_info *dinfo, 18 18 int arch, int mach32, int mach64, 19 19 const char *options); 20 + size_t disas_insn(struct disas_context *dctx, struct instruction *insn); 21 + char *disas_result(struct disas_context *dctx); 20 22 21 23 #else /* DISAS */ 22 24 ··· 38 36 const char *options) 39 37 { 40 38 return -1; 39 + } 40 + 41 + static inline size_t disas_insn(struct disas_context *dctx, 42 + struct instruction *insn) 43 + { 44 + return -1; 45 + } 46 + 47 + static inline char *disas_result(struct disas_context *dctx) 48 + { 49 + return NULL; 41 50 } 42 51 43 52 #endif /* DISAS */
+11 -5
tools/objtool/include/objtool/warn.h
··· 77 77 #define WARN_INSN(insn, format, ...) \ 78 78 ({ \ 79 79 struct instruction *_insn = (insn); \ 80 - if (!_insn->sym || !_insn->sym->warned) \ 80 + if (!_insn->sym || !_insn->sym->warned) { \ 81 81 WARN_FUNC(_insn->sec, _insn->offset, format, \ 82 82 ##__VA_ARGS__); \ 83 + BT_INSN(_insn, ""); \ 84 + } \ 83 85 if (_insn->sym) \ 84 86 _insn->sym->warned = 1; \ 85 87 }) ··· 89 87 #define BT_INSN(insn, format, ...) \ 90 88 ({ \ 91 89 if (opts.verbose || opts.backtrace) { \ 92 - struct instruction *_insn = (insn); \ 93 - char *_str = offstr(_insn->sec, _insn->offset); \ 94 - WARN(" %s: " format, _str, ##__VA_ARGS__); \ 95 - free(_str); \ 90 + struct instruction *__insn = (insn); \ 91 + char *_str = offstr(__insn->sec, __insn->offset); \ 92 + const char *_istr = objtool_disas_insn(__insn); \ 93 + int _len; \ 94 + _len = snprintf(NULL, 0, " %s: " format, _str, ##__VA_ARGS__); \ 95 + _len = (_len < 50) ? 50 - _len : 0; \ 96 + WARN(" %s: " format " %*s%s", _str, ##__VA_ARGS__, _len, "", _istr); \ 97 + free(_str); \ 96 98 } \ 97 99 }) 98 100