Messages in this thread Patch in this message | | | Date | Mon, 25 Feb 2019 13:43:34 +0100 | From | Peter Zijlstra <> | Subject | [PATCH 4/6] objtool: Replace STACK_FRAME_NON_STANDARD annotation |
| |
Replace the existing STACK_FRAME_NON_STANDARD annotation with a 'better' scheme.
The old annotation works by taking the address of a function; this is visible to the compiler and might affect code generation (the function pointer escapes). The new annotation simply stores the function name and has objtool do a symtab lookup.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- include/linux/frame.h | 19 +++++++++++++--- tools/objtool/check.c | 58 +++++++++++++++++++++----------------------------- tools/objtool/check.h | 1 3 files changed, 41 insertions(+), 37 deletions(-)
--- a/include/linux/frame.h +++ b/include/linux/frame.h @@ -11,9 +11,22 @@ * * For more information, see tools/objtool/Documentation/stack-validation.txt. */ -#define STACK_FRAME_NON_STANDARD(func) \ - static void __used __section(.discard.func_stack_frame_non_standard) \ - *__func_stack_frame_non_standard_##func = func +#define STACK_FRAME_NON_STANDARD(func) \ + asm (".pushsection .discard.nonstd_frame_strtab, \"S\", @3\n\t" \ + "999: .ascii \"" #func "\"\n\t" \ + " .byte 0\n\t" \ + ".popsection\n\t" \ + ".pushsection .discard.nonstd_frame\n\t" \ + ".long 999b - .\n\t" \ + ".popsection\n\t") + +/* + * SHT_STRTAB(@3) sections should start with a \0 byte such that the 0 offset + * encodes the NULL string. + */ +asm (".pushsection .discard.nonstd_frame_strtab, \"S\", @3\n\t" + ".byte 0\n\t" + ".popsection\n\t"); #else /* !CONFIG_STACK_VALIDATION */ --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -105,29 +105,6 @@ static struct instruction *next_insn_sam insn = next_insn_same_sec(file, insn)) /* - * Check if the function has been manually whitelisted with the - * STACK_FRAME_NON_STANDARD macro, or if it should be automatically whitelisted - * due to its use of a context switching instruction. - */ -static bool ignore_func(struct objtool_file *file, struct symbol *func) -{ - struct rela *rela; - - /* check for STACK_FRAME_NON_STANDARD */ - if (file->whitelist && file->whitelist->rela) - list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) { - if (rela->sym->type == STT_SECTION && - rela->sym->sec == func->sec && - rela->addend == func->offset) - return true; - if (rela->sym->type == STT_FUNC && rela->sym == func) - return true; - } - - return false; -} - -/* * This checks to see if the given function is a "noreturn" function. * * For global functions which are outside the scope of this object file, we @@ -434,21 +411,37 @@ static int add_dead_ends(struct objtool_ static void add_ignores(struct objtool_file *file) { struct instruction *insn; - struct section *sec; + struct section *strtab_sec, *sec; struct symbol *func; + struct rela *rela; + const char *name; - for_each_sec(file, sec) { - list_for_each_entry(func, &sec->symbol_list, list) { - if (func->type != STT_FUNC) - continue; + sec = find_section_by_name(file->elf, ".rela.discard.nonstd_frame"); + if (!sec) + return; - if (!ignore_func(file, func)) - continue; + strtab_sec = find_section_by_name(file->elf, ".discard.nonstd_frame_strtab"); + if (!strtab_sec) { + WARN("missing nonstd_frame strtab"); + return; + } - func_for_each_insn_all(file, func, insn) - insn->ignore = true; + list_for_each_entry(rela, &sec->rela_list, list) { + if (rela->sym->type != STT_SECTION) { + WARN("unexpected relocation symbol type in %s", sec->name); + return; } + + name = elf_strptr(file->elf->elf, strtab_sec->idx, rela->addend); + func = find_symbol_by_name(file->elf, name); + if (!func) + continue; + + func_for_each_insn_all(file, func, insn) + insn->ignore = true; } + + return; } /* @@ -2198,7 +2191,6 @@ int check(const char *_objname, bool orc INIT_LIST_HEAD(&file.insn_list); hash_init(file.insn_hash); - file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard"); file.c_file = find_section_by_name(file.elf, ".comment"); file.ignore_unreachables = no_unreachable; file.hints = false; --- a/tools/objtool/check.h +++ b/tools/objtool/check.h @@ -60,7 +60,6 @@ struct objtool_file { struct elf *elf; struct list_head insn_list; DECLARE_HASHTABLE(insn_hash, 16); - struct section *whitelist; bool ignore_unreachables, c_file, hints, rodata; };
| |