mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 07:31:28 +00:00
[ELF] Add -z rel and -z rela
LLD supports both REL and RELA for static relocations, but emits either of REL and RELA for dynamic relocations. The relocation entry format is specified by each psABI. musl ld.so supports both REL and RELA. For such ld.so implementations, REL (.rel.dyn .rel.plt) has size benefits even if the psABI chooses RELA: sizeof(Elf64_Rel)=16 < sizeof(Elf64_Rela)=24. * COPY, GLOB_DAT and J[U]MP_SLOT always have 0 addend. A ld.so implementation does not need to read the implicit addend. REL is strictly better. * A RELATIVE has a non-zero addend. Such relocations can be packed compactly with the RELR relocation entry format, which is out of scope of this patch. * For other dynamic relocation types (e.g. symbolic relocation R_X86_64_64), a ld.so implementation needs to read the implicit addend. REL may have minor performance impact, because reading implicit addends forces random access reads instead of being able to blast out a bunch of writes while chasing the relocation array. This patch adds -z rel and -z rela to change the relocation entry format for dynamic relocations. I have tested that a -z rel produced x86-64 executable works with musl ld.so -z rela may be useful for debugging purposes on processors whose psABIs specify REL as the canonical format: addends can be easily read by a tool. Reviewed By: grimar, mcgrathr Differential Revision: https://reviews.llvm.org/D80496
This commit is contained in:
parent
2d7fdab8e3
commit
881c5eef98
@ -422,11 +422,11 @@ static bool isKnownZFlag(StringRef s) {
|
||||
s == "nodelete" || s == "nodlopen" || s == "noexecstack" ||
|
||||
s == "nognustack" || s == "nokeep-text-section-prefix" ||
|
||||
s == "norelro" || s == "noseparate-code" || s == "notext" ||
|
||||
s == "now" || s == "origin" || s == "pac-plt" || s == "relro" ||
|
||||
s == "retpolineplt" || s == "rodynamic" || s == "shstk" ||
|
||||
s == "text" || s == "undefs" || s == "wxneeded" ||
|
||||
s.startswith("common-page-size=") || s.startswith("max-page-size=") ||
|
||||
s.startswith("stack-size=");
|
||||
s == "now" || s == "origin" || s == "pac-plt" || s == "rel" ||
|
||||
s == "rela" || s == "relro" || s == "retpolineplt" ||
|
||||
s == "rodynamic" || s == "shstk" || s == "text" || s == "undefs" ||
|
||||
s == "wxneeded" || s.startswith("common-page-size=") ||
|
||||
s.startswith("max-page-size=") || s.startswith("stack-size=");
|
||||
}
|
||||
|
||||
// Report an error for an unknown -z option.
|
||||
@ -842,6 +842,22 @@ static std::vector<StringRef> getSymbolOrderingFile(MemoryBufferRef mb) {
|
||||
return names.takeVector();
|
||||
}
|
||||
|
||||
static bool getIsRela(opt::InputArgList &args) {
|
||||
// If -z rel or -z rela is specified, use the last option.
|
||||
for (auto *arg : args.filtered_reverse(OPT_z)) {
|
||||
StringRef s(arg->getValue());
|
||||
if (s == "rel")
|
||||
return false;
|
||||
if (s == "rela")
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise use the psABI defined relocation entry format.
|
||||
uint16_t m = config->emachine;
|
||||
return m == EM_AARCH64 || m == EM_AMDGPU || m == EM_HEXAGON || m == EM_PPC ||
|
||||
m == EM_PPC64 || m == EM_RISCV || m == EM_X86_64;
|
||||
}
|
||||
|
||||
static void parseClangOption(StringRef opt, const Twine &msg) {
|
||||
std::string err;
|
||||
raw_string_ostream os(err);
|
||||
@ -1204,20 +1220,19 @@ static void setConfigs(opt::InputArgList &args) {
|
||||
|
||||
// ELF defines two different ways to store relocation addends as shown below:
|
||||
//
|
||||
// Rel: Addends are stored to the location where relocations are applied.
|
||||
// Rel: Addends are stored to the location where relocations are applied. It
|
||||
// cannot pack the full range of addend values for all relocation types, but
|
||||
// this only affects relocation types that we don't support emitting as
|
||||
// dynamic relocations (see getDynRel).
|
||||
// Rela: Addends are stored as part of relocation entry.
|
||||
//
|
||||
// In other words, Rela makes it easy to read addends at the price of extra
|
||||
// 4 or 8 byte for each relocation entry. We don't know why ELF defined two
|
||||
// different mechanisms in the first place, but this is how the spec is
|
||||
// defined.
|
||||
// 4 or 8 byte for each relocation entry.
|
||||
//
|
||||
// You cannot choose which one, Rel or Rela, you want to use. Instead each
|
||||
// ABI defines which one you need to use. The following expression expresses
|
||||
// that.
|
||||
config->isRela = m == EM_AARCH64 || m == EM_AMDGPU || m == EM_HEXAGON ||
|
||||
m == EM_PPC || m == EM_PPC64 || m == EM_RISCV ||
|
||||
m == EM_X86_64;
|
||||
// We pick the format for dynamic relocations according to the psABI for each
|
||||
// processor, but a contrary choice can be made if the dynamic loader
|
||||
// supports.
|
||||
config->isRela = getIsRela(args);
|
||||
|
||||
// If the output uses REL relocations we must store the dynamic relocation
|
||||
// addends to the output sections. We also store addends for RELA relocations
|
||||
|
@ -720,6 +720,12 @@ processing.
|
||||
.It Cm pac-plt
|
||||
AArch64 only, use pointer authentication in PLT.
|
||||
.Pp
|
||||
.It Cm rel
|
||||
Use REL format for dynamic relocations.
|
||||
.Pp
|
||||
.It Cm rela
|
||||
Use RELA format for dynamic relocations.
|
||||
.Pp
|
||||
.It Cm retpolineplt
|
||||
Emit retpoline format PLT entries as a mitigation for CVE-2017-5715.
|
||||
.Pp
|
||||
|
63
lld/test/ELF/i386-zrel-zrela.s
Normal file
63
lld/test/ELF/i386-zrel-zrela.s
Normal file
@ -0,0 +1,63 @@
|
||||
# REQUIRES: x86
|
||||
## The i386 psABI uses Elf64_Rela relocation entries. We produce
|
||||
## Elf32_Rel dynamic relocations by default, but can use Elf32_Rela with -z rela.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o
|
||||
# RUN: ld.lld -shared %t.o -o %t.so
|
||||
# RUN: llvm-readobj -d -r -x .data %t.so | FileCheck --check-prefix=REL %s
|
||||
# RUN: ld.lld -shared -z rel %t.o -o %t1.so
|
||||
# RUN: llvm-readobj -d -r -x .data %t1.so | FileCheck --check-prefix=REL %s
|
||||
|
||||
# REL: REL {{.*}}
|
||||
# REL-NEXT: RELSZ 32 (bytes)
|
||||
# REL-NEXT: RELENT 8 (bytes)
|
||||
# REL-NEXT: RELCOUNT 1
|
||||
# REL-NEXT: JMPREL {{.*}}
|
||||
# REL-NEXT: PLTRELSZ 8 (bytes)
|
||||
# REL-NEXT: PLTGOT {{.*}}
|
||||
# REL-NEXT: PLTREL REL{{$}}
|
||||
# REL: .rel.dyn {
|
||||
# REL-NEXT: R_386_RELATIVE - 0x0
|
||||
# REL-NEXT: R_386_GLOB_DAT func 0x0
|
||||
# REL-NEXT: R_386_TLS_TPOFF tls 0x0
|
||||
# REL-NEXT: R_386_32 _start 0x0
|
||||
# REL-NEXT: }
|
||||
# REL-NEXT: .rel.plt {
|
||||
# REL-NEXT: R_386_JUMP_SLOT func 0x0
|
||||
# REL-NEXT: }
|
||||
|
||||
# REL: Hex dump of section '.data':
|
||||
# REL-NEXT: 0x000042cc cc420000 2a000000
|
||||
|
||||
# RUN: ld.lld -shared -z rel -z rela %t.o -o %t2.so
|
||||
# RUN: llvm-readobj -d -r %t2.so | FileCheck --check-prefix=RELA %s
|
||||
|
||||
# RELA: RELA {{.*}}
|
||||
# RELA-NEXT: RELASZ 48 (bytes)
|
||||
# RELA-NEXT: RELAENT 12 (bytes)
|
||||
# RELA-NEXT: RELACOUNT 1
|
||||
# RELA-NEXT: JMPREL {{.*}}
|
||||
# RELA-NEXT: PLTRELSZ 12 (bytes)
|
||||
# RELA-NEXT: PLTGOT {{.*}}
|
||||
# RELA-NEXT: PLTREL RELA
|
||||
# RELA: .rela.dyn {
|
||||
# RELA-NEXT: R_386_RELATIVE - 0x42EC
|
||||
# RELA-NEXT: R_386_GLOB_DAT func 0x0
|
||||
# RELA-NEXT: R_386_TLS_TPOFF tls 0x2A
|
||||
# RELA-NEXT: R_386_32 _start 0x2A
|
||||
# RELA-NEXT: }
|
||||
# RELA-NEXT: .rela.plt {
|
||||
# RELA-NEXT: R_386_JUMP_SLOT func 0x0
|
||||
# RELA-NEXT: }
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
call func@PLT
|
||||
movl func@GOT(%eax), %eax
|
||||
|
||||
.section .text1,"awx"
|
||||
movl %gs:tls@NTPOFF+42, %eax
|
||||
|
||||
.data
|
||||
.long .data
|
||||
.long _start+42
|
58
lld/test/ELF/x86-64-zrel-zrela.s
Normal file
58
lld/test/ELF/x86-64-zrel-zrela.s
Normal file
@ -0,0 +1,58 @@
|
||||
# REQUIRES: x86
|
||||
## The x86-64 psABI uses Elf64_Rela relocation entries. We produce
|
||||
## Elf64_Rel dynamic relocations by default, but can use Elf64_Rel with -z rel.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
|
||||
# RUN: ld.lld -shared %t.o -o %t.so
|
||||
# RUN: llvm-readobj -d -r %t.so | FileCheck --check-prefix=RELA %s
|
||||
# RUN: ld.lld -shared -z rela %t.o -o %t1.so
|
||||
# RUN: llvm-readobj -d -r %t1.so | FileCheck --check-prefix=RELA %s
|
||||
|
||||
# RELA: RELA {{.*}}
|
||||
# RELA-NEXT: RELASZ 72 (bytes)
|
||||
# RELA-NEXT: RELAENT 24 (bytes)
|
||||
# RELA-NEXT: RELACOUNT 1
|
||||
# RELA-NEXT: JMPREL {{.*}}
|
||||
# RELA-NEXT: PLTRELSZ 24 (bytes)
|
||||
# RELA-NEXT: PLTGOT {{.*}}
|
||||
# RELA-NEXT: PLTREL RELA
|
||||
# RELA: .rela.dyn {
|
||||
# RELA-NEXT: R_X86_64_RELATIVE - 0x3428
|
||||
# RELA-NEXT: R_X86_64_GLOB_DAT func 0x0
|
||||
# RELA-NEXT: R_X86_64_64 _start 0x2A
|
||||
# RELA-NEXT: }
|
||||
# RELA-NEXT: .rela.plt {
|
||||
# RELA-NEXT: R_X86_64_JUMP_SLOT func 0x0
|
||||
# RELA-NEXT: }
|
||||
|
||||
# RUN: ld.lld -shared -z rela -z rel %t.o -o %t2.so
|
||||
# RUN: llvm-readobj -d -r -x .data %t2.so | FileCheck --check-prefix=REL %s
|
||||
|
||||
# REL: REL {{.*}}
|
||||
# REL-NEXT: RELSZ 48 (bytes)
|
||||
# REL-NEXT: RELENT 16 (bytes)
|
||||
# REL-NEXT: RELCOUNT 1
|
||||
# REL-NEXT: JMPREL {{.*}}
|
||||
# REL-NEXT: PLTRELSZ 16 (bytes)
|
||||
# REL-NEXT: PLTGOT {{.*}}
|
||||
# REL-NEXT: PLTREL REL{{$}}
|
||||
# REL: .rel.dyn {
|
||||
# REL-NEXT: R_X86_64_RELATIVE - 0x0
|
||||
# REL-NEXT: R_X86_64_GLOB_DAT func 0x0
|
||||
# REL-NEXT: R_X86_64_64 _start 0
|
||||
# REL-NEXT: }
|
||||
# REL-NEXT: .rel.plt {
|
||||
# REL-NEXT: R_X86_64_JUMP_SLOT func 0x0
|
||||
# REL-NEXT: }
|
||||
|
||||
# REL: Hex dump of section '.data':
|
||||
# REL-NEXT: 0x00003408 08340000 00000000 2a000000 00000000
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
call func@PLT
|
||||
movq func@GOTPCREL(%rip), %rax
|
||||
|
||||
.data
|
||||
.quad .data
|
||||
.quad _start+42
|
Loading…
Reference in New Issue
Block a user