On arm64 with CONFIG_CFI=y, Clang places a 4-byte kCFI type hash immediately before each address-taken function entry. Since these hashes are in the text section, objtool tries to decode them, leading to unpredictable results (e.g., "unannotated intra-function call").
arm64 uses mapping symbols to annotate where code ends and data begins (and vice versa). Use those to just mark such "instructions" as NOP so objtool will ignore them. Signed-off-by: Josh Poimboeuf <[email protected]> --- tools/objtool/check.c | 15 +++++++++++++++ tools/objtool/include/objtool/elf.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index e05dc7a93dc1e..2b03a2d6fc952 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -25,6 +25,7 @@ #include <linux/kernel.h> #include <linux/static_call_types.h> #include <linux/string.h> +#include <linux/kconfig.h> static unsigned long nr_cfi, nr_cfi_reused, nr_cfi_cache; @@ -428,6 +429,8 @@ static int decode_instructions(struct objtool_file *file) for_each_sec(file->elf, sec) { struct instruction *insns = NULL; + struct symbol *map_sym; + bool is_data = false; u8 prev_len = 0; u8 idx = 0; @@ -454,6 +457,8 @@ static int decode_instructions(struct objtool_file *file) if (!strcmp(sec->name, ".init.text") && !opts.module) sec->init = true; + map_sym = list_first_entry(&sec->symbol_list, struct symbol, list); + for (offset = 0; offset < sec_size(sec); offset += insn->len) { if (!insns || idx == INSN_CHUNK_MAX) { insns = calloc(INSN_CHUNK_SIZE, sizeof(*insn)); @@ -478,6 +483,16 @@ static int decode_instructions(struct objtool_file *file) prev_len = insn->len; + /* Use mapping symbols to skip data in text sections */ + sec_for_each_sym_from(sec, map_sym) { + if (map_sym->offset > offset) + break; + if (is_mapping_sym(map_sym)) + is_data = is_data_mapping_sym(map_sym); + } + if (is_data) + insn->type = INSN_NOP; + /* * By default, "ud2" is a dead end unless otherwise * annotated, because GCC 7 inserts it for certain diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h index d895023674673..9d36b14f420e2 100644 --- a/tools/objtool/include/objtool/elf.h +++ b/tools/objtool/include/objtool/elf.h @@ -507,6 +507,9 @@ static inline void set_sym_next_reloc(struct reloc *reloc, struct reloc *next) #define sec_for_each_sym(sec, sym) \ list_for_each_entry(sym, &sec->symbol_list, list) +#define sec_for_each_sym_from(sec, sym) \ + list_for_each_entry_from(sym, &sec->symbol_list, list) + #define sec_prev_sym(sym) \ sym->sec && sym->list.prev != &sym->sec->symbol_list ? \ list_prev_entry(sym, list) : NULL -- 2.53.0

