summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2014-07-18 00:37:52 +0000
committerNick Kledzik <kledzik@apple.com>2014-07-18 00:37:52 +0000
commit68a1abdf14d02a616e9244a9a41be65fd4874aea (patch)
treeb745c61c43859e955b8b3149bf8bd9de14dffa70 /lld/lib/ReaderWriter
parent1eb023013e5e513162ece799f5b94eadfb625131 (diff)
downloadbcm5719-llvm-68a1abdf14d02a616e9244a9a41be65fd4874aea.tar.gz
bcm5719-llvm-68a1abdf14d02a616e9244a9a41be65fd4874aea.zip
[mach-o] Add support for x86 CALL instruction that uses a scattered relocation
llvm-svn: 213340
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp61
1 files changed, 47 insertions, 14 deletions
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
index 4cb043ec8eb..ae59a958fb6 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
@@ -202,6 +202,14 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
break;
+ case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4:
+ // ex: call _foo+n (and _foo defined)
+ *kind = branch32;
+ targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
+ if (E ec = atomFromAddress(0, reloc.value, target, addend))
+ return ec;
+ *addend = targetAddress - reloc.value;
+ break;
case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
// ex: callw _foo (and _foo undefined)
*kind = branch16;
@@ -215,6 +223,14 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
break;
+ case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2:
+ // ex: callw _foo+n (and _foo defined)
+ *kind = branch16;
+ targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
+ if (E ec = atomFromAddress(0, reloc.value, target, addend))
+ return ec;
+ *addend = targetAddress - reloc.value;
+ break;
case GENERIC_RELOC_VANILLA | rExtern | rLength4:
// ex: movl _foo, %eax (and _foo undefined)
// ex: .long _foo (and _foo undefined)
@@ -370,12 +386,19 @@ void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
uint64_t inAtomAddress) {
int32_t *loc32 = reinterpret_cast<int32_t *>(location);
int16_t *loc16 = reinterpret_cast<int16_t *>(location);
+ bool useExternalReloc = useExternalRelocationTo(*ref.target());
switch (ref.kindValue()) {
case branch32:
- write32(*loc32, _swap, ref.addend() - (fixupAddress + 4));
+ if (useExternalReloc)
+ write32(*loc32, _swap, ref.addend() - (fixupAddress + 4));
+ else
+ write32(*loc32, _swap, (targetAddress - (fixupAddress+4)) + ref.addend());
break;
case branch16:
- write16(*loc16, _swap, ref.addend() - (fixupAddress + 2));
+ if (useExternalReloc)
+ write16(*loc16, _swap, ref.addend() - (fixupAddress + 2));
+ else
+ write16(*loc16, _swap, (targetAddress - (fixupAddress+2)) + ref.addend());
break;
case pointer32:
case abs32:
@@ -434,20 +457,30 @@ void ArchHandler_x86::appendSectionRelocations(
bool useExternalReloc = useExternalRelocationTo(*ref.target());
switch (ref.kindValue()) {
case branch32:
- if (useExternalReloc)
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4);
- else
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- GENERIC_RELOC_VANILLA | rPcRel | rLength4);
+ if (useExternalReloc) {
+ appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+ GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength4);
+ } else {
+ if (ref.addend() != 0)
+ appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
+ GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4);
+ else
+ appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
+ GENERIC_RELOC_VANILLA | rPcRel | rLength4);
+ }
break;
case branch16:
- if (useExternalReloc)
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2);
- else
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- GENERIC_RELOC_VANILLA | rPcRel | rLength2);
+ if (useExternalReloc) {
+ appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+ GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength2);
+ } else {
+ if (ref.addend() != 0)
+ appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
+ GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2);
+ else
+ appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
+ GENERIC_RELOC_VANILLA | rPcRel | rLength2);
+ }
break;
case pointer32:
case abs32:
OpenPOWER on IntegriCloud