Skip to content

Commit 5f326c8

Browse files
achartrePeter Zijlstra
authored andcommitted
objtool: Add the --disas=<function-pattern> action
Add the --disas=<function-pattern> actions to disassemble the specified functions. The function pattern can be a single function name (e.g. --disas foo to disassemble the function with the name "foo"), or a shell wildcard pattern (e.g. --disas foo* to disassemble all functions with a name starting with "foo"). 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-18-alexandre.chartre@oracle.com
1 parent c3b7d04 commit 5f326c8

5 files changed

Lines changed: 53 additions & 17 deletions

File tree

tools/objtool/builtin-check.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static const struct option check_options[] = {
7575
OPT_GROUP("Actions:"),
7676
OPT_BOOLEAN(0, "checksum", &opts.checksum, "generate per-function checksums"),
7777
OPT_BOOLEAN(0, "cfi", &opts.cfi, "annotate kernel control flow integrity (kCFI) function preambles"),
78+
OPT_STRING_OPTARG('d', "disas", &opts.disas, "function-pattern", "disassemble functions", "*"),
7879
OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label,noinstr,skylake", "patch toolchain bugs/limitations", parse_hacks),
7980
OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"),
8081
OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"),
@@ -176,6 +177,7 @@ static bool opts_valid(void)
176177
}
177178

178179
if (opts.checksum ||
180+
opts.disas ||
179181
opts.hack_jump_label ||
180182
opts.hack_noinstr ||
181183
opts.ibt ||

tools/objtool/check.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,7 +2611,7 @@ static int decode_sections(struct objtool_file *file)
26112611
* Must be before add_jump_destinations(), which depends on 'func'
26122612
* being set for alternatives, to enable proper sibling call detection.
26132613
*/
2614-
if (validate_branch_enabled() || opts.noinstr || opts.hack_jump_label) {
2614+
if (validate_branch_enabled() || opts.noinstr || opts.hack_jump_label || opts.disas) {
26152615
if (add_special_section_alts(file))
26162616
return -1;
26172617
}
@@ -4915,14 +4915,15 @@ int check(struct objtool_file *file)
49154915
int ret = 0, warnings = 0;
49164916

49174917
/*
4918-
* If the verbose or backtrace option is used then we need a
4919-
* disassembly context to disassemble instruction or function
4920-
* on warning or backtrace.
4918+
* Create a disassembly context if we might disassemble any
4919+
* instruction or function.
49214920
*/
4922-
if (opts.verbose || opts.backtrace || opts.trace) {
4921+
if (opts.verbose || opts.backtrace || opts.trace || opts.disas) {
49234922
disas_ctx = disas_context_create(file);
4924-
if (!disas_ctx)
4923+
if (!disas_ctx) {
4924+
opts.disas = false;
49254925
opts.trace = false;
4926+
}
49264927
objtool_disas_ctx = disas_ctx;
49274928
}
49284929

@@ -5054,27 +5055,30 @@ int check(struct objtool_file *file)
50545055
}
50555056

50565057
out:
5057-
if (!ret && !warnings) {
5058-
free_insns(file);
5059-
return 0;
5060-
}
5061-
5062-
if (opts.werror && warnings)
5063-
ret = 1;
5064-
5065-
if (opts.verbose) {
5058+
if (ret || warnings) {
50665059
if (opts.werror && warnings)
5067-
WARN("%d warning(s) upgraded to errors", warnings);
5068-
disas_warned_funcs(disas_ctx);
5060+
ret = 1;
5061+
5062+
if (opts.verbose) {
5063+
if (opts.werror && warnings)
5064+
WARN("%d warning(s) upgraded to errors", warnings);
5065+
disas_warned_funcs(disas_ctx);
5066+
}
50695067
}
50705068

5069+
if (opts.disas)
5070+
disas_funcs(disas_ctx);
5071+
50715072
if (disas_ctx) {
50725073
disas_context_destroy(disas_ctx);
50735074
objtool_disas_ctx = NULL;
50745075
}
50755076

50765077
free_insns(file);
50775078

5079+
if (!ret && !warnings)
5080+
return 0;
5081+
50785082
if (opts.backup && make_backup())
50795083
return 1;
50805084

tools/objtool/disas.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
#define _GNU_SOURCE
7+
#include <fnmatch.h>
78

89
#include <objtool/arch.h>
910
#include <objtool/check.h>
@@ -556,3 +557,29 @@ void disas_warned_funcs(struct disas_context *dctx)
556557
disas_func(dctx, sym);
557558
}
558559
}
560+
561+
void disas_funcs(struct disas_context *dctx)
562+
{
563+
bool disas_all = !strcmp(opts.disas, "*");
564+
struct section *sec;
565+
struct symbol *sym;
566+
567+
for_each_sec(dctx->file->elf, sec) {
568+
569+
if (!(sec->sh.sh_flags & SHF_EXECINSTR))
570+
continue;
571+
572+
sec_for_each_sym(sec, sym) {
573+
/*
574+
* If the function had a warning and the verbose
575+
* option is used then the function was already
576+
* disassemble.
577+
*/
578+
if (opts.verbose && sym->warned)
579+
continue;
580+
581+
if (disas_all || fnmatch(opts.disas, sym->name, 0) == 0)
582+
disas_func(dctx, sym);
583+
}
584+
}
585+
}

tools/objtool/include/objtool/builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct opts {
2828
bool static_call;
2929
bool uaccess;
3030
int prefix;
31+
const char *disas;
3132

3233
/* options: */
3334
bool backtrace;

tools/objtool/include/objtool/disas.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct disassemble_info;
1515
struct disas_context *disas_context_create(struct objtool_file *file);
1616
void disas_context_destroy(struct disas_context *dctx);
1717
void disas_warned_funcs(struct disas_context *dctx);
18+
void disas_funcs(struct disas_context *dctx);
1819
int disas_info_init(struct disassemble_info *dinfo,
1920
int arch, int mach32, int mach64,
2021
const char *options);
@@ -40,6 +41,7 @@ static inline struct disas_context *disas_context_create(struct objtool_file *fi
4041

4142
static inline void disas_context_destroy(struct disas_context *dctx) {}
4243
static inline void disas_warned_funcs(struct disas_context *dctx) {}
44+
static inline void disas_funcs(struct disas_context *dctx) {}
4345

4446
static inline int disas_info_init(struct disassemble_info *dinfo,
4547
int arch, int mach32, int mach64,

0 commit comments

Comments
 (0)