For duplicate strings, elf_add_string() just blindly adds duplicates. That can be a problem for arm64 which often uses two consecutive instructions (and corresponding relocations) to put an address into a register, like:
d8: 90000001 adrp x1, 0 <meminfo_proc_show> d8: R_AARCH64_ADR_PREL_PG_HI21 .rodata.meminfo_proc_show.str1.8 dc: 91000021 add x1, x1, #0x0 dc: R_AARCH64_ADD_ABS_LO12_NC .rodata.meminfo_proc_show.str1.8 Referencing two different string addresses in the adrp+add pair can result in a corrupt string addresses. Detect such consecutive reuses and force them to use the same string. Signed-off-by: Josh Poimboeuf <[email protected]> --- tools/objtool/elf.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index 3da90686350d..52ef991115fc 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c @@ -1321,6 +1321,8 @@ struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name) unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str) { + static unsigned int last_off; + static const char *last_str; unsigned int offset; if (!strtab) @@ -1329,17 +1331,22 @@ unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char ERROR("can't find .strtab section"); return -1; } - if (!strtab->sh.sh_addralign) { ERROR("'%s': invalid sh_addralign", strtab->name); return -1; } + if (last_str && !strcmp(last_str, str)) + return last_off; + offset = ALIGN(strtab->sh.sh_size, strtab->sh.sh_addralign); if (!elf_add_data(elf, strtab, str, strlen(str) + 1)) return -1; + last_str = str; + last_off = offset; + return offset; } -- 2.53.0

