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

objtool: Handle various symbol types of rodata

In the relocation section ".rela.rodata" of each .o file compiled with
LoongArch toolchain, there are various symbol types such as STT_NOTYPE,
STT_OBJECT, STT_FUNC in addition to the usual STT_SECTION, it needs to
use reloc symbol offset instead of reloc addend to find the destination
instruction in find_jump_table() and add_jump_table().

For the most part, an absolute relocation type is used for rodata. In the
case of STT_SECTION, reloc->sym->offset is always zero, and for the other
symbol types, reloc_addend(reloc) is always zero, thus it can use a simple
statement "reloc->sym->offset + reloc_addend(reloc)" to obtain the symbol
offset for various symbol types.

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Link: https://lore.kernel.org/r/20250211115016.26913-2-yangtiezhu@loongson.cn
Acked-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

authored by

Tiezhu Yang and committed by
Josh Poimboeuf
ab6ce22b bf71940f

+11 -5
+11 -5
tools/objtool/check.c
··· 1954 1954 unsigned int prev_offset = 0; 1955 1955 struct reloc *reloc = table; 1956 1956 struct alternative *alt; 1957 + unsigned long sym_offset; 1957 1958 1958 1959 /* 1959 1960 * Each @reloc is a switch table relocation which points to the target ··· 1972 1971 if (prev_offset && reloc_offset(reloc) != prev_offset + 8) 1973 1972 break; 1974 1973 1974 + sym_offset = reloc->sym->offset + reloc_addend(reloc); 1975 + 1975 1976 /* Detect function pointers from contiguous objects: */ 1976 - if (reloc->sym->sec == pfunc->sec && 1977 - reloc_addend(reloc) == pfunc->offset) 1977 + if (reloc->sym->sec == pfunc->sec && sym_offset == pfunc->offset) 1978 1978 break; 1979 1979 1980 1980 /* ··· 1983 1981 * which point to the end of the function. Ignore them. 1984 1982 */ 1985 1983 if (reloc->sym->sec == pfunc->sec && 1986 - reloc_addend(reloc) == pfunc->offset + pfunc->len) 1984 + sym_offset == pfunc->offset + pfunc->len) 1987 1985 goto next; 1988 1986 1989 - dest_insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc)); 1987 + dest_insn = find_insn(file, reloc->sym->sec, sym_offset); 1990 1988 if (!dest_insn) 1991 1989 break; 1992 1990 ··· 2025 2023 struct reloc *table_reloc; 2026 2024 struct instruction *dest_insn, *orig_insn = insn; 2027 2025 unsigned long table_size; 2026 + unsigned long sym_offset; 2028 2027 2029 2028 /* 2030 2029 * Backward search using the @first_jump_src links, these help avoid ··· 2049 2046 table_reloc = arch_find_switch_table(file, insn, &table_size); 2050 2047 if (!table_reloc) 2051 2048 continue; 2052 - dest_insn = find_insn(file, table_reloc->sym->sec, reloc_addend(table_reloc)); 2049 + 2050 + sym_offset = table_reloc->sym->offset + reloc_addend(table_reloc); 2051 + 2052 + dest_insn = find_insn(file, table_reloc->sym->sec, sym_offset); 2053 2053 if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func) 2054 2054 continue; 2055 2055