[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <9d14c8fa-d61d-bd12-efd7-5a17f4f8cb35@loongson.cn>
Date: Wed, 11 Dec 2024 11:16:33 +0800
From: Tiezhu Yang <yangtiezhu@...ngson.cn>
To: Josh Poimboeuf <jpoimboe@...nel.org>
Cc: Huacai Chen <chenhuacai@...nel.org>, Peter Zijlstra
<peterz@...radead.org>, loongarch@...ts.linux.dev,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH v5 03/10] objtool: Handle PC relative relocation type
On 12/10/2024 04:35 AM, Josh Poimboeuf wrote:
> On Sat, Dec 07, 2024 at 09:59:08AM +0800, Tiezhu Yang wrote:
>> +unsigned long arch_adjust_offset(struct reloc *reloc, struct reloc *table)
>> +{
>> + switch (reloc_type(reloc)) {
>> + case R_LARCH_32_PCREL:
>> + case R_LARCH_64_PCREL:
>> + if (reloc->sym->type == STT_SECTION)
>> + return reloc->sym->offset + reloc_addend(reloc) -
>> + (reloc_offset(reloc) - reloc_offset(table));
>
> How does this even work? i.e., why does the reloc offset (basically the
> jump table index) have anything to do with calculating the location of
> the instruction it's referencing?
Let me try to explain it, this is related with the relocation type.
In short, the jump table index is not used to calculate the location of
the destination instruction for absolute relocation types, but it should
be used for PC relative relocation types.
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.
When compiling on LoongArch, there are some PC relative relocation types
for rodata, it needs to calculate the symbol offset with "S + A - PC" in
this case according to the spec of "ELF for the LoongArch Architecture",
the "PC" is the index of each jump table which is equal with the value
of reloc_offset(reloc) - reloc_offset(table).
I will add the above description to the commit message to make it clear.
>
>> + else
>> + return reloc->sym->offset;
>
> This also seems odd. Why is the addend being ignored? Shouldn't it
> point to the instruction's offset?
Sorry for that, I forgot to calculate the table size if the symbol type
is local label generated by GCC on LoongArch, after doing that, no need
to check the symbol type, just check whether the reloc types are PC
relative, the final code should be something like this:
unsigned long arch_adjust_offset(struct reloc *reloc, struct reloc *table)
{
switch (reloc_type(reloc)) {
case R_LARCH_32_PCREL:
case R_LARCH_64_PCREL:
return reloc->sym->offset + reloc_addend(reloc) -
(reloc_offset(reloc) - reloc_offset(table));
default:
return reloc->sym->offset + reloc_addend(reloc);
}
}
Thanks,
Tiezhu
Powered by blists - more mailing lists