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 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: be2f0b1e1264 ("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/

authored by

Josh Poimboeuf and committed by
Ingo Molnar
ef753d66 2df0c02d

+37 -22
+8 -18
tools/objtool/check.c
··· 1941 1941 return reloc->sym->offset + reloc_addend(reloc); 1942 1942 } 1943 1943 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) 1946 1945 { 1947 1946 unsigned long table_size = insn_jump_table_size(insn); 1948 1947 struct symbol *pfunc = insn_func(insn)->pfunc; ··· 1961 1962 /* Check for the end of the table: */ 1962 1963 if (table_size && reloc_offset(reloc) - reloc_offset(table) >= table_size) 1963 1964 break; 1964 - if (reloc != table && reloc == next_table) 1965 + if (reloc != table && is_jump_table(reloc)) 1965 1966 break; 1966 1967 1967 1968 /* Make sure the table entries are consecutive: */ ··· 2052 2053 if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func) 2053 2054 continue; 2054 2055 2056 + set_jump_table(table_reloc); 2055 2057 orig_insn->_jump_table = table_reloc; 2056 2058 orig_insn->_jump_table_size = table_size; 2059 + 2057 2060 break; 2058 2061 } 2059 2062 } ··· 2097 2096 static int add_func_jump_tables(struct objtool_file *file, 2098 2097 struct symbol *func) 2099 2098 { 2100 - struct instruction *insn, *insn_t1 = NULL, *insn_t2; 2101 - int ret = 0; 2099 + struct instruction *insn; 2100 + int ret; 2102 2101 2103 2102 func_for_each_insn(file, func, insn) { 2104 2103 if (!insn_jump_table(insn)) 2105 2104 continue; 2106 2105 2107 - if (!insn_t1) { 2108 - insn_t1 = insn; 2109 - continue; 2110 - } 2111 2106 2112 - insn_t2 = insn; 2113 - 2114 - ret = add_jump_table(file, insn_t1, insn_jump_table(insn_t2)); 2107 + ret = add_jump_table(file, insn); 2115 2108 if (ret) 2116 2109 return ret; 2117 - 2118 - insn_t1 = insn_t2; 2119 2110 } 2120 2111 2121 - if (insn_t1) 2122 - ret = add_jump_table(file, insn_t1, NULL); 2123 - 2124 - return ret; 2112 + return 0; 2125 2113 } 2126 2114 2127 2115 /*
+3 -3
tools/objtool/elf.c
··· 583 583 { 584 584 struct reloc *reloc; 585 585 586 - for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc) 586 + for (reloc = sym->relocs; reloc; reloc = sym_next_reloc(reloc)) 587 587 set_reloc_sym(elf, reloc, reloc->sym->idx); 588 588 589 589 return 0; ··· 880 880 set_reloc_addend(elf, reloc, addend); 881 881 882 882 elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); 883 - reloc->sym_next_reloc = sym->relocs; 883 + set_sym_next_reloc(reloc, sym->relocs); 884 884 sym->relocs = reloc; 885 885 886 886 return reloc; ··· 979 979 } 980 980 981 981 elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); 982 - reloc->sym_next_reloc = sym->relocs; 982 + set_sym_next_reloc(reloc, sym->relocs); 983 983 sym->relocs = reloc; 984 984 985 985 nr_reloc++;
+26 -1
tools/objtool/include/objtool/elf.h
··· 77 77 struct elf_hash_node hash; 78 78 struct section *sec; 79 79 struct symbol *sym; 80 - struct reloc *sym_next_reloc; 80 + unsigned long _sym_next_reloc; 81 81 }; 82 82 83 83 struct elf { ··· 295 295 __set_reloc_field(reloc, r_info, info); 296 296 297 297 mark_sec_changed(elf, reloc->sec, true); 298 + } 299 + 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; 298 323 } 299 324 300 325 #define for_each_sec(file, sec) \