Re: [PATCH v2 2/2] LoongArch: Skip address pairing for non-exec sections

Tiezhu Yang <[email protected]> Fri, 24 Jul 2026 14:07:36 +0800
Newsgroups dev.linux.lists.loongarch,org.kernel.vger.linux-kernel,org.kvack.linux-mm
Message-ID <[email protected]>
On 2026/7/21 下午5:06, Tiezhu Yang wrote:
> The module loader currently runs expensive address pairing logic for all
> sections blindly during relocation. For massive modules like amdgpu, this
> causes the loader to waste lots of CPU cycles analyzing non-exec sections.
> 
> Furthermore, there is an inconsistency since module_frob_arch_sections()
> already ignores non-exec sections during the counting phase.
> 
> Check the SHF_EXECINSTR flag in apply_relocate_add(). If the section is
> non-exec, skip address pairing and then jump to normal relocation. This
> eliminates redundant search loops to improve module loading efficiency.
> 
> Signed-off-by: Tiezhu Yang <[email protected]>
> ---
>   arch/loongarch/kernel/module.c | 6 ++++++
>   1 file changed, 6 insertions(+)
> 
> diff --git a/arch/loongarch/kernel/module.c b/arch/loongarch/kernel/module.c
> index 7d4d571ee55e..c84ac1546dc6 100644
> --- a/arch/loongarch/kernel/module.c
> +++ b/arch/loongarch/kernel/module.c
> @@ -484,6 +484,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
>   	Elf_Addr v;
>   	Elf_Sym *sym;
>   	Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr;
> +	Elf_Shdr *dst_sec = sechdrs + sechdrs[relsec].sh_info;
>   
>   	pr_debug("%s: Applying relocate section %u to %u\n", __func__, relsec,
>   	       sechdrs[relsec].sh_info);
> @@ -522,6 +523,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
>   
>   		v = sym->st_value + rel[i].r_addend;
>   
> +		/* Skip address pairing for non-exec sections */
> +		if (!(dst_sec->sh_flags & SHF_EXECINSTR))
> +			goto apply_normal;
> +
>   		if (type == R_LARCH_PCADD_LO12 || type == R_LARCH_GOT_PCADD_LO12) {
>   			bool found = false;
>   			unsigned int j = idx;
> @@ -562,6 +567,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
>   			idx = j; /* Record the previous j-loop end index */
>   		}
>   
> +apply_normal:
>   		switch (type) {
>   		case R_LARCH_B26:
>   			err = apply_r_larch_b26(mod, sechdrs, location,
> 

According to the LoongArch ABI specification, the following relocation
types exist exclusively in executable code sections:

R_LARCH_PCADD_LO12
R_LARCH_GOT_PCADD_LO12
R_LARCH_B26
R_LARCH_GOT_PC_HI20...R_LARCH_GOT_PC_LO12
R_LARCH_GOT_PCADD_HI20...R_LARCH_GOT_PCADD_LO12
R_LARCH_SOP_PUSH_PLT_PCREL

https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc

Thus, here is a better way:

```
diff --git a/arch/loongarch/kernel/module.c b/arch/loongarch/kernel/module.c
index 7d4d571ee55e..b1452b8adc63 100644
--- a/arch/loongarch/kernel/module.c
+++ b/arch/loongarch/kernel/module.c
@@ -484,6 +484,8 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char 
*strtab,
         Elf_Addr v;
         Elf_Sym *sym;
         Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr;
+       Elf_Shdr *dst_sec = sechdrs + sechdrs[relsec].sh_info;
+       bool is_exec = !!(dst_sec->sh_flags & SHF_EXECINSTR);

         pr_debug("%s: Applying relocate section %u to %u\n", __func__, 
relsec,
                sechdrs[relsec].sh_info);
@@ -522,6 +524,14 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const 
char *strtab,

                 v = sym->st_value + rel[i].r_addend;

+               /* Skip relocation types that exist exclusively in 
executable sections */
+               if (!is_exec) {
+                       err = handler(mod, location, v, rela_stack, 
&rela_stack_top, type);
+                       if (err)
+                               return err;
+                       continue;
+               }
+
                 if (type == R_LARCH_PCADD_LO12 || type == 
R_LARCH_GOT_PCADD_LO12) {
                         bool found = false;
                         unsigned int j = idx;
```

For the non-exec sections such as .orc_unwind_ip:

fedora@linux:~/7.2-rc3.git$ objdump -h 
drivers/gpu/drm/amd/amdgpu/amdgpu.ko | grep -A 1 .orc_unwind_ip
  32 .orc_unwind_ip 000ac104  0000000000000000  0000000000000000 
18592470  2**0
                   CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

there are 176193 relocation entries:

fedora@linux:~/7.2-rc3.git$ readelf -rW 
drivers/gpu/drm/amd/amdgpu/amdgpu.o | grep .rela.orc_unwind_ip
Relocation section '.rela.orc_unwind_ip' at offset 0x3a5321e8 contains 
176193 entries:

Using the section flag check reduces the operation to a single check for
massive data sections; otherwise, the loader would have to perform six
redundant type comparisons across the if-statement and switch-case for
every single relocation entry.

Thanks,
Tiezhu