Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

objtool: Fix .cold function detection for duplicate symbols

The objtool .cold child/parent correlation is done in two phases: first
in elf_add_symbol() and later in add_jump_destinations().

The first phase is rather crude and can pick the wrong parent if there
are duplicates with the same name.

The second phase usually fixes that, but only if the parent has a direct
jump to the child. It does *not* work if the only branch from the
parent to the child is an alternative or jump table entry.

Make the first phase more robust by looking for the parent in the same
STT_FILE as the child.

Fixes the following objtool warnings in an AutoFDO build with a large
CLANG_AUTOFDO_PROFILE profile:

vmlinux.o: warning: objtool: rdev_add_key() falls through to next function rdev_add_key.cold()
vmlinux.o: warning: objtool: rdev_set_default_key() falls through to next function rdev_set_default_key.cold()

Fixes: 13810435b9a7 ("objtool: Support GCC 8's cold subfunctions")
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/82c7b52e40efa75dd10e1c550cc75c1ce10ac2c9.1763671318.git.jpoimboe@kernel.org

authored by

Josh Poimboeuf and committed by
Peter Zijlstra
2c2acca2 024020e2

+27 -3
+26 -2
tools/objtool/elf.c
··· 288 288 return NULL; 289 289 } 290 290 291 + /* Find local symbol with matching STT_FILE */ 292 + static struct symbol *find_local_symbol_by_file_and_name(const struct elf *elf, 293 + struct symbol *file, 294 + const char *name) 295 + { 296 + struct symbol *sym; 297 + 298 + elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(name)) { 299 + if (sym->bind == STB_LOCAL && sym->file == file && 300 + !strcmp(sym->name, name)) { 301 + return sym; 302 + } 303 + } 304 + 305 + return NULL; 306 + } 307 + 291 308 struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name) 292 309 { 293 310 struct symbol *sym; ··· 541 524 static int read_symbols(struct elf *elf) 542 525 { 543 526 struct section *symtab, *symtab_shndx, *sec; 544 - struct symbol *sym, *pfunc; 527 + struct symbol *sym, *pfunc, *file = NULL; 545 528 int symbols_nr, i; 546 529 char *coldstr; 547 530 Elf_Data *shndx_data = NULL; ··· 614 597 615 598 if (elf_add_symbol(elf, sym)) 616 599 return -1; 600 + 601 + if (sym->type == STT_FILE) 602 + file = sym; 603 + else if (sym->bind == STB_LOCAL) 604 + sym->file = file; 617 605 } 618 606 619 607 if (opts.stats) { ··· 648 626 return -1; 649 627 } 650 628 651 - pfunc = find_symbol_by_name(elf, pname); 629 + pfunc = find_local_symbol_by_file_and_name(elf, sym->file, pname); 630 + if (!pfunc) 631 + pfunc = find_global_symbol_by_name(elf, pname); 652 632 free(pname); 653 633 654 634 if (!pfunc) {
+1 -1
tools/objtool/include/objtool/elf.h
··· 69 69 unsigned int idx, len; 70 70 unsigned long offset; 71 71 unsigned long __subtree_last; 72 - struct symbol *pfunc, *cfunc, *alias; 72 + struct symbol *pfunc, *cfunc, *alias, *file; 73 73 unsigned char bind, type; 74 74 u8 uaccess_safe : 1; 75 75 u8 static_call_tramp : 1;