[lld-macho] Support pc-relative section relocations
Summary: So far we've only supported symbol relocations. Reviewers: ruiu, pcc, MaskRay, smeenai, alexshap, gkm, Ktwu, christylee Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D79211
This commit is contained in:
parent
7bbdbacd00
commit
198b0c57df
|
|
@ -134,6 +134,7 @@ InputFile::parseSections(ArrayRef<section_64> sections) {
|
||||||
for (const section_64 &sec : sections) {
|
for (const section_64 &sec : sections) {
|
||||||
InputSection *isec = make<InputSection>();
|
InputSection *isec = make<InputSection>();
|
||||||
isec->file = this;
|
isec->file = this;
|
||||||
|
isec->header = &sec;
|
||||||
isec->name = StringRef(sec.sectname, strnlen(sec.sectname, 16));
|
isec->name = StringRef(sec.sectname, strnlen(sec.sectname, 16));
|
||||||
isec->segname = StringRef(sec.segname, strnlen(sec.segname, 16));
|
isec->segname = StringRef(sec.segname, strnlen(sec.segname, 16));
|
||||||
isec->data = {buf + sec.offset, static_cast<size_t>(sec.size)};
|
isec->data = {buf + sec.offset, static_cast<size_t>(sec.size)};
|
||||||
|
|
@ -165,11 +166,14 @@ void InputFile::parseRelocations(const section_64 &sec,
|
||||||
r.type = rel.r_type;
|
r.type = rel.r_type;
|
||||||
r.offset = rel.r_address;
|
r.offset = rel.r_address;
|
||||||
r.addend = target->getImplicitAddend(buf + sec.offset + r.offset, r.type);
|
r.addend = target->getImplicitAddend(buf + sec.offset + r.offset, r.type);
|
||||||
if (rel.r_extern)
|
if (rel.r_extern) {
|
||||||
r.target = symbols[rel.r_symbolnum];
|
r.target = symbols[rel.r_symbolnum];
|
||||||
else {
|
} else {
|
||||||
error("TODO: Non-extern relocations are not supported");
|
if (rel.r_symbolnum == 0 || rel.r_symbolnum > sections.size())
|
||||||
continue;
|
fatal("invalid section index in relocation for offset " +
|
||||||
|
std::to_string(r.offset) + " in section " + sec.sectname +
|
||||||
|
" of " + getName());
|
||||||
|
r.target = sections[rel.r_symbolnum - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
relocs.push_back(r);
|
relocs.push_back(r);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ void InputSection::writeTo(uint8_t *buf) {
|
||||||
|
|
||||||
for (Reloc &r : relocs) {
|
for (Reloc &r : relocs) {
|
||||||
uint64_t va = 0;
|
uint64_t va = 0;
|
||||||
|
uint64_t addend = r.addend;
|
||||||
if (auto *s = r.target.dyn_cast<Symbol *>()) {
|
if (auto *s = r.target.dyn_cast<Symbol *>()) {
|
||||||
if (auto *dylibSymbol = dyn_cast<DylibSymbol>(s)) {
|
if (auto *dylibSymbol = dyn_cast<DylibSymbol>(s)) {
|
||||||
va = target->getDylibSymbolVA(*dylibSymbol, r.type);
|
va = target->getDylibSymbolVA(*dylibSymbol, r.type);
|
||||||
|
|
@ -40,11 +41,15 @@ void InputSection::writeTo(uint8_t *buf) {
|
||||||
}
|
}
|
||||||
} else if (auto *isec = r.target.dyn_cast<InputSection *>()) {
|
} else if (auto *isec = r.target.dyn_cast<InputSection *>()) {
|
||||||
va = isec->getVA();
|
va = isec->getVA();
|
||||||
} else {
|
// The implicit addend for pcrel section relocations is the pcrel offset
|
||||||
llvm_unreachable("Unknown relocation target");
|
// in terms of the addresses in the input file. Here we adjust it so that
|
||||||
|
// it describes the offset from the start of the target section.
|
||||||
|
// TODO: Figure out what to do for non-pcrel section relocations.
|
||||||
|
// TODO: The offset of 4 is probably not right for ARM64.
|
||||||
|
addend -= isec->header->addr - (header->addr + r.offset + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t val = va + r.addend;
|
uint64_t val = va + addend;
|
||||||
if (1) // TODO: handle non-pcrel relocations
|
if (1) // TODO: handle non-pcrel relocations
|
||||||
val -= getVA() + r.offset;
|
val -= getVA() + r.offset;
|
||||||
target->relocateOne(buf + r.offset, r.type, val);
|
target->relocateOne(buf + r.offset, r.type, val);
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ public:
|
||||||
InputFile *file = nullptr;
|
InputFile *file = nullptr;
|
||||||
StringRef name;
|
StringRef name;
|
||||||
StringRef segname;
|
StringRef segname;
|
||||||
|
// This provides access to the address of the section in the input file.
|
||||||
|
const llvm::MachO::section_64 *header;
|
||||||
|
|
||||||
OutputSection *parent = nullptr;
|
OutputSection *parent = nullptr;
|
||||||
uint64_t outSecOff = 0;
|
uint64_t outSecOff = 0;
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,12 @@
|
||||||
# CHECK-LABEL: <_main>:
|
# CHECK-LABEL: <_main>:
|
||||||
## Test X86_64_RELOC_BRANCH
|
## Test X86_64_RELOC_BRANCH
|
||||||
# CHECK: callq 0x[[#%x, F_ADDR]] <_f>
|
# CHECK: callq 0x[[#%x, F_ADDR]] <_f>
|
||||||
## Test X86_64_RELOC_SIGNED
|
## Test extern (symbol) X86_64_RELOC_SIGNED
|
||||||
# CHECK: leaq [[#%u, STR_OFF:]](%rip), %rsi
|
# CHECK: leaq [[#%u, STR_OFF:]](%rip), %rsi
|
||||||
# CHECK-NEXT: [[#%x, CSTRING_ADDR - STR_OFF]]
|
# CHECK-NEXT: [[#%x, CSTRING_ADDR - STR_OFF]]
|
||||||
|
## Test non-extern (section) X86_64_RELOC_SIGNED
|
||||||
|
# CHECK: leaq [[#%u, LSTR_OFF:]](%rip), %rsi
|
||||||
|
# CHECK-NEXT: [[#%x, CSTRING_ADDR + 22 - LSTR_OFF]]
|
||||||
|
|
||||||
.section __TEXT,__text
|
.section __TEXT,__text
|
||||||
.globl _main, _f
|
.globl _main, _f
|
||||||
|
|
@ -26,11 +29,21 @@ _main:
|
||||||
_f:
|
_f:
|
||||||
movl $0x2000004, %eax # write() syscall
|
movl $0x2000004, %eax # write() syscall
|
||||||
mov $1, %rdi # stdout
|
mov $1, %rdi # stdout
|
||||||
leaq str(%rip), %rsi
|
leaq _str(%rip), %rsi
|
||||||
mov $13, %rdx # length of str
|
mov $21, %rdx # length of str
|
||||||
|
syscall
|
||||||
|
|
||||||
|
movl $0x2000004, %eax # write() syscall
|
||||||
|
mov $1, %rdi # stdout
|
||||||
|
leaq L_.str(%rip), %rsi
|
||||||
|
mov $15, %rdx # length of str
|
||||||
syscall
|
syscall
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.section __TEXT,__cstring
|
.section __TEXT,__cstring
|
||||||
str:
|
## References to this generate a symbol relocation
|
||||||
.asciz "Hello world!\n"
|
_str:
|
||||||
|
.asciz "Local defined symbol\n"
|
||||||
|
## References to this generate a section relocation
|
||||||
|
L_.str:
|
||||||
|
.asciz "Private symbol\n"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# REQUIRES: x86
|
# REQUIRES: x86
|
||||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
|
||||||
# RUN: lld -flavor darwinnew -o %t %t.o
|
# RUN: lld -flavor darwinnew -o %t %t.o
|
||||||
# RUN: llvm-objdump -d %t | FileCheck %s
|
# RUN: llvm-objdump -D %t | FileCheck %s
|
||||||
|
|
||||||
# CHECK: <_main>:
|
# CHECK: <_main>:
|
||||||
# CHECK-NEXT: movl {{.*}} # 2000 <_s>
|
# CHECK-NEXT: movl {{.*}} # 2000 <_s>
|
||||||
|
|
@ -10,10 +10,18 @@
|
||||||
# CHECK-NEXT: callq {{.*}}
|
# CHECK-NEXT: callq {{.*}}
|
||||||
# CHECK-NEXT: movb {{.*}} # 2000 <_s>
|
# CHECK-NEXT: movb {{.*}} # 2000 <_s>
|
||||||
# CHECK-NEXT: callq {{.*}}
|
# CHECK-NEXT: callq {{.*}}
|
||||||
|
# CHECK: <__not_text>:
|
||||||
|
# CHECK-NEXT: movl {{.*}} # 2005
|
||||||
|
# CHECK-NEXT: callq {{.*}}
|
||||||
|
# CHECK-NEXT: movl {{.*}} # 2007
|
||||||
|
# CHECK-NEXT: callq {{.*}}
|
||||||
|
# CHECK-NEXT: movb {{.*}} # 2005
|
||||||
|
# CHECK-NEXT: callq {{.*}}
|
||||||
|
|
||||||
.section __TEXT,__text
|
.section __TEXT,__text
|
||||||
.globl _main
|
.globl _main
|
||||||
_main:
|
_main:
|
||||||
|
## Symbol relocations
|
||||||
movl $0x434241, _s(%rip) # X86_64_RELOC_SIGNED_4
|
movl $0x434241, _s(%rip) # X86_64_RELOC_SIGNED_4
|
||||||
callq _f
|
callq _f
|
||||||
movl $0x44, _s+2(%rip) # X86_64_RELOC_SIGNED_2
|
movl $0x44, _s+2(%rip) # X86_64_RELOC_SIGNED_2
|
||||||
|
|
@ -31,7 +39,26 @@ _f:
|
||||||
syscall
|
syscall
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section __TEXT,__not_text
|
||||||
|
## Section relocations. We intentionally put them in a separate section since
|
||||||
|
## the __text section typically starts at an address of zero in object files,
|
||||||
|
## and so does not fully exercise the relocation logic.
|
||||||
|
movl $0x434241, L._s(%rip) # X86_64_RELOC_SIGNED_4
|
||||||
|
callq _f
|
||||||
|
movl $0x44, L._s+2(%rip) # X86_64_RELOC_SIGNED_2
|
||||||
|
callq _f
|
||||||
|
movb $0x45, L._s(%rip) # X86_64_RELOC_SIGNED_1
|
||||||
|
callq _f
|
||||||
|
ret
|
||||||
|
|
||||||
.section __DATA,__data
|
.section __DATA,__data
|
||||||
.globl _s
|
.globl _s
|
||||||
_s:
|
_s:
|
||||||
.space 5
|
.space 5
|
||||||
|
|
||||||
|
## Create a new section to force the assembler to use a section relocation for
|
||||||
|
## the private symbol L._s. Otherwise, it will instead use a nearby non-private
|
||||||
|
## symbol to create a symbol relocation plus an addend.
|
||||||
|
.section __DATA,__foo
|
||||||
|
L._s:
|
||||||
|
.space 5
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue