mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
objtool: Refactor prefix symbol creation code
The prefix symbol creation code currently ignores all errors, presumably because some functions don't have the leading NOPs. Shuffle the code around a bit, improve the error handling and document why some errors are ignored. Acked-by: Petr Mladek <pmladek@suse.com> Tested-by: Joe Lawrence <joe.lawrence@redhat.com> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include <objtool/special.h>
|
||||
#include <objtool/warn.h>
|
||||
#include <objtool/checksum.h>
|
||||
#include <objtool/util.h>
|
||||
|
||||
#include <linux/objtool_types.h>
|
||||
#include <linux/hashtable.h>
|
||||
@@ -4233,37 +4234,71 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio
|
||||
return false;
|
||||
}
|
||||
|
||||
static int add_prefix_symbol(struct objtool_file *file, struct symbol *func)
|
||||
/*
|
||||
* For FineIBT or kCFI, a certain number of bytes preceding the function may be
|
||||
* NOPs. Those NOPs may be rewritten at runtime and executed, so give them a
|
||||
* proper function name: __pfx_<func>.
|
||||
*
|
||||
* The NOPs may not exist for the following cases:
|
||||
*
|
||||
* - compiler cloned functions (*.cold, *.part0, etc)
|
||||
* - asm functions created with inline asm or without SYM_FUNC_START()
|
||||
*
|
||||
* So return 0 if the NOPs are missing or the function already has a prefix
|
||||
* symbol.
|
||||
*/
|
||||
static int create_prefix_symbol(struct objtool_file *file, struct symbol *func)
|
||||
{
|
||||
struct instruction *insn, *prev;
|
||||
char name[SYM_NAME_LEN];
|
||||
struct cfi_state *cfi;
|
||||
|
||||
insn = find_insn(file, func->sec, func->offset);
|
||||
if (!insn)
|
||||
if (!is_func_sym(func) || is_prefix_func(func) ||
|
||||
func->cold || func->static_call_tramp)
|
||||
return 0;
|
||||
|
||||
if ((strlen(func->name) + sizeof("__pfx_") > SYM_NAME_LEN)) {
|
||||
WARN("%s: symbol name too long, can't create __pfx_ symbol",
|
||||
func->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (snprintf_check(name, SYM_NAME_LEN, "__pfx_%s", func->name))
|
||||
return -1;
|
||||
|
||||
insn = find_insn(file, func->sec, func->offset);
|
||||
if (!insn) {
|
||||
WARN("%s: can't find starting instruction", func->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (prev = prev_insn_same_sec(file, insn);
|
||||
prev;
|
||||
prev = prev_insn_same_sec(file, prev)) {
|
||||
u64 offset;
|
||||
|
||||
if (prev->type != INSN_NOP)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
offset = func->offset - prev->offset;
|
||||
|
||||
if (offset > opts.prefix)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
if (offset < opts.prefix)
|
||||
continue;
|
||||
|
||||
elf_create_prefix_symbol(file->elf, func, opts.prefix);
|
||||
if (!elf_create_symbol(file->elf, name, func->sec,
|
||||
GELF_ST_BIND(func->sym.st_info),
|
||||
GELF_ST_TYPE(func->sym.st_info),
|
||||
prev->offset, opts.prefix))
|
||||
return -1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!prev)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
if (!insn->cfi) {
|
||||
/*
|
||||
@@ -4281,7 +4316,7 @@ static int add_prefix_symbol(struct objtool_file *file, struct symbol *func)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_prefix_symbols(struct objtool_file *file)
|
||||
static int create_prefix_symbols(struct objtool_file *file)
|
||||
{
|
||||
struct section *sec;
|
||||
struct symbol *func;
|
||||
@@ -4291,10 +4326,8 @@ static int add_prefix_symbols(struct objtool_file *file)
|
||||
continue;
|
||||
|
||||
sec_for_each_sym(sec, func) {
|
||||
if (!is_func_sym(func))
|
||||
continue;
|
||||
|
||||
add_prefix_symbol(file, func);
|
||||
if (create_prefix_symbol(file, func))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4921,7 +4954,7 @@ int check(struct objtool_file *file)
|
||||
}
|
||||
|
||||
if (opts.prefix) {
|
||||
ret = add_prefix_symbols(file);
|
||||
ret = create_prefix_symbols(file);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -942,23 +942,6 @@ struct symbol *elf_create_section_symbol(struct elf *elf, struct section *sec)
|
||||
return sym;
|
||||
}
|
||||
|
||||
struct symbol *
|
||||
elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, size_t size)
|
||||
{
|
||||
size_t namelen = strlen(orig->name) + sizeof("__pfx_");
|
||||
char name[SYM_NAME_LEN];
|
||||
unsigned long offset;
|
||||
|
||||
snprintf(name, namelen, "__pfx_%s", orig->name);
|
||||
|
||||
offset = orig->sym.st_value - size;
|
||||
|
||||
return elf_create_symbol(elf, name, orig->sec,
|
||||
GELF_ST_BIND(orig->sym.st_info),
|
||||
GELF_ST_TYPE(orig->sym.st_info),
|
||||
offset, size);
|
||||
}
|
||||
|
||||
struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
|
||||
unsigned int reloc_idx, unsigned long offset,
|
||||
struct symbol *sym, s64 addend, unsigned int type)
|
||||
|
||||
@@ -148,8 +148,6 @@ struct symbol *elf_create_symbol(struct elf *elf, const char *name,
|
||||
unsigned int type, unsigned long offset,
|
||||
size_t size);
|
||||
struct symbol *elf_create_section_symbol(struct elf *elf, struct section *sec);
|
||||
struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig,
|
||||
size_t size);
|
||||
|
||||
void *elf_add_data(struct elf *elf, struct section *sec, const void *data,
|
||||
size_t size);
|
||||
|
||||
Reference in New Issue
Block a user