[PATCH v4 03/10] objtool: Handle different entry size of rodata

Tiezhu Yang posted 10 patches 1 year, 2 months ago
There is a newer version of this series
[PATCH v4 03/10] objtool: Handle different entry size of rodata
Posted by Tiezhu Yang 1 year, 2 months ago
In the most cases, the entry size of rodata is 8 bytes because the
relocation type is 64 bit, but when compling with Clang on LoongArch,
there exists 32 bit relocation type, the entry size of rodata should
be 4 bytes in this case.

This is preparation for later patch on LoongArch, there is no effect
for the other archs with this patch.

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 tools/objtool/check.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 191950551352..19d1263e64e4 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -26,6 +26,10 @@
 #define EM_LOONGARCH		258
 #endif
 
+#ifndef R_LARCH_32_PCREL
+#define R_LARCH_32_PCREL	99
+#endif
+
 struct alternative {
 	struct alternative *next;
 	struct instruction *insn;
@@ -2096,6 +2100,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 	struct reloc *reloc = table;
 	struct alternative *alt;
 	unsigned long offset;
+	unsigned long rodata_entry_size;
 
 	/*
 	 * Each @reloc is a switch table relocation which points to the target
@@ -2107,8 +2112,15 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 		if (reloc != table && reloc == next_table)
 			break;
 
+		/* Handle the special cases compiled with Clang on LoongArch */
+		if (file->elf->ehdr.e_machine == EM_LOONGARCH &&
+		    reloc_type(reloc) == R_LARCH_32_PCREL)
+			rodata_entry_size = 4;
+		else
+			rodata_entry_size = 8;
+
 		/* Make sure the table entries are consecutive: */
-		if (prev_offset && reloc_offset(reloc) != prev_offset + 8)
+		if (prev_offset && reloc_offset(reloc) != prev_offset + rodata_entry_size)
 			break;
 
 		if (reloc->sym->type == STT_SECTION) {
-- 
2.42.0
Re: [PATCH v4 03/10] objtool: Handle different entry size of rodata
Posted by Josh Poimboeuf 1 year, 2 months ago
On Fri, Nov 22, 2024 at 12:49:58PM +0800, Tiezhu Yang wrote:
> @@ -2107,8 +2112,15 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
>  		if (reloc != table && reloc == next_table)
>  			break;
>  
> +		/* Handle the special cases compiled with Clang on LoongArch */

This comment is not helpful at all.  A comment is only needed if the
code is not already obvious.  In that case it should describe what is
being done and why.

> +		if (file->elf->ehdr.e_machine == EM_LOONGARCH &&
> +		    reloc_type(reloc) == R_LARCH_32_PCREL)
> +			rodata_entry_size = 4;
> +		else
> +			rodata_entry_size = 8;

Is this really loongarch-specific or is it only related to the size of
the reloc?  Can this be abstracted out to a reloc_size() function like
so?

  https://git.kernel.org/pub/scm/linux/kernel/git/jpoimboe/linux.git/tree/tools/objtool/klp-diff.c?h=objtool-diff#n834

maybe it could live in elf.h.

-- 
Josh
Re: [PATCH v4 03/10] objtool: Handle different entry size of rodata
Posted by Tiezhu Yang 1 year, 2 months ago
On 11/26/2024 03:02 PM, Josh Poimboeuf wrote:
> On Fri, Nov 22, 2024 at 12:49:58PM +0800, Tiezhu Yang wrote:
>> @@ -2107,8 +2112,15 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
>>  		if (reloc != table && reloc == next_table)
>>  			break;
>>
>> +		/* Handle the special cases compiled with Clang on LoongArch */
>
> This comment is not helpful at all.  A comment is only needed if the
> code is not already obvious.  In that case it should describe what is
> being done and why.

Will remove it.

>> +		if (file->elf->ehdr.e_machine == EM_LOONGARCH &&
>> +		    reloc_type(reloc) == R_LARCH_32_PCREL)
>> +			rodata_entry_size = 4;
>> +		else
>> +			rodata_entry_size = 8;
>
> Is this really loongarch-specific or is it only related to the size of
> the reloc?

This is related with the reloc type, but it may be wrong to only
check the reloc type to assign the value of rodata_entry_size,
becasue the value of reloc type for different archs may be same,
so it needs to check ehdr.e_machine and relocation type.

> Can this be abstracted out to a reloc_size() function like
> so?
>
>   https://git.kernel.org/pub/scm/linux/kernel/git/jpoimboe/linux.git/tree/tools/objtool/klp-diff.c?h=objtool-diff#n834
>
> maybe it could live in elf.h.

OK, if I understand your comment correctly, this should be an
arch-specific function defined in 
tools/objtool/arch/*/include/arch/elf.h, otherwise it also needs to 
check ehdr.e_machine
in tools/objtool/include/objtool/elf.h.

Thanks,
Tiezhu
Re: [PATCH v4 03/10] objtool: Handle different entry size of rodata
Posted by Josh Poimboeuf 1 year, 2 months ago
On Tue, Nov 26, 2024 at 06:59:38PM +0800, Tiezhu Yang wrote:
> > Can this be abstracted out to a reloc_size() function like
> > so?
> > 
> >   https://git.kernel.org/pub/scm/linux/kernel/git/jpoimboe/linux.git/tree/tools/objtool/klp-diff.c?h=objtool-diff#n834
> > 
> > maybe it could live in elf.h.
> 
> OK, if I understand your comment correctly, this should be an
> arch-specific function defined in tools/objtool/arch/*/include/arch/elf.h,
> otherwise it also needs to check ehdr.e_machine
> in tools/objtool/include/objtool/elf.h.

It should probably be an arch-specific function in tools/objtool/arch
somewhere.

-- 
Josh
Re: [PATCH v4 03/10] objtool: Handle different entry size of rodata
Posted by Tiezhu Yang 1 year, 2 months ago
On 11/26/2024 06:59 PM, Tiezhu Yang wrote:
> On 11/26/2024 03:02 PM, Josh Poimboeuf wrote:
>> On Fri, Nov 22, 2024 at 12:49:58PM +0800, Tiezhu Yang wrote:
>>> @@ -2107,8 +2112,15 @@ static int add_jump_table(struct objtool_file
>>> *file, struct instruction *insn,
>>>          if (reloc != table && reloc == next_table)
>>>              break;
>>>
>>> +        /* Handle the special cases compiled with Clang on LoongArch */
>>
>> This comment is not helpful at all.  A comment is only needed if the
>> code is not already obvious.  In that case it should describe what is
>> being done and why.
>
> Will remove it.
>
>>> +        if (file->elf->ehdr.e_machine == EM_LOONGARCH &&
>>> +            reloc_type(reloc) == R_LARCH_32_PCREL)
>>> +            rodata_entry_size = 4;
>>> +        else
>>> +            rodata_entry_size = 8;
>>
>> Is this really loongarch-specific or is it only related to the size of
>> the reloc?
>
> This is related with the reloc type, but it may be wrong to only
> check the reloc type to assign the value of rodata_entry_size,
> becasue the value of reloc type for different archs may be same,
> so it needs to check ehdr.e_machine and relocation type.
>
>> Can this be abstracted out to a reloc_size() function like
>> so?
>>
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/jpoimboe/linux.git/tree/tools/objtool/klp-diff.c?h=objtool-diff#n834
>>
>>
>> maybe it could live in elf.h.
>
> OK, if I understand your comment correctly, this should be an
> arch-specific function defined in
> tools/objtool/arch/*/include/arch/elf.h, otherwise it also needs to
> check ehdr.e_machine
> in tools/objtool/include/objtool/elf.h.

There are only macro definitions in
tools/objtool/arch/*/include/arch/elf.h,
so I think it is better to add reloc_size() in
tools/objtool/include/objtool/elf.h,
like this:

static inline unsigned int reloc_size(struct elf *elf, struct reloc *reloc)
{
         if (elf->ehdr.e_machine == EM_X86_64) {
                 switch (reloc_type(reloc)) {
                 case R_X86_64_32:
                 case R_X86_64_PC32:
                         return 4;
                 case R_X86_64_64:
                 case R_X86_64_PC64:
                         return 8;
                 default:
                         ERROR("unknown X86_64 reloc type");
                 }
         } else if (elf->ehdr.e_machine == EM_LOONGARCH) {
                 switch (reloc_type(reloc)) {
                 case R_LARCH_32:
                 case R_LARCH_32_PCREL:
                         return 4;
                 case R_LARCH_64:
                 case R_LARCH_64_PCREL:
                         return 8;
                 default:
                         ERROR("unknown LoongArch reloc type");
                 }
         } else {
                 return 8;
         }
}

and call it in check.c, like this:

rodata_entry_size = reloc_size(file->elf, reloc);

What do you think?

Thanks,
Tiezhu
Re: [PATCH v4 03/10] objtool: Handle different entry size of rodata
Posted by Josh Poimboeuf 1 year, 2 months ago
On Tue, Nov 26, 2024 at 09:22:22PM +0800, Tiezhu Yang wrote:
> > OK, if I understand your comment correctly, this should be an
> > arch-specific function defined in
> > tools/objtool/arch/*/include/arch/elf.h, otherwise it also needs to
> > check ehdr.e_machine
> > in tools/objtool/include/objtool/elf.h.
> 
> There are only macro definitions in
> tools/objtool/arch/*/include/arch/elf.h,
> so I think it is better to add reloc_size() in
> tools/objtool/include/objtool/elf.h,
> like this:
> 
> static inline unsigned int reloc_size(struct elf *elf, struct reloc *reloc)
> {
>         if (elf->ehdr.e_machine == EM_X86_64) {
>                 switch (reloc_type(reloc)) {
>                 case R_X86_64_32:
>                 case R_X86_64_PC32:
>                         return 4;
>                 case R_X86_64_64:
>                 case R_X86_64_PC64:
>                         return 8;
>                 default:
>                         ERROR("unknown X86_64 reloc type");
>                 }
>         } else if (elf->ehdr.e_machine == EM_LOONGARCH) {
>                 switch (reloc_type(reloc)) {
>                 case R_LARCH_32:
>                 case R_LARCH_32_PCREL:
>                         return 4;
>                 case R_LARCH_64:
>                 case R_LARCH_64_PCREL:
>                         return 8;
>                 default:
>                         ERROR("unknown LoongArch reloc type");
>                 }
>         } else {
>                 return 8;
>         }
> }

How about tools/objtool/arch/loongarch/decode.c?  Then we don't need to
check e_machine.

-- 
Josh
Re: [PATCH v4 03/10] objtool: Handle different entry size of rodata
Posted by Tiezhu Yang 1 year, 2 months ago

On 11/27/2024 08:57 AM, Josh Poimboeuf wrote:
> On Tue, Nov 26, 2024 at 09:22:22PM +0800, Tiezhu Yang wrote:
>>> OK, if I understand your comment correctly, this should be an
>>> arch-specific function defined in
>>> tools/objtool/arch/*/include/arch/elf.h, otherwise it also needs to
>>> check ehdr.e_machine
>>> in tools/objtool/include/objtool/elf.h.
>>
>> There are only macro definitions in
>> tools/objtool/arch/*/include/arch/elf.h,
>> so I think it is better to add reloc_size() in
>> tools/objtool/include/objtool/elf.h,
>> like this:
>>
>> static inline unsigned int reloc_size(struct elf *elf, struct reloc *reloc)
>> {
>>         if (elf->ehdr.e_machine == EM_X86_64) {
>>                 switch (reloc_type(reloc)) {
>>                 case R_X86_64_32:
>>                 case R_X86_64_PC32:
>>                         return 4;
>>                 case R_X86_64_64:
>>                 case R_X86_64_PC64:
>>                         return 8;
>>                 default:
>>                         ERROR("unknown X86_64 reloc type");
>>                 }
>>         } else if (elf->ehdr.e_machine == EM_LOONGARCH) {
>>                 switch (reloc_type(reloc)) {
>>                 case R_LARCH_32:
>>                 case R_LARCH_32_PCREL:
>>                         return 4;
>>                 case R_LARCH_64:
>>                 case R_LARCH_64_PCREL:
>>                         return 8;
>>                 default:
>>                         ERROR("unknown LoongArch reloc type");
>>                 }
>>         } else {
>>                 return 8;
>>         }
>> }
>
> How about tools/objtool/arch/loongarch/decode.c?  Then we don't need to
> check e_machine.

OK, makes sense, will do it.