ARM non-scattered MachO relocations for movw/movt.

Needed when building -mdynamic-no-pic code.

rdar://10459256

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153097 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2012-03-20 17:25:45 +00:00
parent 1fc999ec47
commit 07cdd80ccc
2 changed files with 81 additions and 22 deletions

View File

@ -34,12 +34,12 @@ class ARMMachObjectWriter : public MCMachObjectTargetWriter {
MCValue Target,
unsigned Log2Size,
uint64_t &FixedValue);
void RecordARMMovwMovtRelocation(MachObjectWriter *Writer,
const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue);
void RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue);
public:
ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType,
@ -102,34 +102,47 @@ static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
Log2Size = llvm::Log2_32(4);
return true;
// For movw/movt r_type relocations they always have a pair following them and
// the r_length bits are used differently. The encoding of the r_length is as
// follows:
// low bit of r_length:
// 0 - :lower16: for movw instructions
// 1 - :upper16: for movt instructions
// high bit of r_length:
// 0 - arm instructions
// 1 - thumb instructions
case ARM::fixup_arm_movt_hi16:
case ARM::fixup_arm_movt_hi16_pcrel:
RelocType = unsigned(macho::RIT_ARM_Half);
Log2Size = 1;
return true;
case ARM::fixup_t2_movt_hi16:
case ARM::fixup_t2_movt_hi16_pcrel:
RelocType = unsigned(macho::RIT_ARM_HalfDifference);
// Report as 'long', even though that is not quite accurate.
Log2Size = llvm::Log2_32(4);
RelocType = unsigned(macho::RIT_ARM_Half);
Log2Size = 3;
return true;
case ARM::fixup_arm_movw_lo16:
case ARM::fixup_arm_movw_lo16_pcrel:
RelocType = unsigned(macho::RIT_ARM_Half);
Log2Size = 0;
return true;
case ARM::fixup_t2_movw_lo16:
case ARM::fixup_t2_movw_lo16_pcrel:
RelocType = unsigned(macho::RIT_ARM_Half);
// Report as 'long', even though that is not quite accurate.
Log2Size = llvm::Log2_32(4);
Log2Size = 2;
return true;
}
}
void ARMMachObjectWriter::
RecordARMMovwMovtRelocation(MachObjectWriter *Writer,
const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
uint64_t &FixedValue) {
RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
uint64_t &FixedValue) {
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
unsigned Type = macho::RIT_ARM_Half;
@ -313,10 +326,9 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
// scattered relocation entry. Differences always require scattered
// relocations.
if (Target.getSymB()) {
if (RelocType == macho::RIT_ARM_Half ||
RelocType == macho::RIT_ARM_HalfDifference)
return RecordARMMovwMovtRelocation(Writer, Asm, Layout, Fragment, Fixup,
Target, FixedValue);
if (RelocType == macho::RIT_ARM_Half)
return RecordARMScatteredHalfRelocation(Writer, Asm, Layout, Fragment,
Fixup, Target, FixedValue);
return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
Target, Log2Size, FixedValue);
}
@ -391,6 +403,30 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
(Log2Size << 25) |
(IsExtern << 27) |
(Type << 28));
// Even when it's not a scattered relocation, movw/movt always uses
// a PAIR relocation.
if (Type == macho::RIT_ARM_Half) {
// The other-half value only gets populated for the movt relocation.
uint32_t Value = 0;;
switch ((unsigned)Fixup.getKind()) {
default: break;
case ARM::fixup_arm_movt_hi16:
case ARM::fixup_arm_movt_hi16_pcrel:
case ARM::fixup_t2_movt_hi16:
case ARM::fixup_t2_movt_hi16_pcrel:
Value = FixedValue;
break;
}
macho::RelocationEntry MREPair;
MREPair.Word0 = Value;
MREPair.Word1 = ((0xffffff) |
(Log2Size << 25) |
(macho::RIT_Pair << 28));
Writer->addRelocation(Fragment->getParent(), MREPair);
}
Writer->addRelocation(Fragment->getParent(), MRE);
}

View File

@ -0,0 +1,23 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumbv7-apple-darwin10 -filetype=obj -o - < %s | macho-dump | FileCheck %s
.thumb
.thumb_func foo
foo:
movw r0, :lower16:(bar + 16)
movt r0, :upper16:(bar + 16)
bx r0
@ CHECK: ('_relocations', [
@ CHECK: # Relocation 0
@ CHECK: (('word-0', 0x4),
@ CHECK: ('word-1', 0x8e000001)),
@ CHECK: # Relocation 1
@ CHECK: (('word-0', 0x10),
@ CHECK: ('word-1', 0x16ffffff)),
@ CHECK: # Relocation 2
@ CHECK: (('word-0', 0x0),
@ CHECK: ('word-1', 0x8c000001)),
@ CHECK: # Relocation 3
@ CHECK: (('word-0', 0x0),
@ CHECK: ('word-1', 0x14ffffff)),
@ CHECK: ])