mirror of https://github.com/torvalds/linux.git
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
This commit is contained in:
parent
c3b7d044fc
commit
5f326c8897
|
|
@ -75,6 +75,7 @@ static const struct option check_options[] = {
|
||||||
OPT_GROUP("Actions:"),
|
OPT_GROUP("Actions:"),
|
||||||
OPT_BOOLEAN(0, "checksum", &opts.checksum, "generate per-function checksums"),
|
OPT_BOOLEAN(0, "checksum", &opts.checksum, "generate per-function checksums"),
|
||||||
OPT_BOOLEAN(0, "cfi", &opts.cfi, "annotate kernel control flow integrity (kCFI) function preambles"),
|
OPT_BOOLEAN(0, "cfi", &opts.cfi, "annotate kernel control flow integrity (kCFI) function preambles"),
|
||||||
|
OPT_STRING_OPTARG('d', "disas", &opts.disas, "function-pattern", "disassemble functions", "*"),
|
||||||
OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label,noinstr,skylake", "patch toolchain bugs/limitations", parse_hacks),
|
OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label,noinstr,skylake", "patch toolchain bugs/limitations", parse_hacks),
|
||||||
OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"),
|
OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"),
|
||||||
OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"),
|
OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"),
|
||||||
|
|
@ -176,6 +177,7 @@ static bool opts_valid(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.checksum ||
|
if (opts.checksum ||
|
||||||
|
opts.disas ||
|
||||||
opts.hack_jump_label ||
|
opts.hack_jump_label ||
|
||||||
opts.hack_noinstr ||
|
opts.hack_noinstr ||
|
||||||
opts.ibt ||
|
opts.ibt ||
|
||||||
|
|
|
||||||
|
|
@ -2611,7 +2611,7 @@ static int decode_sections(struct objtool_file *file)
|
||||||
* Must be before add_jump_destinations(), which depends on 'func'
|
* Must be before add_jump_destinations(), which depends on 'func'
|
||||||
* being set for alternatives, to enable proper sibling call detection.
|
* being set for alternatives, to enable proper sibling call detection.
|
||||||
*/
|
*/
|
||||||
if (validate_branch_enabled() || opts.noinstr || opts.hack_jump_label) {
|
if (validate_branch_enabled() || opts.noinstr || opts.hack_jump_label || opts.disas) {
|
||||||
if (add_special_section_alts(file))
|
if (add_special_section_alts(file))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -4915,14 +4915,15 @@ int check(struct objtool_file *file)
|
||||||
int ret = 0, warnings = 0;
|
int ret = 0, warnings = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the verbose or backtrace option is used then we need a
|
* Create a disassembly context if we might disassemble any
|
||||||
* disassembly context to disassemble instruction or function
|
* instruction or function.
|
||||||
* on warning or backtrace.
|
|
||||||
*/
|
*/
|
||||||
if (opts.verbose || opts.backtrace || opts.trace) {
|
if (opts.verbose || opts.backtrace || opts.trace || opts.disas) {
|
||||||
disas_ctx = disas_context_create(file);
|
disas_ctx = disas_context_create(file);
|
||||||
if (!disas_ctx)
|
if (!disas_ctx) {
|
||||||
|
opts.disas = false;
|
||||||
opts.trace = false;
|
opts.trace = false;
|
||||||
|
}
|
||||||
objtool_disas_ctx = disas_ctx;
|
objtool_disas_ctx = disas_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5054,20 +5055,20 @@ int check(struct objtool_file *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!ret && !warnings) {
|
if (ret || warnings) {
|
||||||
free_insns(file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.werror && warnings)
|
|
||||||
ret = 1;
|
|
||||||
|
|
||||||
if (opts.verbose) {
|
|
||||||
if (opts.werror && warnings)
|
if (opts.werror && warnings)
|
||||||
WARN("%d warning(s) upgraded to errors", warnings);
|
ret = 1;
|
||||||
disas_warned_funcs(disas_ctx);
|
|
||||||
|
if (opts.verbose) {
|
||||||
|
if (opts.werror && warnings)
|
||||||
|
WARN("%d warning(s) upgraded to errors", warnings);
|
||||||
|
disas_warned_funcs(disas_ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts.disas)
|
||||||
|
disas_funcs(disas_ctx);
|
||||||
|
|
||||||
if (disas_ctx) {
|
if (disas_ctx) {
|
||||||
disas_context_destroy(disas_ctx);
|
disas_context_destroy(disas_ctx);
|
||||||
objtool_disas_ctx = NULL;
|
objtool_disas_ctx = NULL;
|
||||||
|
|
@ -5075,6 +5076,9 @@ int check(struct objtool_file *file)
|
||||||
|
|
||||||
free_insns(file);
|
free_insns(file);
|
||||||
|
|
||||||
|
if (!ret && !warnings)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (opts.backup && make_backup())
|
if (opts.backup && make_backup())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
#include <fnmatch.h>
|
||||||
|
|
||||||
#include <objtool/arch.h>
|
#include <objtool/arch.h>
|
||||||
#include <objtool/check.h>
|
#include <objtool/check.h>
|
||||||
|
|
@ -556,3 +557,29 @@ void disas_warned_funcs(struct disas_context *dctx)
|
||||||
disas_func(dctx, sym);
|
disas_func(dctx, sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disas_funcs(struct disas_context *dctx)
|
||||||
|
{
|
||||||
|
bool disas_all = !strcmp(opts.disas, "*");
|
||||||
|
struct section *sec;
|
||||||
|
struct symbol *sym;
|
||||||
|
|
||||||
|
for_each_sec(dctx->file->elf, sec) {
|
||||||
|
|
||||||
|
if (!(sec->sh.sh_flags & SHF_EXECINSTR))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sec_for_each_sym(sec, sym) {
|
||||||
|
/*
|
||||||
|
* If the function had a warning and the verbose
|
||||||
|
* option is used then the function was already
|
||||||
|
* disassemble.
|
||||||
|
*/
|
||||||
|
if (opts.verbose && sym->warned)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (disas_all || fnmatch(opts.disas, sym->name, 0) == 0)
|
||||||
|
disas_func(dctx, sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ struct opts {
|
||||||
bool static_call;
|
bool static_call;
|
||||||
bool uaccess;
|
bool uaccess;
|
||||||
int prefix;
|
int prefix;
|
||||||
|
const char *disas;
|
||||||
|
|
||||||
/* options: */
|
/* options: */
|
||||||
bool backtrace;
|
bool backtrace;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ struct disassemble_info;
|
||||||
struct disas_context *disas_context_create(struct objtool_file *file);
|
struct disas_context *disas_context_create(struct objtool_file *file);
|
||||||
void disas_context_destroy(struct disas_context *dctx);
|
void disas_context_destroy(struct disas_context *dctx);
|
||||||
void disas_warned_funcs(struct disas_context *dctx);
|
void disas_warned_funcs(struct disas_context *dctx);
|
||||||
|
void disas_funcs(struct disas_context *dctx);
|
||||||
int disas_info_init(struct disassemble_info *dinfo,
|
int disas_info_init(struct disassemble_info *dinfo,
|
||||||
int arch, int mach32, int mach64,
|
int arch, int mach32, int mach64,
|
||||||
const char *options);
|
const char *options);
|
||||||
|
|
@ -40,6 +41,7 @@ static inline struct disas_context *disas_context_create(struct objtool_file *fi
|
||||||
|
|
||||||
static inline void disas_context_destroy(struct disas_context *dctx) {}
|
static inline void disas_context_destroy(struct disas_context *dctx) {}
|
||||||
static inline void disas_warned_funcs(struct disas_context *dctx) {}
|
static inline void disas_warned_funcs(struct disas_context *dctx) {}
|
||||||
|
static inline void disas_funcs(struct disas_context *dctx) {}
|
||||||
|
|
||||||
static inline int disas_info_init(struct disassemble_info *dinfo,
|
static inline int disas_info_init(struct disassemble_info *dinfo,
|
||||||
int arch, int mach32, int mach64,
|
int arch, int mach32, int mach64,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue