LoongArch: Add support for relocating the kernel with RELR relocation
RELR as a relocation packing format for relative relocations for reducing the size of relative relocation records. In a position independent executable there are often many relative relocation records, and our vmlinux is a PIE. The LLD linker (since 17.0.0) and the BFD linker (since 2.43) supports packing the relocations in the RELR format for LoongArch, with the flag -z pack-relative-relocs. Commits5cf896fb6b
("arm64: Add support for relocating the kernel with RELR relocations") andccb2d173b9
("Makefile: use -z pack-relative-relocs") have already added the framework to use RELR. We just need to wire it up and process the RELR relocation records in relocate_relative() in addition to the RELA relocation records. A ".p2align 3" directive is added to la_abs macro or the BFD linker cannot pack the relocation records against the .la_abs section (the ". = ALIGN(8);" directive in vmlinux.lds.S is too late in the linking process). With defconfig and CONFIG_RELR vmlinux.efi is 2.1 MiB (6%) smaller, and vmlinuz.efi (using gzip compression) is 384 KiB (2.8%) smaller. Link: https://groups.google.com/d/topic/generic-abi/bX460iggiKg Link: https://reviews.llvm.org/D138135#4531389 Link: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=d89ecf33ab6d Signed-off-by: Xi Ruoyao <xry111@xry111.site> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
parent
0ad158e4ef
commit
e05d4cd9b8
@ -610,6 +610,7 @@ config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
|
||||
|
||||
config RELOCATABLE
|
||||
bool "Relocatable kernel"
|
||||
select ARCH_HAS_RELR
|
||||
help
|
||||
This builds the kernel as a Position Independent Executable (PIE),
|
||||
which retains all relocation metadata required, so as to relocate
|
||||
|
@ -609,6 +609,7 @@
|
||||
lu32i.d \reg, 0
|
||||
lu52i.d \reg, \reg, 0
|
||||
.pushsection ".la_abs", "aw", %progbits
|
||||
.p2align 3
|
||||
.dword 766b
|
||||
.dword \sym
|
||||
.popsection
|
||||
|
@ -34,6 +34,11 @@ extern long __la_abs_end;
|
||||
extern long __rela_dyn_begin;
|
||||
extern long __rela_dyn_end;
|
||||
|
||||
#ifdef CONFIG_RELR
|
||||
extern long __relr_dyn_begin;
|
||||
extern long __relr_dyn_end;
|
||||
#endif
|
||||
|
||||
extern unsigned long __init relocate_kernel(void);
|
||||
|
||||
#endif
|
||||
|
@ -38,6 +38,24 @@ static inline void __init relocate_relative(void)
|
||||
relocated_addr = (Elf64_Addr)RELOCATED(relocated_addr);
|
||||
*(Elf64_Addr *)RELOCATED(addr) = relocated_addr;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RELR
|
||||
u64 *addr = NULL;
|
||||
u64 *relr = (u64 *)&__relr_dyn_begin;
|
||||
u64 *relr_end = (u64 *)&__relr_dyn_end;
|
||||
|
||||
for ( ; relr < relr_end; relr++) {
|
||||
if ((*relr & 1) == 0) {
|
||||
addr = (u64 *)(*relr + reloc_offset);
|
||||
*addr++ += reloc_offset;
|
||||
} else {
|
||||
for (u64 *p = addr, r = *relr >> 1; r; p++, r >>= 1)
|
||||
if (r & 1)
|
||||
*p += reloc_offset;
|
||||
addr += 63;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void __init relocate_absolute(long random_offset)
|
||||
|
@ -113,6 +113,14 @@ SECTIONS
|
||||
__rela_dyn_end = .;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RELR
|
||||
.relr.dyn : ALIGN(8) {
|
||||
__relr_dyn_begin = .;
|
||||
*(.relr.dyn)
|
||||
__relr_dyn_end = .;
|
||||
}
|
||||
#endif
|
||||
|
||||
.data.rel : { *(.data.rel*) }
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
|
Loading…
Reference in New Issue
Block a user