From: Josh Poimboeuf <jpoimboe@kernel.org>
To: x86@kernel.org
Cc: linux-kernel@vger.kernel.org, Petr Mladek <pmladek@suse.com>,
Miroslav Benes <mbenes@suse.cz>,
Joe Lawrence <joe.lawrence@redhat.com>,
live-patching@vger.kernel.org, Song Liu <song@kernel.org>,
laokz <laokz@foxmail.com>, Jiri Kosina <jikos@kernel.org>,
Marcos Paulo de Souza <mpdesouza@suse.com>,
Weinan Liu <wnliu@google.com>,
Fazla Mehrab <a.mehrab@bytedance.com>,
Chen Zhongjin <chenzhongjin@huawei.com>,
Puranjay Mohan <puranjay@kernel.org>,
Dylan Hatch <dylanbhatch@google.com>,
Peter Zijlstra <peterz@infradead.org>
Subject: [PATCH v4 37/63] objtool: Refactor add_jump_destinations()
Date: Wed, 17 Sep 2025 09:03:45 -0700 [thread overview]
Message-ID: <e8a19eb65fd70069ead9654bf8e2df9f60340338.1758067943.git.jpoimboe@kernel.org> (raw)
In-Reply-To: <cover.1758067942.git.jpoimboe@kernel.org>
The add_jump_destinations() logic is a bit weird and convoluted after
being incrementally tweaked over the years. Refactor it to hopefully be
more logical and straightforward.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
tools/objtool/check.c | 222 +++++++++++++---------------
tools/objtool/include/objtool/elf.h | 4 +-
2 files changed, 106 insertions(+), 120 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 2af4cafb683fa..6d21b83b9377a 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1423,9 +1423,14 @@ static void add_return_call(struct objtool_file *file, struct instruction *insn,
}
static bool is_first_func_insn(struct objtool_file *file,
- struct instruction *insn, struct symbol *sym)
+ struct instruction *insn)
{
- if (insn->offset == sym->offset)
+ struct symbol *func = insn_func(insn);
+
+ if (!func)
+ return false;
+
+ if (insn->offset == func->offset)
return true;
/* Allow direct CALL/JMP past ENDBR */
@@ -1433,51 +1438,30 @@ static bool is_first_func_insn(struct objtool_file *file,
struct instruction *prev = prev_insn_same_sym(file, insn);
if (prev && prev->type == INSN_ENDBR &&
- insn->offset == sym->offset + prev->len)
+ insn->offset == func->offset + prev->len)
return true;
}
return false;
}
-/*
- * A sibling call is a tail-call to another symbol -- to differentiate from a
- * recursive tail-call which is to the same symbol.
- */
-static bool jump_is_sibling_call(struct objtool_file *file,
- struct instruction *from, struct instruction *to)
-{
- struct symbol *fs = from->sym;
- struct symbol *ts = to->sym;
-
- /* Not a sibling call if from/to a symbol hole */
- if (!fs || !ts)
- return false;
-
- /* Not a sibling call if not targeting the start of a symbol. */
- if (!is_first_func_insn(file, to, ts))
- return false;
-
- /* Disallow sibling calls into STT_NOTYPE */
- if (is_notype_sym(ts))
- return false;
-
- /* Must not be self to be a sibling */
- return fs->pfunc != ts->pfunc;
-}
-
/*
* Find the destination instructions for all jumps.
*/
static int add_jump_destinations(struct objtool_file *file)
{
- struct instruction *insn, *jump_dest;
+ struct instruction *insn;
struct reloc *reloc;
- struct section *dest_sec;
- unsigned long dest_off;
for_each_insn(file, insn) {
struct symbol *func = insn_func(insn);
+ struct instruction *dest_insn;
+ struct section *dest_sec;
+ struct symbol *dest_sym;
+ unsigned long dest_off;
+
+ if (!is_static_jump(insn))
+ continue;
if (insn->jump_dest) {
/*
@@ -1486,51 +1470,53 @@ static int add_jump_destinations(struct objtool_file *file)
*/
continue;
}
- if (!is_static_jump(insn))
- continue;
reloc = insn_reloc(file, insn);
if (!reloc) {
dest_sec = insn->sec;
dest_off = arch_jump_destination(insn);
- } else if (is_sec_sym(reloc->sym)) {
- dest_sec = reloc->sym->sec;
- dest_off = arch_insn_adjusted_addend(insn, reloc);
- } else if (reloc->sym->retpoline_thunk) {
- if (add_retpoline_call(file, insn))
- return -1;
- continue;
- } else if (reloc->sym->return_thunk) {
- add_return_call(file, insn, true);
- continue;
- } else if (func) {
- /*
- * External sibling call or internal sibling call with
- * STT_FUNC reloc.
- */
- if (add_call_dest(file, insn, reloc->sym, true))
- return -1;
- continue;
- } else if (reloc->sym->sec->idx) {
- dest_sec = reloc->sym->sec;
- dest_off = reloc->sym->sym.st_value +
- arch_insn_adjusted_addend(insn, reloc);
+ dest_sym = dest_sec->sym;
} else {
- /* non-func asm code jumping to another file */
- continue;
+ dest_sym = reloc->sym;
+ if (is_undef_sym(dest_sym)) {
+ if (dest_sym->retpoline_thunk) {
+ if (add_retpoline_call(file, insn))
+ return -1;
+ continue;
+ }
+
+ if (dest_sym->return_thunk) {
+ add_return_call(file, insn, true);
+ continue;
+ }
+
+ /* External symbol */
+ if (func) {
+ /* External sibling call */
+ if (add_call_dest(file, insn, dest_sym, true))
+ return -1;
+ continue;
+ }
+
+ /* Non-func asm code jumping to external symbol */
+ continue;
+ }
+
+ dest_sec = dest_sym->sec;
+ dest_off = dest_sym->offset + arch_insn_adjusted_addend(insn, reloc);
}
- jump_dest = find_insn(file, dest_sec, dest_off);
- if (!jump_dest) {
+ dest_insn = find_insn(file, dest_sec, dest_off);
+ if (!dest_insn) {
struct symbol *sym = find_symbol_by_offset(dest_sec, dest_off);
/*
- * This is a special case for retbleed_untrain_ret().
- * It jumps to __x86_return_thunk(), but objtool
- * can't find the thunk's starting RET
- * instruction, because the RET is also in the
- * middle of another instruction. Objtool only
- * knows about the outer instruction.
+ * retbleed_untrain_ret() jumps to
+ * __x86_return_thunk(), but objtool can't find
+ * the thunk's starting RET instruction,
+ * because the RET is also in the middle of
+ * another instruction. Objtool only knows
+ * about the outer instruction.
*/
if (sym && sym->embedded_insn) {
add_return_call(file, insn, false);
@@ -1538,73 +1524,73 @@ static int add_jump_destinations(struct objtool_file *file)
}
/*
- * GCOV/KCOV dead code can jump to the end of the
- * function/section.
+ * GCOV/KCOV dead code can jump to the end of
+ * the function/section.
*/
if (file->ignore_unreachables && func &&
dest_sec == insn->sec &&
dest_off == func->offset + func->len)
continue;
- ERROR_INSN(insn, "can't find jump dest instruction at %s+0x%lx",
- dest_sec->name, dest_off);
+ ERROR_INSN(insn, "can't find jump dest instruction at %s",
+ offstr(dest_sec, dest_off));
return -1;
}
- /*
- * An intra-TU jump in retpoline.o might not have a relocation
- * for its jump dest, in which case the above
- * add_{retpoline,return}_call() didn't happen.
- */
- if (jump_dest->sym && jump_dest->offset == jump_dest->sym->offset) {
- if (jump_dest->sym->retpoline_thunk) {
- if (add_retpoline_call(file, insn))
- return -1;
- continue;
- }
- if (jump_dest->sym->return_thunk) {
- add_return_call(file, insn, true);
- continue;
- }
+ if (!dest_sym || is_sec_sym(dest_sym)) {
+ dest_sym = dest_insn->sym;
+ if (!dest_sym)
+ goto set_jump_dest;
}
- /*
- * Cross-function jump.
- */
-
- if (func && insn_func(jump_dest) && !func->cold &&
- insn_func(jump_dest)->cold) {
-
- /*
- * 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.
- */
- func->cfunc = insn_func(jump_dest);
- insn_func(jump_dest)->pfunc = func;
- }
-
- if (jump_is_sibling_call(file, insn, jump_dest)) {
- /*
- * Internal sibling call without reloc or with
- * STT_SECTION reloc.
- */
- if (add_call_dest(file, insn, insn_func(jump_dest), true))
+ if (dest_sym->retpoline_thunk && dest_insn->offset == dest_sym->offset) {
+ if (add_retpoline_call(file, insn))
return -1;
continue;
}
- insn->jump_dest = jump_dest;
+ if (dest_sym->return_thunk && dest_insn->offset == dest_sym->offset) {
+ add_return_call(file, insn, true);
+ continue;
+ }
+
+ if (!insn->sym || insn->sym == dest_insn->sym)
+ 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))
+ return -1;
+ continue;
+ }
+
+set_jump_dest:
+ insn->jump_dest = dest_insn;
}
return 0;
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 79edf82e76ddf..07fc41f574b90 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -181,9 +181,9 @@ static inline unsigned int elf_text_rela_type(struct elf *elf)
return elf_addr_size(elf) == 4 ? R_TEXT32 : R_TEXT64;
}
-static inline bool sym_has_sec(struct symbol *sym)
+static inline bool is_undef_sym(struct symbol *sym)
{
- return sym->sec->idx;
+ return !sym->sec->idx;
}
static inline bool is_null_sym(struct symbol *sym)
--
2.50.0
next prev parent reply other threads:[~2025-09-17 16:04 UTC|newest]
Thread overview: 93+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-17 16:03 [PATCH v4 00/63] objtool,livepatch: klp-build livepatch module generation Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 01/63] s390/vmlinux.lds.S: Prevent thunk functions from getting placed with normal text Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 02/63] vmlinux.lds: Unify TEXT_MAIN, DATA_MAIN, and related macros Josh Poimboeuf
2025-12-20 16:25 ` Carlos Llamas
2026-01-06 22:46 ` Will Deacon
2026-01-08 21:59 ` Carlos Llamas
2025-09-17 16:03 ` [PATCH v4 03/63] x86/module: Improve relocation error messages Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 04/63] x86/kprobes: Remove STACK_FRAME_NON_STANDARD annotation Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 05/63] compiler: Tweak __UNIQUE_ID() naming Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 06/63] compiler.h: Make addressable symbols less of an eyesore Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 07/63] elfnote: Change ELFNOTE() to use __UNIQUE_ID() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 08/63] kbuild: Remove 'kmod_' prefix from __KBUILD_MODNAME Josh Poimboeuf
2025-10-20 12:20 ` Alexander Stein
2025-10-20 17:22 ` Josh Poimboeuf
2025-10-22 9:53 ` Anders Roxell
[not found] ` <CGME20251020130001eucas1p259c59daada89ad0fece76b7a86581f0e@eucas1p2.samsung.com>
2025-10-20 12:59 ` Marek Szyprowski
2025-10-20 16:34 ` Mark Brown
2025-10-20 16:37 ` Cosmin Tanislav
2025-09-17 16:03 ` [PATCH v4 09/63] modpost: Ignore unresolved section bounds symbols Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 10/63] x86/alternative: Refactor INT3 call emulation selftest Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 11/63] interval_tree: Sync interval_tree_generic.h with tools Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 12/63] interval_tree: Fix ITSTATIC usage for *_subtree_search() Josh Poimboeuf
2025-09-18 16:30 ` [PATCH v4.1 " Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 13/63] objtool: Make find_symbol_containing() less arbitrary Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 14/63] objtool: Fix broken error handling in read_symbols() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 15/63] objtool: Propagate elf_truncate_section() error in elf_write() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 16/63] objtool: Remove error handling boilerplate Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 17/63] objtool: Add empty symbols to the symbol tree again Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 18/63] objtool: Fix interval tree insertion for zero-length symbols Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 19/63] objtool: Fix weak symbol detection Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 20/63] objtool: Fix x86 addend calculation Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 21/63] objtool: Fix __pa_symbol() relocation handling Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 22/63] objtool: Fix "unexpected end of section" warning for alternatives Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 23/63] objtool: Check for missing annotation entries in read_annotate() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 24/63] objtool: Const string cleanup Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 25/63] objtool: Clean up compiler flag usage Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 26/63] objtool: Remove .parainstructions reference Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 27/63] objtool: Convert elf iterator macros to use 'struct elf' Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 28/63] objtool: Add section/symbol type helpers Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 29/63] objtool: Mark .cold subfunctions Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 30/63] objtool: Fix weak symbol hole detection for .cold functions Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 31/63] objtool: Mark prefix functions Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 32/63] objtool: Simplify reloc offset calculation in unwind_read_hints() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 33/63] objtool: Avoid emptying lists for duplicate sections Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 34/63] objtool: Rename --Werror to --werror Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 35/63] objtool: Resurrect --backup option Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 36/63] objtool: Reindent check_options[] Josh Poimboeuf
2025-09-17 16:03 ` Josh Poimboeuf [this message]
2025-09-17 16:03 ` [PATCH v4 38/63] objtool: Simplify special symbol handling in elf_update_symbol() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 39/63] objtool: Generalize elf_create_symbol() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 40/63] objtool: Generalize elf_create_section() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 41/63] objtool: Add elf_create_data() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 42/63] objtool: Add elf_create_reloc() and elf_init_reloc() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 43/63] objtool: Add elf_create_file() Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 44/63] objtool: Add annotype() helper Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 45/63] objtool: Move ANNOTATE* macros to annotate.h Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 46/63] objtool: Add ANNOTATE_DATA_SPECIAL Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 47/63] x86/asm: Annotate special section entries Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 48/63] objtool: Unify STACK_FRAME_NON_STANDARD entry sizes Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 49/63] objtool/klp: Add --checksum option to generate per-function checksums Josh Poimboeuf
2025-10-27 1:19 ` Michael Kelley
2025-10-27 22:22 ` Josh Poimboeuf
2025-11-05 15:22 ` Michael Kelley
2025-11-11 20:09 ` Josh Poimboeuf
2025-11-12 1:39 ` Michael Kelley
2025-11-12 2:26 ` Michael Kelley
2025-11-12 4:04 ` Josh Poimboeuf
2025-11-12 4:32 ` Michael Kelley
2025-11-12 13:25 ` David Laight
2025-11-12 16:16 ` Josh Poimboeuf
2025-11-12 21:39 ` David Laight
2025-09-17 16:03 ` [PATCH v4 50/63] objtool/klp: Add --debug-checksum=<funcs> to show per-instruction checksums Josh Poimboeuf
2025-09-17 16:03 ` [PATCH v4 51/63] objtool/klp: Introduce klp diff subcommand for diffing object files Josh Poimboeuf
2025-10-08 14:01 ` Petr Mladek
2025-10-08 15:27 ` Josh Poimboeuf
2025-10-09 12:29 ` Petr Mladek
2025-10-09 23:19 ` Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 52/63] objtool/klp: Add --debug option to show cloning decisions Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 53/63] objtool/klp: Add post-link subcommand to finalize livepatch modules Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 54/63] objtool: Refactor prefix symbol creation code Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 55/63] objtool: Add base objtool support for livepatch modules Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 56/63] livepatch: Add CONFIG_KLP_BUILD Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 57/63] kbuild,objtool: Defer objtool validation step for CONFIG_KLP_BUILD Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 58/63] livepatch/klp-build: Introduce fix-patch-lines script to avoid __LINE__ diff noise Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 59/63] livepatch/klp-build: Add stub init code for livepatch modules Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 60/63] livepatch/klp-build: Introduce klp-build script for generating " Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 61/63] livepatch/klp-build: Add --debug option to show cloning decisions Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 62/63] livepatch/klp-build: Add --show-first-changed option to show function divergence Josh Poimboeuf
2025-09-17 16:04 ` [PATCH v4 63/63] livepatch: Introduce source code helpers for livepatch modules Josh Poimboeuf
2025-09-18 16:32 ` [PATCH v4 00/63] objtool,livepatch: klp-build livepatch module generation Josh Poimboeuf
2025-10-07 17:38 ` Joe Lawrence
2025-10-10 7:30 ` Petr Mladek
2025-10-11 0:54 ` Josh Poimboeuf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e8a19eb65fd70069ead9654bf8e2df9f60340338.1758067943.git.jpoimboe@kernel.org \
--to=jpoimboe@kernel.org \
--cc=a.mehrab@bytedance.com \
--cc=chenzhongjin@huawei.com \
--cc=dylanbhatch@google.com \
--cc=jikos@kernel.org \
--cc=joe.lawrence@redhat.com \
--cc=laokz@foxmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=mpdesouza@suse.com \
--cc=peterz@infradead.org \
--cc=pmladek@suse.com \
--cc=puranjay@kernel.org \
--cc=song@kernel.org \
--cc=wnliu@google.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®