Skip to content

Commit 08cc55b

Browse files
Ard Biesheuvelwildea01
authored andcommitted
arm64: relocatable: suppress R_AARCH64_ABS64 relocations in vmlinux
The linker routines that we rely on to produce a relocatable PIE binary treat it as a shared ELF object in some ways, i.e., it emits symbol based R_AARCH64_ABS64 relocations into the final binary since doing so would be appropriate when linking a shared library that is subject to symbol preemption. (This means that an executable can override certain symbols that are exported by a shared library it is linked with, and that the shared library *must* update all its internal references as well, and point them to the version provided by the executable.) Symbol preemption does not occur for OS hosted PIE executables, let alone for vmlinux, and so we would prefer to get rid of these symbol based relocations. This would allow us to simplify the relocation routines, and to strip the .dynsym, .dynstr and .hash sections from the binary. (Note that these are tiny, and are placed in the .init segment, but they clutter up the vmlinux binary.) Note that these R_AARCH64_ABS64 relocations are only emitted for absolute references to symbols defined in the linker script, all other relocatable quantities are covered by anonymous R_AARCH64_RELATIVE relocations that simply list the offsets to all 64-bit values in the binary that need to be fixed up based on the offset between the link time and run time addresses. Fortunately, GNU ld has a -Bsymbolic option, which is intended for shared libraries to allow them to ignore symbol preemption, and unconditionally bind all internal symbol references to its own definitions. So set it for our PIE binary as well, and get rid of the asoociated sections and the relocation code that processes them. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> [will: fixed conflict with __dynsym_offset linker script entry] Signed-off-by: Will Deacon <will.deacon@arm.com>
1 parent d6732fc commit 08cc55b

3 files changed

Lines changed: 5 additions & 29 deletions

File tree

arch/arm64/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
1515
GZFLAGS :=-9
1616

1717
ifneq ($(CONFIG_RELOCATABLE),)
18-
LDFLAGS_vmlinux += -pie
18+
LDFLAGS_vmlinux += -pie -Bsymbolic
1919
endif
2020

2121
KBUILD_DEFCONFIG := defconfig

arch/arm64/kernel/head.S

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -781,40 +781,25 @@ __primary_switch:
781781
* Iterate over each entry in the relocation table, and apply the
782782
* relocations in place.
783783
*/
784-
ldr w8, =__dynsym_offset // offset to symbol table
785784
ldr w9, =__rela_offset // offset to reloc table
786785
ldr w10, =__rela_size // size of reloc table
787786

788787
mov_q x11, KIMAGE_VADDR // default virtual offset
789788
add x11, x11, x23 // actual virtual offset
790-
add x8, x8, x11 // __va(.dynsym)
791789
add x9, x9, x11 // __va(.rela)
792790
add x10, x9, x10 // __va(.rela) + sizeof(.rela)
793791

794792
0: cmp x9, x10
795-
b.hs 2f
793+
b.hs 1f
796794
ldp x11, x12, [x9], #24
797795
ldr x13, [x9, #-8]
798796
cmp w12, #R_AARCH64_RELATIVE
799-
b.ne 1f
797+
b.ne 0b
800798
add x13, x13, x23 // relocate
801799
str x13, [x11, x23]
802800
b 0b
803801

804-
1: cmp w12, #R_AARCH64_ABS64
805-
b.ne 0b
806-
add x12, x12, x12, lsl #1 // symtab offset: 24x top word
807-
add x12, x8, x12, lsr #(32 - 3) // ... shifted into bottom word
808-
ldrsh w14, [x12, #6] // Elf64_Sym::st_shndx
809-
ldr x15, [x12, #8] // Elf64_Sym::st_value
810-
cmp w14, #-0xf // SHN_ABS (0xfff1) ?
811-
add x14, x15, x23 // relocate
812-
csel x15, x14, x15, ne
813-
add x15, x13, x15
814-
str x15, [x11, x23]
815-
b 0b
816-
817-
2:
802+
1:
818803
#endif
819804
ldr x8, =__primary_switched
820805
br x8

arch/arm64/kernel/vmlinux.lds.S

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ SECTIONS
103103
*(.discard)
104104
*(.discard.*)
105105
*(.interp .dynamic)
106+
*(.dynsym .dynstr .hash)
106107
}
107108

108109
. = KIMAGE_VADDR + TEXT_OFFSET;
@@ -174,19 +175,9 @@ SECTIONS
174175
.rela : ALIGN(8) {
175176
*(.rela .rela*)
176177
}
177-
.dynsym : ALIGN(8) {
178-
*(.dynsym)
179-
}
180-
.dynstr : {
181-
*(.dynstr)
182-
}
183-
.hash : {
184-
*(.hash)
185-
}
186178

187179
__rela_offset = ABSOLUTE(ADDR(.rela) - KIMAGE_VADDR);
188180
__rela_size = SIZEOF(.rela);
189-
__dynsym_offset = ABSOLUTE(ADDR(.dynsym) - KIMAGE_VADDR);
190181

191182
. = ALIGN(SEGMENT_ALIGN);
192183
__init_end = .;

0 commit comments

Comments
 (0)