* [PATCH 0/6] objtool: AUTOFDO fixes + alias improvements
@ 2025-11-20 20:52 Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 1/6] objtool: Support Clang AUTOFDO .cold functions Josh Poimboeuf
` (5 more replies)
0 siblings, 6 replies; 14+ messages in thread
From: Josh Poimboeuf @ 2025-11-20 20:52 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Peter Zijlstra, Rong Xu, Han Shen, Sriraman Tallam,
Krzysztof Pszeniczny
For tip/objtool/core.
- Patches 1 and 2 fix some issues which were found when testing with
AutoFDO .cold functions.
- Patches 3-5 make improvements to the handling of symbol aliases.
- Patch 6 uses the alias infrastructure to simplify the .cold
parent/child correlation code.
Josh Poimboeuf (6):
objtool: Support Clang AUTOFDO .cold functions
objtool: Fix .cold function detection for duplicate symbols
objtool: Don't alias undefined symbols
objtool: Return canonical symbol when aliases exist in symbol finding
helpers
objtool: Skip non-canonical aliased symbols in add_jump_table_alts()
objtool: Remove second pass of .cold function correlation
tools/objtool/check.c | 25 +---------
tools/objtool/elf.c | 71 +++++++++++++++++++++--------
tools/objtool/include/objtool/elf.h | 2 +-
3 files changed, 55 insertions(+), 43 deletions(-)
--
2.51.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/6] objtool: Support Clang AUTOFDO .cold functions
2025-11-20 20:52 [PATCH 0/6] objtool: AUTOFDO fixes + alias improvements Josh Poimboeuf
@ 2025-11-20 20:52 ` Josh Poimboeuf
2025-11-20 22:18 ` Rong Xu
2025-11-21 9:58 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 2/6] objtool: Fix .cold function detection for duplicate symbols Josh Poimboeuf
` (4 subsequent siblings)
5 siblings, 2 replies; 14+ messages in thread
From: Josh Poimboeuf @ 2025-11-20 20:52 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Peter Zijlstra, Rong Xu, Han Shen, Sriraman Tallam,
Krzysztof Pszeniczny
AutoFDO enables -fsplit-machine-functions which can move the cold parts
of a function to a <func>.cold symbol in a .text.split.<func> section.
Unlike GCC, the Clang <func>.cold symbols are not marked STT_FUNC. This
confuses objtool in several ways, resulting in warnings like the
following:
vmlinux.o: warning: objtool: apply_retpolines.cold+0xfc: unsupported instruction in callable function
vmlinux.o: warning: objtool: machine_check_poll.cold+0x2e: unsupported instruction in callable function
vmlinux.o: warning: objtool: free_deferred_objects.cold+0x1f: relocation to !ENDBR: free_deferred_objects.cold+0x26
vmlinux.o: warning: objtool: rpm_idle.cold+0xe0: relocation to !ENDBR: rpm_idle.cold+0xe7
vmlinux.o: warning: objtool: tcp_rcv_state_process.cold+0x1c: relocation to !ENDBR: tcp_rcv_state_process.cold+0x23
Fix it by marking the .cold symbols as STT_FUNC.
Fixes: 2fd65f7afd5a ("AutoFDO: Enable machine function split optimization for AutoFDO")
Reported-by: Rong Xu <xur@google.com>
Closes: https://lore.kernel.org/20251103215244.2080638-2-xur@google.com
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
tools/objtool/elf.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 3f20b257ab25..7895f65aca2a 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -502,8 +502,16 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
if (strstarts(sym->name, ".klp.sym"))
sym->klp = 1;
- if (!sym->klp && is_func_sym(sym) && strstr(sym->name, ".cold"))
+ if (!sym->klp && !is_sec_sym(sym) && strstr(sym->name, ".cold")) {
sym->cold = 1;
+
+ /*
+ * Clang doesn't mark cold subfunctions as STT_FUNC, which
+ * breaks several objtool assumptions. Fake it.
+ */
+ sym->type = STT_FUNC;
+ }
+
sym->pfunc = sym->cfunc = sym;
sym->demangled_name = demangle_name(sym);
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/6] objtool: Fix .cold function detection for duplicate symbols
2025-11-20 20:52 [PATCH 0/6] objtool: AUTOFDO fixes + alias improvements Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 1/6] objtool: Support Clang AUTOFDO .cold functions Josh Poimboeuf
@ 2025-11-20 20:52 ` Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 3/6] objtool: Don't alias undefined symbols Josh Poimboeuf
` (3 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Josh Poimboeuf @ 2025-11-20 20:52 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Peter Zijlstra, Rong Xu, Han Shen, Sriraman Tallam,
Krzysztof Pszeniczny
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>
---
tools/objtool/elf.c | 28 ++++++++++++++++++++++++++--
tools/objtool/include/objtool/elf.h | 2 +-
2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 7895f65aca2a..fffca31d47ed 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -288,6 +288,23 @@ struct symbol *find_symbol_by_name(const struct elf *elf, const char *name)
return NULL;
}
+/* Find local symbol with matching STT_FILE */
+static struct symbol *find_local_symbol_by_file_and_name(const struct elf *elf,
+ struct symbol *file,
+ const char *name)
+{
+ struct symbol *sym;
+
+ elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(name)) {
+ if (sym->bind == STB_LOCAL && sym->file == file &&
+ !strcmp(sym->name, name)) {
+ return sym;
+ }
+ }
+
+ return NULL;
+}
+
struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name)
{
struct symbol *sym;
@@ -524,7 +541,7 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
static int read_symbols(struct elf *elf)
{
struct section *symtab, *symtab_shndx, *sec;
- struct symbol *sym, *pfunc;
+ struct symbol *sym, *pfunc, *file = NULL;
int symbols_nr, i;
char *coldstr;
Elf_Data *shndx_data = NULL;
@@ -597,6 +614,11 @@ static int read_symbols(struct elf *elf)
if (elf_add_symbol(elf, sym))
return -1;
+
+ if (sym->type == STT_FILE)
+ file = sym;
+ else if (sym->bind == STB_LOCAL)
+ sym->file = file;
}
if (opts.stats) {
@@ -626,7 +648,9 @@ static int read_symbols(struct elf *elf)
return -1;
}
- pfunc = find_symbol_by_name(elf, pname);
+ pfunc = find_local_symbol_by_file_and_name(elf, sym->file, pname);
+ if (!pfunc)
+ pfunc = find_global_symbol_by_name(elf, pname);
free(pname);
if (!pfunc) {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 21d8b825fd8f..e12c516bd320 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -69,7 +69,7 @@ struct symbol {
unsigned int idx, len;
unsigned long offset;
unsigned long __subtree_last;
- struct symbol *pfunc, *cfunc, *alias;
+ struct symbol *pfunc, *cfunc, *alias, *file;
unsigned char bind, type;
u8 uaccess_safe : 1;
u8 static_call_tramp : 1;
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/6] objtool: Don't alias undefined symbols
2025-11-20 20:52 [PATCH 0/6] objtool: AUTOFDO fixes + alias improvements Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 1/6] objtool: Support Clang AUTOFDO .cold functions Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 2/6] objtool: Fix .cold function detection for duplicate symbols Josh Poimboeuf
@ 2025-11-20 20:52 ` Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 4/6] objtool: Return canonical symbol when aliases exist in symbol finding helpers Josh Poimboeuf
` (2 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Josh Poimboeuf @ 2025-11-20 20:52 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Peter Zijlstra, Rong Xu, Han Shen, Sriraman Tallam,
Krzysztof Pszeniczny
Objtool is mistakenly aliasing all undefined symbols. That's obviously
wrong, though it has no consequence since objtool happens to only use
sym->alias for defined symbols. Fix it regardless.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
tools/objtool/elf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index fffca31d47ed..4f15643ad70c 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -492,8 +492,8 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
sym->len = sym->sym.st_size;
__sym_for_each(iter, &sym->sec->symbol_tree, sym->offset, sym->offset) {
- if (iter->offset == sym->offset && iter->type == sym->type &&
- iter->len == sym->len)
+ if (!is_undef_sym(iter) && iter->offset == sym->offset &&
+ iter->type == sym->type && iter->len == sym->len)
iter->alias = sym;
}
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/6] objtool: Return canonical symbol when aliases exist in symbol finding helpers
2025-11-20 20:52 [PATCH 0/6] objtool: AUTOFDO fixes + alias improvements Josh Poimboeuf
` (2 preceding siblings ...)
2025-11-20 20:52 ` [PATCH 3/6] objtool: Don't alias undefined symbols Josh Poimboeuf
@ 2025-11-20 20:52 ` Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 5/6] objtool: Skip non-canonical aliased symbols in add_jump_table_alts() Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 6/6] objtool: Remove second pass of .cold function correlation Josh Poimboeuf
5 siblings, 1 reply; 14+ messages in thread
From: Josh Poimboeuf @ 2025-11-20 20:52 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Peter Zijlstra, Rong Xu, Han Shen, Sriraman Tallam,
Krzysztof Pszeniczny
When symbol alias ambiguity exists in the symbol finding helper
functions, return the canonical sym->alias, as that's the one which gets
used by validate_branch() and elsewhere.
This doesn't fix any known issues, just makes the symbol alias behavior
more robust.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
tools/objtool/elf.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 4f15643ad70c..7e2c0ae6b41a 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -172,11 +172,11 @@ static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx)
struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset)
{
struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree;
- struct symbol *iter;
+ struct symbol *sym;
- __sym_for_each(iter, tree, offset, offset) {
- if (iter->offset == offset && !is_sec_sym(iter))
- return iter;
+ __sym_for_each(sym, tree, offset, offset) {
+ if (sym->offset == offset && !is_sec_sym(sym))
+ return sym->alias;
}
return NULL;
@@ -185,11 +185,11 @@ struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset)
struct symbol *find_func_by_offset(struct section *sec, unsigned long offset)
{
struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree;
- struct symbol *iter;
+ struct symbol *func;
- __sym_for_each(iter, tree, offset, offset) {
- if (iter->offset == offset && is_func_sym(iter))
- return iter;
+ __sym_for_each(func, tree, offset, offset) {
+ if (func->offset == offset && is_func_sym(func))
+ return func->alias;
}
return NULL;
@@ -220,7 +220,7 @@ struct symbol *find_symbol_containing(const struct section *sec, unsigned long o
}
}
- return sym;
+ return sym ? sym->alias : NULL;
}
/*
@@ -266,11 +266,11 @@ int find_symbol_hole_containing(const struct section *sec, unsigned long offset)
struct symbol *find_func_containing(struct section *sec, unsigned long offset)
{
struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree;
- struct symbol *iter;
+ struct symbol *func;
- __sym_for_each(iter, tree, offset, offset) {
- if (is_func_sym(iter))
- return iter;
+ __sym_for_each(func, tree, offset, offset) {
+ if (is_func_sym(func))
+ return func->alias;
}
return NULL;
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/6] objtool: Skip non-canonical aliased symbols in add_jump_table_alts()
2025-11-20 20:52 [PATCH 0/6] objtool: AUTOFDO fixes + alias improvements Josh Poimboeuf
` (3 preceding siblings ...)
2025-11-20 20:52 ` [PATCH 4/6] objtool: Return canonical symbol when aliases exist in symbol finding helpers Josh Poimboeuf
@ 2025-11-20 20:52 ` Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 6/6] objtool: Remove second pass of .cold function correlation Josh Poimboeuf
5 siblings, 1 reply; 14+ messages in thread
From: Josh Poimboeuf @ 2025-11-20 20:52 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Peter Zijlstra, Rong Xu, Han Shen, Sriraman Tallam,
Krzysztof Pszeniczny
If a symbol has aliases, make add_jump_table_alts() skip the
non-canonical ones to avoid any surprises.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
tools/objtool/check.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 72c7f6f03350..6a4a29f8f2f5 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2197,7 +2197,7 @@ static int add_jump_table_alts(struct objtool_file *file)
return 0;
for_each_sym(file->elf, func) {
- if (!is_func_sym(func))
+ if (!is_func_sym(func) || func->alias != func)
continue;
mark_func_jump_tables(file, func);
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 6/6] objtool: Remove second pass of .cold function correlation
2025-11-20 20:52 [PATCH 0/6] objtool: AUTOFDO fixes + alias improvements Josh Poimboeuf
` (4 preceding siblings ...)
2025-11-20 20:52 ` [PATCH 5/6] objtool: Skip non-canonical aliased symbols in add_jump_table_alts() Josh Poimboeuf
@ 2025-11-20 20:52 ` Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
5 siblings, 1 reply; 14+ messages in thread
From: Josh Poimboeuf @ 2025-11-20 20:52 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Peter Zijlstra, Rong Xu, Han Shen, Sriraman Tallam,
Krzysztof Pszeniczny
The .cold function parent/child correlation logic has two passes: one in
read_symbols() and one in add_jump_destinations().
The second pass was added with commit cd77849a69cf ("objtool: Fix GCC 8
cold subfunction detection for aliased functions") to ensure that if the
parent symbol had aliases then the canonical symbol was chosen as the
parent.
That solution was rather clunky, not to mention incomplete due to the
existence of alternatives and switch tables. Now that we have
sym->alias, the canonical alias fix can be done much simpler in the
first pass, making the second pass obsolete.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
tools/objtool/check.c | 23 +----------------------
tools/objtool/elf.c | 3 ++-
2 files changed, 3 insertions(+), 23 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 6a4a29f8f2f5..1a20ff89df74 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1623,34 +1623,13 @@ static int add_jump_destinations(struct objtool_file *file)
continue;
}
- if (!insn->sym || insn->sym == dest_insn->sym)
+ if (!insn->sym || insn->sym->pfunc == dest_sym->pfunc)
goto set_jump_dest;
/*
* Internal cross-function jump.
*/
- /*
- * For GCC 8+, create parent/child links for any cold
- * subfunctions. This is _mostly_ redundant with a
- * similar initialization in read_symbols().
- *
- * If a function has aliases, we want the *first* such
- * function in the symbol table to be the subfunction's
- * parent. In that case we overwrite the
- * initialization done in read_symbols().
- *
- * However this code can't completely replace the
- * read_symbols() code because this doesn't detect the
- * case where the parent function's only reference to a
- * subfunction is through a jump table.
- */
- if (func && dest_sym->cold) {
- func->cfunc = dest_sym;
- dest_sym->pfunc = func;
- goto set_jump_dest;
- }
-
if (is_first_func_insn(file, dest_insn)) {
/* Internal sibling call */
if (add_call_dest(file, insn, dest_sym, true))
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 7e2c0ae6b41a..6a8ed9c62323 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -658,8 +658,9 @@ static int read_symbols(struct elf *elf)
return -1;
}
- sym->pfunc = pfunc;
+ sym->pfunc = pfunc->alias;
pfunc->cfunc = sym;
+ pfunc->alias->cfunc = sym;
/*
* Unfortunately, -fnoreorder-functions puts the child
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] objtool: Support Clang AUTOFDO .cold functions
2025-11-20 20:52 ` [PATCH 1/6] objtool: Support Clang AUTOFDO .cold functions Josh Poimboeuf
@ 2025-11-20 22:18 ` Rong Xu
2025-11-21 9:58 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
1 sibling, 0 replies; 14+ messages in thread
From: Rong Xu @ 2025-11-20 22:18 UTC (permalink / raw)
To: Josh Poimboeuf
Cc: x86, linux-kernel, Peter Zijlstra, Han Shen, Sriraman Tallam,
Krzysztof Pszeniczny
Thanks Josh for the fix. I can confirm this fixes the objtool issue
related to split-function in AutoFDO and Propeller builds
Tested-by: xur@google.com
Reviewed-by: xur@google.com
-Rong
On Thu, Nov 20, 2025 at 12:52 PM Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> AutoFDO enables -fsplit-machine-functions which can move the cold parts
> of a function to a <func>.cold symbol in a .text.split.<func> section.
>
> Unlike GCC, the Clang <func>.cold symbols are not marked STT_FUNC. This
> confuses objtool in several ways, resulting in warnings like the
> following:
>
> vmlinux.o: warning: objtool: apply_retpolines.cold+0xfc: unsupported instruction in callable function
> vmlinux.o: warning: objtool: machine_check_poll.cold+0x2e: unsupported instruction in callable function
> vmlinux.o: warning: objtool: free_deferred_objects.cold+0x1f: relocation to !ENDBR: free_deferred_objects.cold+0x26
> vmlinux.o: warning: objtool: rpm_idle.cold+0xe0: relocation to !ENDBR: rpm_idle.cold+0xe7
> vmlinux.o: warning: objtool: tcp_rcv_state_process.cold+0x1c: relocation to !ENDBR: tcp_rcv_state_process.cold+0x23
>
> Fix it by marking the .cold symbols as STT_FUNC.
>
> Fixes: 2fd65f7afd5a ("AutoFDO: Enable machine function split optimization for AutoFDO")
> Reported-by: Rong Xu <xur@google.com>
> Closes: https://lore.kernel.org/20251103215244.2080638-2-xur@google.com
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
> ---
> tools/objtool/elf.c | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
> index 3f20b257ab25..7895f65aca2a 100644
> --- a/tools/objtool/elf.c
> +++ b/tools/objtool/elf.c
> @@ -502,8 +502,16 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
> if (strstarts(sym->name, ".klp.sym"))
> sym->klp = 1;
>
> - if (!sym->klp && is_func_sym(sym) && strstr(sym->name, ".cold"))
> + if (!sym->klp && !is_sec_sym(sym) && strstr(sym->name, ".cold")) {
> sym->cold = 1;
> +
> + /*
> + * Clang doesn't mark cold subfunctions as STT_FUNC, which
> + * breaks several objtool assumptions. Fake it.
> + */
> + sym->type = STT_FUNC;
> + }
> +
> sym->pfunc = sym->cfunc = sym;
>
> sym->demangled_name = demangle_name(sym);
> --
> 2.51.1
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [tip: objtool/core] objtool: Remove second pass of .cold function correlation
2025-11-20 20:52 ` [PATCH 6/6] objtool: Remove second pass of .cold function correlation Josh Poimboeuf
@ 2025-11-21 9:57 ` tip-bot2 for Josh Poimboeuf
0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2025-11-21 9:57 UTC (permalink / raw)
To: linux-tip-commits
Cc: Josh Poimboeuf, Peter Zijlstra (Intel), x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 106f11d43be53156187270d00c83ddf5ef3f6ac6
Gitweb: https://git.kernel.org/tip/106f11d43be53156187270d00c83ddf5ef3f6ac6
Author: Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate: Thu, 20 Nov 2025 12:52:20 -08:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 21 Nov 2025 10:04:08 +01:00
objtool: Remove second pass of .cold function correlation
The .cold function parent/child correlation logic has two passes: one in
read_symbols() and one in add_jump_destinations().
The second pass was added with commit cd77849a69cf ("objtool: Fix GCC 8
cold subfunction detection for aliased functions") to ensure that if the
parent symbol had aliases then the canonical symbol was chosen as the
parent.
That solution was rather clunky, not to mention incomplete due to the
existence of alternatives and switch tables. Now that we have
sym->alias, the canonical alias fix can be done much simpler in the
first pass, making the second pass obsolete.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/bdab245a38000a5407f663a031f39e14c67a43d4.1763671318.git.jpoimboe@kernel.org
---
tools/objtool/check.c | 23 +----------------------
tools/objtool/elf.c | 3 ++-
2 files changed, 3 insertions(+), 23 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 6a4a29f..1a20ff8 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1623,34 +1623,13 @@ static int add_jump_destinations(struct objtool_file *file)
continue;
}
- if (!insn->sym || insn->sym == dest_insn->sym)
+ if (!insn->sym || insn->sym->pfunc == dest_sym->pfunc)
goto set_jump_dest;
/*
* Internal cross-function jump.
*/
- /*
- * For GCC 8+, create parent/child links for any cold
- * subfunctions. This is _mostly_ redundant with a
- * similar initialization in read_symbols().
- *
- * If a function has aliases, we want the *first* such
- * function in the symbol table to be the subfunction's
- * parent. In that case we overwrite the
- * initialization done in read_symbols().
- *
- * However this code can't completely replace the
- * read_symbols() code because this doesn't detect the
- * case where the parent function's only reference to a
- * subfunction is through a jump table.
- */
- if (func && dest_sym->cold) {
- func->cfunc = dest_sym;
- dest_sym->pfunc = func;
- goto set_jump_dest;
- }
-
if (is_first_func_insn(file, dest_insn)) {
/* Internal sibling call */
if (add_call_dest(file, insn, dest_sym, true))
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 7e2c0ae..6a8ed9c 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -658,8 +658,9 @@ static int read_symbols(struct elf *elf)
return -1;
}
- sym->pfunc = pfunc;
+ sym->pfunc = pfunc->alias;
pfunc->cfunc = sym;
+ pfunc->alias->cfunc = sym;
/*
* Unfortunately, -fnoreorder-functions puts the child
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip: objtool/core] objtool: Skip non-canonical aliased symbols in add_jump_table_alts()
2025-11-20 20:52 ` [PATCH 5/6] objtool: Skip non-canonical aliased symbols in add_jump_table_alts() Josh Poimboeuf
@ 2025-11-21 9:57 ` tip-bot2 for Josh Poimboeuf
0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2025-11-21 9:57 UTC (permalink / raw)
To: linux-tip-commits
Cc: Josh Poimboeuf, Peter Zijlstra (Intel), x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: a91a61b290430ba0dd2c42378f744d6b21657f42
Gitweb: https://git.kernel.org/tip/a91a61b290430ba0dd2c42378f744d6b21657f42
Author: Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate: Thu, 20 Nov 2025 12:52:19 -08:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 21 Nov 2025 10:04:08 +01:00
objtool: Skip non-canonical aliased symbols in add_jump_table_alts()
If a symbol has aliases, make add_jump_table_alts() skip the
non-canonical ones to avoid any surprises.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/169aa17564b9aadb74897945ea74ac2eb70c5b13.1763671318.git.jpoimboe@kernel.org
---
tools/objtool/check.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 72c7f6f..6a4a29f 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2197,7 +2197,7 @@ static int add_jump_table_alts(struct objtool_file *file)
return 0;
for_each_sym(file->elf, func) {
- if (!is_func_sym(func))
+ if (!is_func_sym(func) || func->alias != func)
continue;
mark_func_jump_tables(file, func);
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip: objtool/core] objtool: Return canonical symbol when aliases exist in symbol finding helpers
2025-11-20 20:52 ` [PATCH 4/6] objtool: Return canonical symbol when aliases exist in symbol finding helpers Josh Poimboeuf
@ 2025-11-21 9:57 ` tip-bot2 for Josh Poimboeuf
0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2025-11-21 9:57 UTC (permalink / raw)
To: linux-tip-commits
Cc: Josh Poimboeuf, Peter Zijlstra (Intel), x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 9205a322cf96f16a49e412dfa3f09431f3e02fc5
Gitweb: https://git.kernel.org/tip/9205a322cf96f16a49e412dfa3f09431f3e02fc5
Author: Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate: Thu, 20 Nov 2025 12:52:18 -08:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 21 Nov 2025 10:04:08 +01:00
objtool: Return canonical symbol when aliases exist in symbol finding helpers
When symbol alias ambiguity exists in the symbol finding helper
functions, return the canonical sym->alias, as that's the one which gets
used by validate_branch() and elsewhere.
This doesn't fix any known issues, just makes the symbol alias behavior
more robust.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/450470a4897706af77453ad333e18af5ebab653c.1763671318.git.jpoimboe@kernel.org
---
tools/objtool/elf.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 4f15643..7e2c0ae 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -172,11 +172,11 @@ static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx)
struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset)
{
struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree;
- struct symbol *iter;
+ struct symbol *sym;
- __sym_for_each(iter, tree, offset, offset) {
- if (iter->offset == offset && !is_sec_sym(iter))
- return iter;
+ __sym_for_each(sym, tree, offset, offset) {
+ if (sym->offset == offset && !is_sec_sym(sym))
+ return sym->alias;
}
return NULL;
@@ -185,11 +185,11 @@ struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset)
struct symbol *find_func_by_offset(struct section *sec, unsigned long offset)
{
struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree;
- struct symbol *iter;
+ struct symbol *func;
- __sym_for_each(iter, tree, offset, offset) {
- if (iter->offset == offset && is_func_sym(iter))
- return iter;
+ __sym_for_each(func, tree, offset, offset) {
+ if (func->offset == offset && is_func_sym(func))
+ return func->alias;
}
return NULL;
@@ -220,7 +220,7 @@ struct symbol *find_symbol_containing(const struct section *sec, unsigned long o
}
}
- return sym;
+ return sym ? sym->alias : NULL;
}
/*
@@ -266,11 +266,11 @@ int find_symbol_hole_containing(const struct section *sec, unsigned long offset)
struct symbol *find_func_containing(struct section *sec, unsigned long offset)
{
struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree;
- struct symbol *iter;
+ struct symbol *func;
- __sym_for_each(iter, tree, offset, offset) {
- if (is_func_sym(iter))
- return iter;
+ __sym_for_each(func, tree, offset, offset) {
+ if (is_func_sym(func))
+ return func->alias;
}
return NULL;
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip: objtool/core] objtool: Don't alias undefined symbols
2025-11-20 20:52 ` [PATCH 3/6] objtool: Don't alias undefined symbols Josh Poimboeuf
@ 2025-11-21 9:57 ` tip-bot2 for Josh Poimboeuf
0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2025-11-21 9:57 UTC (permalink / raw)
To: linux-tip-commits
Cc: Josh Poimboeuf, Peter Zijlstra (Intel), x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 16f366c5a68839736d3616b466f1738811408ec7
Gitweb: https://git.kernel.org/tip/16f366c5a68839736d3616b466f1738811408ec7
Author: Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate: Thu, 20 Nov 2025 12:52:17 -08:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 21 Nov 2025 10:04:08 +01:00
objtool: Don't alias undefined symbols
Objtool is mistakenly aliasing all undefined symbols. That's obviously
wrong, though it has no consequence since objtool happens to only use
sym->alias for defined symbols. Fix it regardless.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/bc401173a7717757eee672fc1ca5a20451d77b86.1763671318.git.jpoimboe@kernel.org
---
tools/objtool/elf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index fffca31..4f15643 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -492,8 +492,8 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
sym->len = sym->sym.st_size;
__sym_for_each(iter, &sym->sec->symbol_tree, sym->offset, sym->offset) {
- if (iter->offset == sym->offset && iter->type == sym->type &&
- iter->len == sym->len)
+ if (!is_undef_sym(iter) && iter->offset == sym->offset &&
+ iter->type == sym->type && iter->len == sym->len)
iter->alias = sym;
}
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip: objtool/core] objtool: Fix .cold function detection for duplicate symbols
2025-11-20 20:52 ` [PATCH 2/6] objtool: Fix .cold function detection for duplicate symbols Josh Poimboeuf
@ 2025-11-21 9:57 ` tip-bot2 for Josh Poimboeuf
0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2025-11-21 9:57 UTC (permalink / raw)
To: linux-tip-commits
Cc: Josh Poimboeuf, Peter Zijlstra (Intel), x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 2c2acca2eabf53a954ed5aacef987bbf909b9f12
Gitweb: https://git.kernel.org/tip/2c2acca2eabf53a954ed5aacef987bbf909b9f12
Author: Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate: Thu, 20 Nov 2025 12:52:16 -08:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 21 Nov 2025 10:04:07 +01:00
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
---
tools/objtool/elf.c | 28 ++++++++++++++++++++++++++--
tools/objtool/include/objtool/elf.h | 2 +-
2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 7895f65..fffca31 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -288,6 +288,23 @@ struct symbol *find_symbol_by_name(const struct elf *elf, const char *name)
return NULL;
}
+/* Find local symbol with matching STT_FILE */
+static struct symbol *find_local_symbol_by_file_and_name(const struct elf *elf,
+ struct symbol *file,
+ const char *name)
+{
+ struct symbol *sym;
+
+ elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(name)) {
+ if (sym->bind == STB_LOCAL && sym->file == file &&
+ !strcmp(sym->name, name)) {
+ return sym;
+ }
+ }
+
+ return NULL;
+}
+
struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name)
{
struct symbol *sym;
@@ -524,7 +541,7 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
static int read_symbols(struct elf *elf)
{
struct section *symtab, *symtab_shndx, *sec;
- struct symbol *sym, *pfunc;
+ struct symbol *sym, *pfunc, *file = NULL;
int symbols_nr, i;
char *coldstr;
Elf_Data *shndx_data = NULL;
@@ -597,6 +614,11 @@ static int read_symbols(struct elf *elf)
if (elf_add_symbol(elf, sym))
return -1;
+
+ if (sym->type == STT_FILE)
+ file = sym;
+ else if (sym->bind == STB_LOCAL)
+ sym->file = file;
}
if (opts.stats) {
@@ -626,7 +648,9 @@ static int read_symbols(struct elf *elf)
return -1;
}
- pfunc = find_symbol_by_name(elf, pname);
+ pfunc = find_local_symbol_by_file_and_name(elf, sym->file, pname);
+ if (!pfunc)
+ pfunc = find_global_symbol_by_name(elf, pname);
free(pname);
if (!pfunc) {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 21d8b82..e12c516 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -69,7 +69,7 @@ struct symbol {
unsigned int idx, len;
unsigned long offset;
unsigned long __subtree_last;
- struct symbol *pfunc, *cfunc, *alias;
+ struct symbol *pfunc, *cfunc, *alias, *file;
unsigned char bind, type;
u8 uaccess_safe : 1;
u8 static_call_tramp : 1;
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip: objtool/core] objtool: Support Clang AUTOFDO .cold functions
2025-11-20 20:52 ` [PATCH 1/6] objtool: Support Clang AUTOFDO .cold functions Josh Poimboeuf
2025-11-20 22:18 ` Rong Xu
@ 2025-11-21 9:58 ` tip-bot2 for Josh Poimboeuf
1 sibling, 0 replies; 14+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2025-11-21 9:58 UTC (permalink / raw)
To: linux-tip-commits
Cc: Rong Xu, Josh Poimboeuf, Peter Zijlstra (Intel), x86,
linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 024020e2b6adb4e568fb80f624b5e20d8943f107
Gitweb: https://git.kernel.org/tip/024020e2b6adb4e568fb80f624b5e20d8943f107
Author: Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate: Thu, 20 Nov 2025 12:52:15 -08:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 21 Nov 2025 10:04:07 +01:00
objtool: Support Clang AUTOFDO .cold functions
AutoFDO enables -fsplit-machine-functions which can move the cold parts
of a function to a <func>.cold symbol in a .text.split.<func> section.
Unlike GCC, the Clang <func>.cold symbols are not marked STT_FUNC. This
confuses objtool in several ways, resulting in warnings like the
following:
vmlinux.o: warning: objtool: apply_retpolines.cold+0xfc: unsupported instruction in callable function
vmlinux.o: warning: objtool: machine_check_poll.cold+0x2e: unsupported instruction in callable function
vmlinux.o: warning: objtool: free_deferred_objects.cold+0x1f: relocation to !ENDBR: free_deferred_objects.cold+0x26
vmlinux.o: warning: objtool: rpm_idle.cold+0xe0: relocation to !ENDBR: rpm_idle.cold+0xe7
vmlinux.o: warning: objtool: tcp_rcv_state_process.cold+0x1c: relocation to !ENDBR: tcp_rcv_state_process.cold+0x23
Fix it by marking the .cold symbols as STT_FUNC.
Fixes: 2fd65f7afd5a ("AutoFDO: Enable machine function split optimization for AutoFDO")
Closes: https://lore.kernel.org/20251103215244.2080638-2-xur@google.com
Reported-by: Rong Xu <xur@google.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: xur@google.com
Tested-by: xur@google.com
Link: https://patch.msgid.link/20a67326f04b2a361c031b56d58e8a803b3c5893.1763671318.git.jpoimboe@kernel.org
---
tools/objtool/elf.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 3f20b25..7895f65 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -502,8 +502,16 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
if (strstarts(sym->name, ".klp.sym"))
sym->klp = 1;
- if (!sym->klp && is_func_sym(sym) && strstr(sym->name, ".cold"))
+ if (!sym->klp && !is_sec_sym(sym) && strstr(sym->name, ".cold")) {
sym->cold = 1;
+
+ /*
+ * Clang doesn't mark cold subfunctions as STT_FUNC, which
+ * breaks several objtool assumptions. Fake it.
+ */
+ sym->type = STT_FUNC;
+ }
+
sym->pfunc = sym->cfunc = sym;
sym->demangled_name = demangle_name(sym);
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2025-11-21 9:58 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-20 20:52 [PATCH 0/6] objtool: AUTOFDO fixes + alias improvements Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 1/6] objtool: Support Clang AUTOFDO .cold functions Josh Poimboeuf
2025-11-20 22:18 ` Rong Xu
2025-11-21 9:58 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 2/6] objtool: Fix .cold function detection for duplicate symbols Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 3/6] objtool: Don't alias undefined symbols Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 4/6] objtool: Return canonical symbol when aliases exist in symbol finding helpers Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 5/6] objtool: Skip non-canonical aliased symbols in add_jump_table_alts() Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2025-11-20 20:52 ` [PATCH 6/6] objtool: Remove second pass of .cold function correlation Josh Poimboeuf
2025-11-21 9:57 ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox