mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-24 20:30:06 +00:00
ARM: Darwin BL/BLX relocations to out-of-range symbols.
When a BL/BLX references a symbol in the same translation unit that is out of range, use an external relocation. The linker will use this to generate a branch island rather than a direct reference, allowing the relocation to resolve correctly. rdar://12359919 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164615 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1309844399
commit
fe2d5f8487
@ -41,6 +41,12 @@ class ARMMachObjectWriter : public MCMachObjectTargetWriter {
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
bool requiresExternRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCFragment &Fragment,
|
||||
unsigned RelocType, const MCSymbolData *SD,
|
||||
uint64_t FixedValue);
|
||||
|
||||
public:
|
||||
ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType,
|
||||
uint32_t CPUSubtype)
|
||||
@ -305,6 +311,46 @@ void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
|
||||
Writer->addRelocation(Fragment->getParent(), MRE);
|
||||
}
|
||||
|
||||
bool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCFragment &Fragment,
|
||||
unsigned RelocType,
|
||||
const MCSymbolData *SD,
|
||||
uint64_t FixedValue) {
|
||||
// Most cases can be identified purely from the symbol.
|
||||
if (Writer->doesSymbolRequireExternRelocation(SD))
|
||||
return true;
|
||||
int64_t Value = (int64_t)FixedValue; // The displacement is signed.
|
||||
int64_t Range;
|
||||
switch (RelocType) {
|
||||
default:
|
||||
return false;
|
||||
case macho::RIT_ARM_Branch24Bit:
|
||||
// PC pre-adjustment of 8 for these instructions.
|
||||
Value -= 8;
|
||||
// ARM BL/BLX has a 25-bit offset.
|
||||
Range = 0x1ffffff;
|
||||
break;
|
||||
case macho::RIT_ARM_ThumbBranch22Bit:
|
||||
// PC pre-adjustment of 4 for these instructions.
|
||||
Value -= 4;
|
||||
// Thumb BL/BLX has a 24-bit offset.
|
||||
Range = 0xffffff;
|
||||
}
|
||||
// BL/BLX also use external relocations when an internal relocation
|
||||
// would result in the target being out of range. This gives the linker
|
||||
// enough information to generate a branch island.
|
||||
const MCSectionData &SymSD = Asm.getSectionData(
|
||||
SD->getSymbol().getSection());
|
||||
Value += Writer->getSectionAddress(&SymSD);
|
||||
Value -= Writer->getSectionAddress(Fragment.getParent());
|
||||
// If the resultant value would be out of range for an internal relocation,
|
||||
// use an external instead.
|
||||
if (Value > Range || Value < -(Range + 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
@ -373,7 +419,8 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
|
||||
}
|
||||
|
||||
// Check whether we need an external or internal relocation.
|
||||
if (Writer->doesSymbolRequireExternRelocation(SD)) {
|
||||
if (requiresExternRelocation(Writer, Asm, *Fragment, RelocType, SD,
|
||||
FixedValue)) {
|
||||
IsExtern = 1;
|
||||
Index = SD->getIndex();
|
||||
|
||||
|
43
test/MC/MachO/ARM/long-call-branch-island-relocation.s
Normal file
43
test/MC/MachO/ARM/long-call-branch-island-relocation.s
Normal file
@ -0,0 +1,43 @@
|
||||
@ RUN: llvm-mc -n -triple armv7-apple-darwin10 %s -filetype=obj -o %t.o
|
||||
@ RUN: macho-dump --dump-section-data < %t.o | FileCheck %s
|
||||
|
||||
@ rdar://12359919
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
.globl _bar
|
||||
.align 2
|
||||
.code 16
|
||||
.thumb_func _bar
|
||||
_bar:
|
||||
push {r7, lr}
|
||||
mov r7, sp
|
||||
bl _foo
|
||||
pop {r7, pc}
|
||||
|
||||
|
||||
_junk:
|
||||
@ Make the _foo symbol sufficiently far away to force the 'bl' relocation
|
||||
@ above to be out of range. On Darwin, the assembler deals with this by
|
||||
@ generating an external relocation so the linker can create a branch
|
||||
@ island.
|
||||
|
||||
.space 20000000
|
||||
|
||||
.section __TEXT,initcode,regular,pure_instructions
|
||||
|
||||
.globl _foo
|
||||
.align 2
|
||||
.code 16
|
||||
_foo:
|
||||
push {r7, lr}
|
||||
mov r7, sp
|
||||
pop {r7, pc}
|
||||
|
||||
|
||||
@ CHECK: ('_relocations', [
|
||||
@ CHECK: # Relocation 0
|
||||
@ CHECK: (('word-0', 0x4),
|
||||
@ CHECK: ('word-1', 0x6d000002)),
|
||||
@ CHECK: ])
|
Loading…
Reference in New Issue
Block a user