Re: [PATCH v2 10/14] objtool: Add support for relative switch tables
From: Christophe Leroy <hidden>
Date: 2023-06-23 15:09:37
Also in:
lkml
Subsystem:
objtool, the rest · Maintainers:
Josh Poimboeuf, Peter Zijlstra, Linus Torvalds
Le 22/06/2023 à 13:48, Peter Zijlstra a écrit :
On Thu, Jun 22, 2023 at 12:54:32PM +0200, Christophe Leroy wrote:quoted
On powerpc, switch tables are relative, than means the address of the table is added to the value of the entry in order to get the pointed address: (r10 is the table address, r4 the index in the table) lis r10,0 <== Load r10 with upper part of .rodata address R_PPC_ADDR16_HA .rodata addi r10,r10,0 <== Add lower part of .rodata address R_PPC_ADDR16_LO .rodata lwzx r8,r10,r4 <== Read table entry at r10 + r4 into r8 add r10,r8,r10 <== Add table address to read value mtctr r10 <== Save calculated address in CTR bctr <== Branch to address in CTR But for c_jump_tables it is not the case, they contain the pointed address directly: lis r28,0 <== Load r28 with upper .rodata..c_jump_table R_PPC_ADDR16_HA .rodata..c_jump_table addi r28,r28,0 <== Add lower part of .rodata..c_jump_table R_PPC_ADDR16_LO .rodata..c_jump_table lwzx r10,r28,r10 <== Read table entry at r10 + r28 into r10 mtctr r10 <== Save read value in CTR bctr <== Branch to address in CTR Add support to objtool for relative tables, with a flag in order to tell table by table if that table uses relative or absolute addressing. And use correct size for 'long' instead of hard coding a size of '8'.Again, see tip/objtool/core... This one is going to be a little hard. It would be very good if you can avoid growing struct reloc; Josh went through a ton of effort to shrink it. Would it work to use reloc->sym->is_rel_jumptable ? That still has a few spare bits in it's bitfield.
I noticed that the relocation types are different, so the flag is indeed not needed. I have now done the following, will it work for x86 ?
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index ae4a1608d97e..05d789e6d3b6 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c@@ -1988,7 +1988,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, struct symbol *pfunc = insn_func(insn)->pfunc; struct reloc *table = insn_jump_table(insn); struct instruction *dest_insn; - unsigned int prev_offset = 0; + unsigned int offset, prev_offset = 0; struct reloc *reloc = table; struct alternative *alt;
@@ -2003,7 +2003,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, break; /* Make sure the table entries are consecutive: */ - if (prev_offset && reloc_offset(reloc) != prev_offset + 8) + if (prev_offset && reloc_offset(reloc) != prev_offset + elf_addr_size(file->elf)) break; /* Detect function pointers from contiguous objects: */
@@ -2011,7 +2011,12 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, reloc_addend(reloc) == pfunc->offset) break; - dest_insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc)); + if (reloc_type(reloc) == R_ABS32 || reloc_type(reloc) == R_ABS64) + offset = reloc_addend(reloc); + else + offset = reloc_addend(reloc) + reloc_offset(table) - reloc_offset(reloc); + + dest_insn = find_insn(file, reloc->sym->sec, offset); if (!dest_insn) break; Christophe