mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 02:31:27 +02:00
objtool: Add insn_sym() helper
Alternative replacement instructions awkwardly have insn->sym set to the function they get patched to rather than the symbol (or rather lack thereof) they belong to in the file. This makes it difficult to know where a given instruction actually lives. Add a new insn_sym() helper which preserves the existing semantic of insn->sym. Rename insn->sym to insn->_sym, which contains the actual ELF binary symbol (or NULL, for alternative replacements) an instruction lives in. The private insn->_sym value will be needed for a subsequent patch. Acked-by: Song Liu <song@kernel.org> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
This commit is contained in:
parent
5d6a03eeb7
commit
3ee67629b2
|
|
@ -495,7 +495,7 @@ static int decode_instructions(struct objtool_file *file)
|
|||
}
|
||||
|
||||
sym_for_each_insn(file, func, insn) {
|
||||
insn->sym = func;
|
||||
insn->_sym = func;
|
||||
if (is_func_sym(func) &&
|
||||
insn->type == INSN_ENDBR &&
|
||||
list_empty(&insn->call_node)) {
|
||||
|
|
@ -859,15 +859,14 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file)
|
|||
list_for_each_entry(insn, &file->endbr_list, call_node) {
|
||||
|
||||
int *site = (int *)sec->data->d_buf + idx;
|
||||
struct symbol *sym = insn->sym;
|
||||
struct symbol *func = insn_func(insn);
|
||||
*site = 0;
|
||||
|
||||
if (opts.module && sym && is_func_sym(sym) &&
|
||||
insn->offset == sym->offset &&
|
||||
(!strcmp(sym->name, "init_module") ||
|
||||
!strcmp(sym->name, "cleanup_module"))) {
|
||||
if (opts.module && func && insn->offset == func->offset &&
|
||||
(!strcmp(func->name, "init_module") ||
|
||||
!strcmp(func->name, "cleanup_module"))) {
|
||||
ERROR("%s(): Magic init_module() function name is deprecated, use module_init(fn) instead",
|
||||
sym->name);
|
||||
func->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1581,7 +1580,7 @@ static int add_jump_destinations(struct objtool_file *file)
|
|||
}
|
||||
|
||||
if (!dest_sym || is_sec_sym(dest_sym)) {
|
||||
dest_sym = dest_insn->sym;
|
||||
dest_sym = insn_sym(dest_insn);
|
||||
if (!dest_sym)
|
||||
goto set_jump_dest;
|
||||
}
|
||||
|
|
@ -1597,7 +1596,7 @@ static int add_jump_destinations(struct objtool_file *file)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!insn->sym || insn->sym->pfunc == dest_sym->pfunc)
|
||||
if (!insn_sym(insn) || insn_sym(insn)->pfunc == dest_sym->pfunc)
|
||||
goto set_jump_dest;
|
||||
|
||||
/*
|
||||
|
|
@ -1770,7 +1769,6 @@ static int handle_group_alt(struct objtool_file *file,
|
|||
nop->offset = special_alt->new_off + special_alt->new_len;
|
||||
nop->len = special_alt->orig_len - special_alt->new_len;
|
||||
nop->type = INSN_NOP;
|
||||
nop->sym = orig_insn->sym;
|
||||
nop->alt_group = new_alt_group;
|
||||
nop->fake = 1;
|
||||
}
|
||||
|
|
@ -1789,7 +1787,6 @@ static int handle_group_alt(struct objtool_file *file,
|
|||
|
||||
last_new_insn = insn;
|
||||
|
||||
insn->sym = orig_insn->sym;
|
||||
insn->alt_group = new_alt_group;
|
||||
|
||||
/*
|
||||
|
|
@ -2432,12 +2429,12 @@ static int __annotate_late(struct objtool_file *file, int type, struct instructi
|
|||
break;
|
||||
|
||||
case ANNOTYPE_NOCFI:
|
||||
sym = insn->sym;
|
||||
sym = insn_sym(insn);
|
||||
if (!sym) {
|
||||
ERROR_INSN(insn, "dodgy NOCFI annotation");
|
||||
return -1;
|
||||
}
|
||||
insn->sym->nocfi = 1;
|
||||
sym->nocfi = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -2538,7 +2535,7 @@ static void mark_holes(struct objtool_file *file)
|
|||
* favour of a regular symbol, but leaves the code in place.
|
||||
*/
|
||||
for_each_insn(file, insn) {
|
||||
if (insn->sym || !find_symbol_hole_containing(insn->sec, insn->offset)) {
|
||||
if (insn_sym(insn) || !find_symbol_hole_containing(insn->sec, insn->offset)) {
|
||||
in_hole = false;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2982,7 +2979,7 @@ static int update_cfi_state(struct instruction *insn,
|
|||
}
|
||||
|
||||
if (op->dest.reg == CFI_BP && op->src.reg == CFI_SP &&
|
||||
insn->sym->frame_pointer) {
|
||||
insn_sym(insn)->frame_pointer) {
|
||||
/* addi.d fp,sp,imm on LoongArch */
|
||||
if (cfa->base == CFI_SP && cfa->offset == op->src.offset) {
|
||||
cfa->base = CFI_BP;
|
||||
|
|
@ -2994,7 +2991,7 @@ static int update_cfi_state(struct instruction *insn,
|
|||
if (op->dest.reg == CFI_SP && op->src.reg == CFI_BP) {
|
||||
/* addi.d sp,fp,imm on LoongArch */
|
||||
if (cfa->base == CFI_BP && cfa->offset == 0) {
|
||||
if (insn->sym->frame_pointer) {
|
||||
if (insn_sym(insn)->frame_pointer) {
|
||||
cfa->base = CFI_SP;
|
||||
cfa->offset = -op->src.offset;
|
||||
}
|
||||
|
|
@ -4171,7 +4168,7 @@ static int validate_retpoline(struct objtool_file *file)
|
|||
* broken.
|
||||
*/
|
||||
list_for_each_entry(insn, &file->retpoline_call_list, call_node) {
|
||||
struct symbol *sym = insn->sym;
|
||||
struct symbol *sym = insn_sym(insn);
|
||||
|
||||
if (sym && (is_notype_sym(sym) ||
|
||||
is_func_sym(sym)) && !sym->nocfi) {
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ static bool disas_print_addr_alt(bfd_vma addr, struct disassemble_info *dinfo)
|
|||
offset = addr - alt_group->first_insn->offset;
|
||||
|
||||
addr = orig_first_insn->offset + offset;
|
||||
sym = orig_first_insn->sym;
|
||||
sym = insn_sym(orig_first_insn);
|
||||
|
||||
disas_print_addr_sym(orig_first_insn->sec, sym, addr, dinfo);
|
||||
|
||||
|
|
@ -222,15 +222,13 @@ static void disas_print_addr_noreloc(bfd_vma addr,
|
|||
{
|
||||
struct disas_context *dctx = dinfo->application_data;
|
||||
struct instruction *insn = dctx->insn;
|
||||
struct symbol *sym = NULL;
|
||||
struct symbol *sym = insn_sym(insn);
|
||||
|
||||
if (disas_print_addr_alt(addr, dinfo))
|
||||
return;
|
||||
|
||||
if (insn->sym && addr >= insn->sym->offset &&
|
||||
addr < insn->sym->offset + insn->sym->len) {
|
||||
sym = insn->sym;
|
||||
}
|
||||
if (sym && (addr < sym->offset || addr >= sym->offset + sym->len))
|
||||
sym = NULL;
|
||||
|
||||
disas_print_addr_sym(insn->sec, sym, addr, dinfo);
|
||||
}
|
||||
|
|
@ -291,9 +289,9 @@ static void disas_print_address(bfd_vma addr, struct disassemble_info *dinfo)
|
|||
* up. So check it first.
|
||||
*/
|
||||
jump_dest = insn->jump_dest;
|
||||
if (jump_dest && jump_dest->sym && jump_dest->offset == addr) {
|
||||
if (jump_dest && insn_sym(jump_dest) && jump_dest->offset == addr) {
|
||||
if (!disas_print_addr_alt(addr, dinfo))
|
||||
disas_print_addr_sym(jump_dest->sec, jump_dest->sym,
|
||||
disas_print_addr_sym(jump_dest->sec, insn_sym(jump_dest),
|
||||
addr, dinfo);
|
||||
return;
|
||||
}
|
||||
|
|
@ -768,8 +766,8 @@ static int disas_alt_jump(struct disas_alt *dalt)
|
|||
if (orig_insn->len == 5)
|
||||
suffix[0] = 'q';
|
||||
str = strfmt("jmp%-3s %lx <%s+0x%lx>", suffix,
|
||||
dest_insn->offset, dest_insn->sym->name,
|
||||
dest_insn->offset - dest_insn->sym->offset);
|
||||
dest_insn->offset, insn_sym(dest_insn)->name,
|
||||
dest_insn->offset - insn_sym(dest_insn)->offset);
|
||||
nops = 0;
|
||||
} else {
|
||||
str = strfmt("nop%d", orig_insn->len);
|
||||
|
|
@ -794,8 +792,8 @@ static int disas_alt_extable(struct disas_alt *dalt)
|
|||
|
||||
alt_insn = dalt->alt->insn;
|
||||
str = strfmt("resume at 0x%lx <%s+0x%lx>",
|
||||
alt_insn->offset, alt_insn->sym->name,
|
||||
alt_insn->offset - alt_insn->sym->offset);
|
||||
alt_insn->offset, insn_sym(alt_insn)->name,
|
||||
alt_insn->offset - insn_sym(alt_insn)->offset);
|
||||
if (!str)
|
||||
return -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -94,14 +94,30 @@ struct instruction {
|
|||
};
|
||||
};
|
||||
struct alternative *alts;
|
||||
struct symbol *sym;
|
||||
struct symbol *_sym;
|
||||
struct stack_op *stack_ops;
|
||||
struct cfi_state *cfi;
|
||||
};
|
||||
|
||||
/*
|
||||
* Return the symbol associated with an instruction. For alternative
|
||||
* replacements, return the symbol of the original code being replaced rather
|
||||
* than NULL. insn->_sym reflects the actual location in the ELF file.
|
||||
*/
|
||||
static inline struct symbol *insn_sym(struct instruction *insn)
|
||||
{
|
||||
struct symbol *sym = insn->_sym;
|
||||
|
||||
if ((!sym || !is_func_sym(sym)) &&
|
||||
insn->alt_group && insn->alt_group->orig_group)
|
||||
sym = insn->alt_group->orig_group->first_insn->_sym;
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
static inline struct symbol *insn_func(struct instruction *insn)
|
||||
{
|
||||
struct symbol *sym = insn->sym;
|
||||
struct symbol *sym = insn_sym(insn);
|
||||
|
||||
if (sym && sym->type != STT_FUNC)
|
||||
sym = NULL;
|
||||
|
|
|
|||
|
|
@ -77,13 +77,13 @@ static inline char *offstr(struct section *sec, unsigned long offset)
|
|||
#define WARN_INSN(insn, format, ...) \
|
||||
({ \
|
||||
struct instruction *_insn = (insn); \
|
||||
if (!_insn->sym || !_insn->sym->warned) { \
|
||||
if (!insn_sym(_insn) || !insn_sym(_insn)->warned) { \
|
||||
WARN_FUNC(_insn->sec, _insn->offset, format, \
|
||||
##__VA_ARGS__); \
|
||||
BT_INSN(_insn, ""); \
|
||||
} \
|
||||
if (_insn->sym) \
|
||||
_insn->sym->warned = 1; \
|
||||
if (insn_sym(_insn)) \
|
||||
insn_sym(_insn)->warned = 1; \
|
||||
})
|
||||
|
||||
#define BT_INSN(insn, format, ...) \
|
||||
|
|
|
|||
|
|
@ -169,8 +169,8 @@ void trace_alt_begin(struct instruction *orig_insn, struct alternative *alt,
|
|||
*/
|
||||
TRACE_ALT_INFO_NOADDR(orig_insn, "/ ", "%s for instruction at 0x%lx <%s+0x%lx>",
|
||||
alt_name,
|
||||
orig_insn->offset, orig_insn->sym->name,
|
||||
orig_insn->offset - orig_insn->sym->offset);
|
||||
orig_insn->offset, insn_sym(orig_insn)->name,
|
||||
orig_insn->offset - insn_sym(orig_insn)->offset);
|
||||
} else {
|
||||
TRACE_ALT_INFO_NOADDR(orig_insn, "/ ", "%s", alt_name);
|
||||
}
|
||||
|
|
@ -185,8 +185,8 @@ void trace_alt_begin(struct instruction *orig_insn, struct alternative *alt,
|
|||
if (orig_insn->type == INSN_NOP) {
|
||||
suffix[0] = (orig_insn->len == 5) ? 'q' : '\0';
|
||||
TRACE_ADDR(orig_insn, "jmp%-3s %lx <%s+0x%lx>", suffix,
|
||||
alt_insn->offset, alt_insn->sym->name,
|
||||
alt_insn->offset - alt_insn->sym->offset);
|
||||
alt_insn->offset, insn_sym(alt_insn)->name,
|
||||
alt_insn->offset - insn_sym(alt_insn)->offset);
|
||||
} else {
|
||||
TRACE_ADDR(orig_insn, "nop%d", orig_insn->len);
|
||||
trace_depth--;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user