Skip to content

Commit c4b93b0

Browse files
seehearfeeljpoimboe
authored andcommitted
objtool: Handle PC relative relocation type
For the most part, an absolute relocation type is used for rodata. In the case of STT_SECTION, reloc->sym->offset is always zero, 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. When compiling on LoongArch, there exist PC relative relocation types for rodata, it needs to calculate the symbol offset with "S + A - PC" according to the spec of "ELF for the LoongArch Architecture". If there is only one jump table in the rodata, the "PC" is the entry address which is equal with the value of reloc_offset(reloc), at this time, reloc_offset(table) is 0. If there are many jump tables in the rodata, the "PC" is the offset of the jump table's base address which is equal with the value of reloc_offset(reloc) - reloc_offset(table). So for LoongArch, if the relocation type is PC relative, it can use a statement "reloc_offset(reloc) - reloc_offset(table)" to get the "PC" value when calculating the symbol offset with "S + A - PC" for one or many jump tables in the rodata. Add an arch-specific function arch_jump_table_sym_offset() to assign the symbol offset, for the most part that is an absolute relocation, the default value is "reloc->sym->offset + reloc_addend(reloc)" in the weak definition, it can be overridden by each architecture that has different requirements. Link: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc Signed-off-by: Tiezhu Yang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Acked-by: Huacai Chen <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]>
1 parent 091bf31 commit c4b93b0

File tree

4 files changed

+27
-5
lines changed

4 files changed

+27
-5
lines changed

tools/objtool/arch/loongarch/decode.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
#include <asm/inst.h>
66
#include <asm/orc_types.h>
77
#include <linux/objtool_types.h>
8-
9-
#ifndef EM_LOONGARCH
10-
#define EM_LOONGARCH 258
11-
#endif
8+
#include <arch/elf.h>
129

1310
int arch_ftrace_match(char *name)
1411
{
@@ -374,3 +371,15 @@ unsigned int arch_reloc_size(struct reloc *reloc)
374371
return 8;
375372
}
376373
}
374+
375+
unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table)
376+
{
377+
switch (reloc_type(reloc)) {
378+
case R_LARCH_32_PCREL:
379+
case R_LARCH_64_PCREL:
380+
return reloc->sym->offset + reloc_addend(reloc) -
381+
(reloc_offset(reloc) - reloc_offset(table));
382+
default:
383+
return reloc->sym->offset + reloc_addend(reloc);
384+
}
385+
}

tools/objtool/arch/loongarch/include/arch/elf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
#ifndef R_LARCH_32_PCREL
1919
#define R_LARCH_32_PCREL 99
2020
#endif
21+
#ifndef R_LARCH_64_PCREL
22+
#define R_LARCH_64_PCREL 109
23+
#endif
24+
25+
#ifndef EM_LOONGARCH
26+
#define EM_LOONGARCH 258
27+
#endif
2128

2229
#define R_NONE R_LARCH_NONE
2330
#define R_ABS32 R_LARCH_32

tools/objtool/check.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,11 @@ static int add_special_section_alts(struct objtool_file *file)
19441944
return ret;
19451945
}
19461946

1947+
__weak unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table)
1948+
{
1949+
return reloc->sym->offset + reloc_addend(reloc);
1950+
}
1951+
19471952
static int add_jump_table(struct objtool_file *file, struct instruction *insn,
19481953
struct reloc *next_table)
19491954
{
@@ -1972,7 +1977,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
19721977
if (prev_offset && reloc_offset(reloc) != prev_offset + arch_reloc_size(reloc))
19731978
break;
19741979

1975-
sym_offset = reloc->sym->offset + reloc_addend(reloc);
1980+
sym_offset = arch_jump_table_sym_offset(reloc, table);
19761981

19771982
/* Detect function pointers from contiguous objects: */
19781983
if (reloc->sym->sec == pfunc->sec && sym_offset == pfunc->offset)

tools/objtool/include/objtool/arch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,6 @@ int arch_rewrite_retpolines(struct objtool_file *file);
9898
bool arch_pc_relative_reloc(struct reloc *reloc);
9999

100100
unsigned int arch_reloc_size(struct reloc *reloc);
101+
unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table);
101102

102103
#endif /* _ARCH_H */

0 commit comments

Comments
 (0)