Le 22/06/2023 à 13:48, Peter Zijlstra a écrit : > On Thu, Jun 22, 2023 at 12:54:32PM +0200, Christophe Leroy wrote: >> 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