Skip to content

Commit ef753d6

Browse files
jpoimboeIngo Molnar
authored andcommitted
objtool: Fix detection of consecutive jump tables on Clang 20
The jump table detection code assumes jump tables are in the same order as their corresponding indirect branches. That's apparently not always true with Clang 20. Fix that by changing how multiple jump tables are detected. In the first detection pass, mark the beginning of each jump table so the second pass can tell where one ends and the next one begins. Fixes the following warnings: vmlinux.o: warning: objtool: SiS_GetCRT2Ptr+0x1ad: stack state mismatch: cfa1=4+8 cfa2=5+16 sound/core/seq/snd-seq.o: warning: objtool: cc_ev_to_ump_midi2+0x589: return with modified stack frame Fixes: be2f0b1 ("objtool: Get rid of reloc->jump_table_start") Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: Nathan Chancellor <nathan@kernel.org> Cc: Nick Desaulniers <ndesaulniers@google.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: https://lore.kernel.org/r/141752fff614eab962dba6bdfaa54aa67ff03bba.1742852846.git.jpoimboe@kernel.org Closes: https://lore.kernel.org/oe-kbuild-all/202503171547.LlCTJLQL-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202503200535.J3hAvcjw-lkp@intel.com/
1 parent 2df0c02 commit ef753d6

File tree

3 files changed

+37
-22
lines changed

3 files changed

+37
-22
lines changed

tools/objtool/check.c

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,8 +1941,7 @@ __weak unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct relo
19411941
return reloc->sym->offset + reloc_addend(reloc);
19421942
}
19431943

1944-
static int add_jump_table(struct objtool_file *file, struct instruction *insn,
1945-
struct reloc *next_table)
1944+
static int add_jump_table(struct objtool_file *file, struct instruction *insn)
19461945
{
19471946
unsigned long table_size = insn_jump_table_size(insn);
19481947
struct symbol *pfunc = insn_func(insn)->pfunc;
@@ -1962,7 +1961,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
19621961
/* Check for the end of the table: */
19631962
if (table_size && reloc_offset(reloc) - reloc_offset(table) >= table_size)
19641963
break;
1965-
if (reloc != table && reloc == next_table)
1964+
if (reloc != table && is_jump_table(reloc))
19661965
break;
19671966

19681967
/* Make sure the table entries are consecutive: */
@@ -2053,8 +2052,10 @@ static void find_jump_table(struct objtool_file *file, struct symbol *func,
20532052
if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func)
20542053
continue;
20552054

2055+
set_jump_table(table_reloc);
20562056
orig_insn->_jump_table = table_reloc;
20572057
orig_insn->_jump_table_size = table_size;
2058+
20582059
break;
20592060
}
20602061
}
@@ -2096,31 +2097,20 @@ static void mark_func_jump_tables(struct objtool_file *file,
20962097
static int add_func_jump_tables(struct objtool_file *file,
20972098
struct symbol *func)
20982099
{
2099-
struct instruction *insn, *insn_t1 = NULL, *insn_t2;
2100-
int ret = 0;
2100+
struct instruction *insn;
2101+
int ret;
21012102

21022103
func_for_each_insn(file, func, insn) {
21032104
if (!insn_jump_table(insn))
21042105
continue;
21052106

2106-
if (!insn_t1) {
2107-
insn_t1 = insn;
2108-
continue;
2109-
}
2110-
2111-
insn_t2 = insn;
21122107

2113-
ret = add_jump_table(file, insn_t1, insn_jump_table(insn_t2));
2108+
ret = add_jump_table(file, insn);
21142109
if (ret)
21152110
return ret;
2116-
2117-
insn_t1 = insn_t2;
21182111
}
21192112

2120-
if (insn_t1)
2121-
ret = add_jump_table(file, insn_t1, NULL);
2122-
2123-
return ret;
2113+
return 0;
21242114
}
21252115

21262116
/*

tools/objtool/elf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
583583
{
584584
struct reloc *reloc;
585585

586-
for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc)
586+
for (reloc = sym->relocs; reloc; reloc = sym_next_reloc(reloc))
587587
set_reloc_sym(elf, reloc, reloc->sym->idx);
588588

589589
return 0;
@@ -880,7 +880,7 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
880880
set_reloc_addend(elf, reloc, addend);
881881

882882
elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
883-
reloc->sym_next_reloc = sym->relocs;
883+
set_sym_next_reloc(reloc, sym->relocs);
884884
sym->relocs = reloc;
885885

886886
return reloc;
@@ -979,7 +979,7 @@ static int read_relocs(struct elf *elf)
979979
}
980980

981981
elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
982-
reloc->sym_next_reloc = sym->relocs;
982+
set_sym_next_reloc(reloc, sym->relocs);
983983
sym->relocs = reloc;
984984

985985
nr_reloc++;

tools/objtool/include/objtool/elf.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ struct reloc {
7777
struct elf_hash_node hash;
7878
struct section *sec;
7979
struct symbol *sym;
80-
struct reloc *sym_next_reloc;
80+
unsigned long _sym_next_reloc;
8181
};
8282

8383
struct elf {
@@ -297,6 +297,31 @@ static inline void set_reloc_type(struct elf *elf, struct reloc *reloc, unsigned
297297
mark_sec_changed(elf, reloc->sec, true);
298298
}
299299

300+
#define RELOC_JUMP_TABLE_BIT 1UL
301+
302+
/* Does reloc mark the beginning of a jump table? */
303+
static inline bool is_jump_table(struct reloc *reloc)
304+
{
305+
return reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT;
306+
}
307+
308+
static inline void set_jump_table(struct reloc *reloc)
309+
{
310+
reloc->_sym_next_reloc |= RELOC_JUMP_TABLE_BIT;
311+
}
312+
313+
static inline struct reloc *sym_next_reloc(struct reloc *reloc)
314+
{
315+
return (struct reloc *)(reloc->_sym_next_reloc & ~RELOC_JUMP_TABLE_BIT);
316+
}
317+
318+
static inline void set_sym_next_reloc(struct reloc *reloc, struct reloc *next)
319+
{
320+
unsigned long bit = reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT;
321+
322+
reloc->_sym_next_reloc = (unsigned long)next | bit;
323+
}
324+
300325
#define for_each_sec(file, sec) \
301326
list_for_each_entry(sec, &file->elf->sections, list)
302327

0 commit comments

Comments
 (0)