mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 23:51:56 +00:00
[mach-o] add parsing of x86 relocations
llvm-svn: 212239
This commit is contained in:
parent
bcb70eee1a
commit
de0860aae4
@ -182,6 +182,9 @@ inline void swapStruct(llvm::MachO::nlist_64 &sym) {
|
||||
|
||||
|
||||
|
||||
inline uint16_t read16(bool swap, uint16_t value) {
|
||||
return (swap ? getSwappedBytes(value) : value);
|
||||
}
|
||||
|
||||
inline uint32_t read32(bool swap, uint32_t value) {
|
||||
return (swap ? getSwappedBytes(value) : value);
|
||||
|
@ -438,10 +438,25 @@ std::error_code convertRelocs(const Section §ion,
|
||||
if (sectIndex > normalizedFile.sections.size())
|
||||
return make_dynamic_error_code(Twine("out of range section "
|
||||
"index (") + Twine(sectIndex) + ")");
|
||||
const Section § = normalizedFile.sections[sectIndex-1];
|
||||
const Section *sect = nullptr;
|
||||
if (sectIndex == 0) {
|
||||
for (const Section &s : normalizedFile.sections) {
|
||||
uint64_t sAddr = s.address;
|
||||
if ((sAddr <= addr) && (addr < sAddr+s.content.size())) {
|
||||
sect = &s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sect) {
|
||||
return make_dynamic_error_code(Twine("address (" + Twine(addr)
|
||||
+ ") is not in any section"));
|
||||
}
|
||||
} else {
|
||||
sect = &normalizedFile.sections[sectIndex-1];
|
||||
}
|
||||
uint32_t offsetInTarget;
|
||||
uint64_t offsetInSect = addr - sect.address;
|
||||
*atom = file.findAtomCoveringAddress(sect, offsetInSect, &offsetInTarget);
|
||||
uint64_t offsetInSect = addr - sect->address;
|
||||
*atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
|
||||
*addend = offsetInTarget;
|
||||
return std::error_code();
|
||||
};
|
||||
@ -534,7 +549,7 @@ std::error_code convertRelocs(const Section §ion,
|
||||
+ " (r_address=" + Twine::utohexstr(reloc.offset)
|
||||
+ ", r_type=" + Twine(reloc.type)
|
||||
+ ", r_extern=" + Twine(reloc.isExtern)
|
||||
+ ", r_length=" + Twine(reloc.length)
|
||||
+ ", r_length=" + Twine((int)reloc.length)
|
||||
+ ", r_pcrel=" + Twine(reloc.pcRel)
|
||||
+ (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
|
||||
: (Twine(", r_scattered=1, r_value=")
|
||||
@ -542,7 +557,17 @@ std::error_code convertRelocs(const Section §ion,
|
||||
+ ")" );
|
||||
} else {
|
||||
// Instantiate an lld::Reference object and add to its atom.
|
||||
inAtom->addReference(offsetInAtom, kind, target, addend);
|
||||
Reference::KindArch arch = Reference::KindArch::all;
|
||||
switch (normalizedFile.arch ) {
|
||||
case lld::MachOLinkingContext::arch_x86_64:
|
||||
arch = Reference::KindArch::x86_64;
|
||||
break;
|
||||
case lld::MachOLinkingContext::arch_x86:
|
||||
arch = Reference::KindArch::x86;
|
||||
break;
|
||||
}
|
||||
|
||||
inAtom->addReference(offsetInAtom, kind, target, addend, arch);
|
||||
}
|
||||
}
|
||||
return std::error_code();
|
||||
@ -580,7 +605,8 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
|
||||
}
|
||||
|
||||
// TEMP BEGIN: until all KindHandlers switched to new interface.
|
||||
if (normalizedFile.arch != lld::MachOLinkingContext::arch_x86_64)
|
||||
if ((normalizedFile.arch != lld::MachOLinkingContext::arch_x86_64) &&
|
||||
(normalizedFile.arch != lld::MachOLinkingContext::arch_x86))
|
||||
return std::unique_ptr<File>(std::move(file));
|
||||
// TEMP END
|
||||
|
||||
|
@ -76,6 +76,23 @@ KindHandler::RelocPattern KindHandler::relocPattern(const Relocation &reloc) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int16_t KindHandler::readS16(bool swap, const uint8_t *addr) {
|
||||
return read16(swap, *reinterpret_cast<const uint16_t*>(addr));
|
||||
}
|
||||
|
||||
int32_t KindHandler::readS32(bool swap, const uint8_t *addr) {
|
||||
return read32(swap, *reinterpret_cast<const uint32_t*>(addr));
|
||||
}
|
||||
|
||||
uint32_t KindHandler::readU32(bool swap, const uint8_t *addr) {
|
||||
return read32(swap, *reinterpret_cast<const uint32_t*>(addr));
|
||||
}
|
||||
|
||||
int64_t KindHandler::readS64(bool swap, const uint8_t *addr) {
|
||||
return read64(swap, *reinterpret_cast<const uint64_t*>(addr));
|
||||
}
|
||||
|
||||
|
||||
bool KindHandler::isPairedReloc(const Relocation &reloc) {
|
||||
llvm_unreachable("abstract");
|
||||
}
|
||||
@ -87,13 +104,13 @@ KindHandler::getReferenceInfo(const Relocation &reloc,
|
||||
uint64_t fixupAddress, bool swap,
|
||||
FindAtomBySectionAndAddress atomFromAddress,
|
||||
FindAtomBySymbolIndex atomFromSymbolIndex,
|
||||
Reference::KindValue *kind,
|
||||
const lld::Atom **target,
|
||||
Reference::KindValue *kind,
|
||||
const lld::Atom **target,
|
||||
Reference::Addend *addend) {
|
||||
llvm_unreachable("abstract");
|
||||
}
|
||||
|
||||
std::error_code
|
||||
std::error_code
|
||||
KindHandler::getPairReferenceInfo(const normalized::Relocation &reloc1,
|
||||
const normalized::Relocation &reloc2,
|
||||
const DefinedAtom *inAtom,
|
||||
@ -101,8 +118,8 @@ KindHandler::getPairReferenceInfo(const normalized::Relocation &reloc1,
|
||||
uint64_t fixupAddress, bool swap,
|
||||
FindAtomBySectionAndAddress atomFromAddress,
|
||||
FindAtomBySymbolIndex atomFromSymbolIndex,
|
||||
Reference::KindValue *kind,
|
||||
const lld::Atom **target,
|
||||
Reference::KindValue *kind,
|
||||
const lld::Atom **target,
|
||||
Reference::Addend *addend) {
|
||||
llvm_unreachable("abstract");
|
||||
}
|
||||
@ -169,13 +186,6 @@ bool KindHandler_x86_64::isPairedReloc(const Relocation &reloc) {
|
||||
return (reloc.type == X86_64_RELOC_SUBTRACTOR);
|
||||
}
|
||||
|
||||
static int32_t readS32(bool swap, const uint8_t *addr) {
|
||||
return read32(swap, *reinterpret_cast<const uint32_t*>(addr));
|
||||
}
|
||||
|
||||
static int64_t readS64(bool swap, const uint8_t *addr) {
|
||||
return read64(swap, *reinterpret_cast<const uint64_t*>(addr));
|
||||
}
|
||||
|
||||
Reference::KindValue
|
||||
KindHandler_x86_64::kindFromReloc(const Relocation &reloc) {
|
||||
@ -400,29 +410,166 @@ KindHandler_x86::~KindHandler_x86() {
|
||||
}
|
||||
|
||||
const Registry::KindStrings KindHandler_x86::kindStrings[] = {
|
||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_BRANCH32),
|
||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_ABS32),
|
||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_FUNC_REL32),
|
||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_POINTER32),
|
||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_LAZY_TARGET),
|
||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_LAZY_IMMEDIATE),
|
||||
LLD_KIND_STRING_ENTRY(invalid),
|
||||
LLD_KIND_STRING_ENTRY(branch32),
|
||||
LLD_KIND_STRING_ENTRY(branch16),
|
||||
LLD_KIND_STRING_ENTRY(abs32),
|
||||
LLD_KIND_STRING_ENTRY(funcRel32),
|
||||
LLD_KIND_STRING_ENTRY(pointer32),
|
||||
LLD_KIND_STRING_ENTRY(delta32),
|
||||
LLD_KIND_STRING_ENTRY(lazyPointer),
|
||||
LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
|
||||
LLD_KIND_STRING_END
|
||||
};
|
||||
|
||||
bool KindHandler_x86::isCallSite(const Reference &ref) {
|
||||
return (ref.kindValue() == LLD_X86_RELOC_BRANCH32);
|
||||
return (ref.kindValue() == branch32);
|
||||
}
|
||||
|
||||
bool KindHandler_x86::isPointer(const Reference &ref) {
|
||||
return (ref.kindValue() == LLD_X86_RELOC_POINTER32);
|
||||
return (ref.kindValue() == pointer32);
|
||||
}
|
||||
|
||||
bool KindHandler_x86::isLazyImmediate(const Reference &ref) {
|
||||
return (ref.kindValue() == LLD_X86_RELOC_LAZY_TARGET);
|
||||
return (ref.kindValue() == lazyImmediateLocation);
|
||||
}
|
||||
|
||||
bool KindHandler_x86::isLazyTarget(const Reference &ref) {
|
||||
return (ref.kindValue() == LLD_X86_RELOC_LAZY_TARGET);
|
||||
return (ref.kindValue() == lazyPointer);
|
||||
}
|
||||
|
||||
|
||||
bool KindHandler_x86::isPairedReloc(const Relocation &reloc) {
|
||||
if (!reloc.scattered)
|
||||
return false;
|
||||
return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) ||
|
||||
(reloc.type == GENERIC_RELOC_SECTDIFF);
|
||||
}
|
||||
|
||||
|
||||
std::error_code
|
||||
KindHandler_x86::getReferenceInfo(const Relocation &reloc,
|
||||
const DefinedAtom *inAtom,
|
||||
uint32_t offsetInAtom,
|
||||
uint64_t fixupAddress, bool swap,
|
||||
FindAtomBySectionAndAddress atomFromAddress,
|
||||
FindAtomBySymbolIndex atomFromSymbolIndex,
|
||||
Reference::KindValue *kind,
|
||||
const lld::Atom **target,
|
||||
Reference::Addend *addend) {
|
||||
typedef std::error_code E;
|
||||
DefinedAtom::ContentPermissions perms;
|
||||
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
|
||||
uint64_t targetAddress;
|
||||
switch (relocPattern(reloc)) {
|
||||
case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4:
|
||||
// ex: call _foo (and _foo undefined)
|
||||
*kind = branch32;
|
||||
if (E ec = atomFromSymbolIndex(reloc.symbol, target))
|
||||
return ec;
|
||||
*addend = fixupAddress + 4 + readS32(swap, fixupContent);
|
||||
break;
|
||||
case GENERIC_RELOC_VANILLA | rPcRel | rLength4:
|
||||
// ex: call _foo (and _foo defined)
|
||||
*kind = branch32;
|
||||
targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
|
||||
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
|
||||
break;
|
||||
case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
|
||||
// ex: callw _foo (and _foo undefined)
|
||||
*kind = branch16;
|
||||
if (E ec = atomFromSymbolIndex(reloc.symbol, target))
|
||||
return ec;
|
||||
*addend = fixupAddress + 2 + readS16(swap, fixupContent);
|
||||
break;
|
||||
case GENERIC_RELOC_VANILLA | rPcRel | rLength2:
|
||||
// ex: callw _foo (and _foo defined)
|
||||
*kind = branch16;
|
||||
targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
|
||||
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
|
||||
break;
|
||||
case GENERIC_RELOC_VANILLA | rExtern | rLength4:
|
||||
// ex: movl _foo, %eax (and _foo undefined)
|
||||
// ex: .long _foo (and _foo undefined)
|
||||
perms = inAtom->permissions();
|
||||
*kind = ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X)
|
||||
? abs32 : pointer32;
|
||||
if (E ec = atomFromSymbolIndex(reloc.symbol, target))
|
||||
return ec;
|
||||
*addend = readU32(swap, fixupContent);
|
||||
break;
|
||||
case GENERIC_RELOC_VANILLA | rLength4:
|
||||
// ex: movl _foo, %eax (and _foo defined)
|
||||
// ex: .long _foo (and _foo defined)
|
||||
perms = inAtom->permissions();
|
||||
*kind = ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X)
|
||||
? abs32 : pointer32;
|
||||
targetAddress = readU32(swap, fixupContent);
|
||||
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
|
||||
break;
|
||||
default:
|
||||
return make_dynamic_error_code(Twine("unsupported i386 relocation type"));
|
||||
}
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
|
||||
std::error_code
|
||||
KindHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
|
||||
const normalized::Relocation &reloc2,
|
||||
const DefinedAtom *inAtom,
|
||||
uint32_t offsetInAtom,
|
||||
uint64_t fixupAddress, bool swap,
|
||||
FindAtomBySectionAndAddress atomFromAddr,
|
||||
FindAtomBySymbolIndex atomFromSymbolIndex,
|
||||
Reference::KindValue *kind,
|
||||
const lld::Atom **target,
|
||||
Reference::Addend *addend) {
|
||||
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
|
||||
std::error_code ec;
|
||||
DefinedAtom::ContentPermissions perms = inAtom->permissions();
|
||||
uint32_t fromAddress;
|
||||
uint32_t toAddress;
|
||||
uint32_t value;
|
||||
const lld::Atom *fromTarget;
|
||||
Reference::Addend offsetInTo;
|
||||
Reference::Addend offsetInFrom;
|
||||
switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
|
||||
case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
|
||||
GENERIC_RELOC_PAIR | rScattered | rLength4):
|
||||
case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
|
||||
GENERIC_RELOC_PAIR | rScattered | rLength4):
|
||||
toAddress = reloc1.value;
|
||||
fromAddress = reloc2.value;
|
||||
value = readS32(swap, fixupContent);
|
||||
ec = atomFromAddr(0, toAddress, target, &offsetInTo);
|
||||
if (ec)
|
||||
return ec;
|
||||
ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
|
||||
if (ec)
|
||||
return ec;
|
||||
if (fromTarget != inAtom)
|
||||
return make_dynamic_error_code(Twine("SECTDIFF relocation where "
|
||||
"subtrahend label is not in atom"));
|
||||
*kind = ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X)
|
||||
? funcRel32 : delta32;
|
||||
if (*kind == funcRel32) {
|
||||
// SECTDIFF relocations are used in i386 codegen where the function
|
||||
// prolog does a CALL to the next instruction which POPs the return
|
||||
// address into EBX which becomes the pic-base register. The POP
|
||||
// instruction is label the used for the subtrahend in expressions.
|
||||
// The funcRel32 kind represents the 32-bit delta to some symbol from
|
||||
// the start of the function (atom) containing the funcRel32.
|
||||
uint32_t ta = fromAddress + value - toAddress;
|
||||
*addend = ta - offsetInFrom;
|
||||
} else {
|
||||
*addend= fromAddress + value - toAddress;
|
||||
}
|
||||
return std::error_code();
|
||||
break;
|
||||
default:
|
||||
return make_dynamic_error_code(Twine("unsupported i386 relocation type"));
|
||||
}
|
||||
}
|
||||
|
||||
void KindHandler_x86::applyFixup(Reference::KindNamespace ns,
|
||||
|
@ -125,7 +125,11 @@ protected:
|
||||
rLength8 = 0x0300
|
||||
};
|
||||
static RelocPattern relocPattern(const normalized::Relocation &reloc);
|
||||
|
||||
|
||||
static int16_t readS16(bool swap, const uint8_t *addr);
|
||||
static int32_t readS32(bool swap, const uint8_t *addr);
|
||||
static uint32_t readU32(bool swap, const uint8_t *addr);
|
||||
static int64_t readS64(bool swap, const uint8_t *addr);
|
||||
};
|
||||
|
||||
|
||||
@ -216,12 +220,61 @@ public:
|
||||
bool isPointer(const Reference &) override;
|
||||
bool isLazyImmediate(const Reference &) override;
|
||||
bool isLazyTarget(const Reference &) override;
|
||||
virtual void applyFixup(Reference::KindNamespace ns, Reference::KindArch arch,
|
||||
bool isPairedReloc(const normalized::Relocation &) override;
|
||||
std::error_code getReferenceInfo(const normalized::Relocation &reloc,
|
||||
const DefinedAtom *inAtom,
|
||||
uint32_t offsetInAtom,
|
||||
uint64_t fixupAddress, bool swap,
|
||||
FindAtomBySectionAndAddress atomFromAddress,
|
||||
FindAtomBySymbolIndex atomFromSymbolIndex,
|
||||
Reference::KindValue *kind,
|
||||
const lld::Atom **target,
|
||||
Reference::Addend *addend) override;
|
||||
std::error_code
|
||||
getPairReferenceInfo(const normalized::Relocation &reloc1,
|
||||
const normalized::Relocation &reloc2,
|
||||
const DefinedAtom *inAtom,
|
||||
uint32_t offsetInAtom,
|
||||
uint64_t fixupAddress, bool swap,
|
||||
FindAtomBySectionAndAddress atomFromAddress,
|
||||
FindAtomBySymbolIndex atomFromSymbolIndex,
|
||||
Reference::KindValue *kind,
|
||||
const lld::Atom **target,
|
||||
Reference::Addend *addend) override;
|
||||
|
||||
void applyFixup(Reference::KindNamespace ns, Reference::KindArch arch,
|
||||
Reference::KindValue kindValue, uint64_t addend,
|
||||
uint8_t *location, uint64_t fixupAddress,
|
||||
uint64_t targetAddress) override;
|
||||
|
||||
private:
|
||||
friend class X86LazyPointerAtom;
|
||||
friend class X86StubHelperAtom;
|
||||
friend class X86StubAtom;
|
||||
friend class X86StubHelperCommonAtom;
|
||||
friend class X86NonLazyPointerAtom;
|
||||
|
||||
enum : Reference::KindValue {
|
||||
invalid, /// for error condition
|
||||
|
||||
// Kinds found in mach-o .o files:
|
||||
branch32, /// ex: call _foo
|
||||
branch16, /// ex: callw _foo
|
||||
abs32, /// ex: movl _foo, %eax
|
||||
funcRel32, /// ex: movl _foo-L1(%eax), %eax
|
||||
pointer32, /// ex: .long _foo
|
||||
delta32, /// ex: .long _foo - .
|
||||
|
||||
// Kinds introduced by Passes:
|
||||
lazyPointer, /// Location contains a lazy pointer.
|
||||
lazyImmediateLocation, /// Location contains immediate value used in stub.
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class KindHandler_arm : public KindHandler {
|
||||
public:
|
||||
static const Registry::KindStrings kindStrings[];
|
||||
|
@ -39,7 +39,7 @@ sections:
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 0
|
||||
- offset: 0x00000008
|
||||
type: GENERIC_RELOC_VANILLA
|
||||
length: 2
|
||||
@ -51,7 +51,7 @@ sections:
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 0
|
||||
undefined-symbols:
|
||||
- name: ___CFConstantStringClassReference
|
||||
type: N_UNDF
|
||||
@ -60,19 +60,35 @@ undefined-symbols:
|
||||
...
|
||||
|
||||
# CHECK: defined-atoms:
|
||||
# CHECK: - scope: hidden
|
||||
# CHECK: - ref-name: [[STR1:L[L0-9]+]]
|
||||
# CHECK: scope: hidden
|
||||
# CHECK: type: c-string
|
||||
# CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ]
|
||||
# CHECK: merge: by-content
|
||||
# CHECK: - scope: hidden
|
||||
# CHECK: - ref-name: [[STR2:L[L0-9]+]]
|
||||
# CHECK: scope: hidden
|
||||
# CHECK: type: c-string
|
||||
# CHECK: content: [ 74, 68, 65, 72, 65, 00 ]
|
||||
# CHECK: merge: by-content
|
||||
# CHECK: - scope: hidden
|
||||
# CHECK: type: cfstring
|
||||
# CHECK: merge: by-content
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: pointer32
|
||||
# CHECK: offset: 0
|
||||
# CHECK: target: ___CFConstantStringClassReference
|
||||
# CHECK: - kind: pointer32
|
||||
# CHECK: offset: 8
|
||||
# CHECK: target: [[STR1]]
|
||||
# CHECK: - scope: hidden
|
||||
# CHECK: type: cfstring
|
||||
# CHECK: merge: by-content
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: pointer32
|
||||
# CHECK: offset: 0
|
||||
# CHECK: target: ___CFConstantStringClassReference
|
||||
# CHECK: - kind: pointer32
|
||||
# CHECK: offset: 8
|
||||
# CHECK: target: [[STR2]]
|
||||
# CHECK:undefined-atoms:
|
||||
# CHECK: - name: ___CFConstantStringClassReference
|
||||
|
@ -71,11 +71,13 @@ undefined-symbols:
|
||||
|
||||
|
||||
# CHECK:defined-atoms:
|
||||
# CHECK: - scope: hidden
|
||||
# CHECK: - ref-name: [[GOT1:L[L0-9]+]]
|
||||
# CHECK: scope: hidden
|
||||
# CHECK: type: got
|
||||
# CHECK: content: [ 00, 00, 00, 00 ]
|
||||
# CHECK: merge: by-content
|
||||
# CHECK: - scope: hidden
|
||||
# CHECK: - ref-name: [[GOT2:L[L0-9]+]]
|
||||
# CHECK: scope: hidden
|
||||
# CHECK: type: got
|
||||
# CHECK: content: [ 00, 00, 00, 00 ]
|
||||
# CHECK: merge: by-content
|
||||
@ -83,6 +85,13 @@ undefined-symbols:
|
||||
# CHECK: scope: global
|
||||
# CHECK: content: [ 55, 89, E5, E8, 00, 00, 00, 00, 59, 8D, 81, 14,
|
||||
# CHECK: 00, 00, 00, 8D, 81, 18, 00, 00, 00, 5D, C3 ]
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: funcRel32
|
||||
# CHECK: offset: 11
|
||||
# CHECK: target: [[GOT1]]
|
||||
# CHECK: - kind: funcRel32
|
||||
# CHECK: offset: 17
|
||||
# CHECK: target: [[GOT2]]
|
||||
# CHECK: - name: _foo
|
||||
# CHECK: content: [ 55, 89, E5, 5D, C3 ]
|
||||
|
||||
|
190
lld/test/mach-o/parse-relocs-x86.yaml
Normal file
190
lld/test/mach-o/parse-relocs-x86.yaml
Normal file
@ -0,0 +1,190 @@
|
||||
# RUN: lld -flavor darwin -arch i386 -r -print_atoms %s -o %t | FileCheck %s
|
||||
#
|
||||
# Test parsing of x86 relocations.
|
||||
#
|
||||
# .text
|
||||
#
|
||||
#_test:
|
||||
# call _undef
|
||||
# call _undef+2
|
||||
# callw _undef
|
||||
#L1:
|
||||
# movl _undef, %eax
|
||||
# movl _x, %eax
|
||||
# movl _x-L1(%eax), %eax
|
||||
# movl _x+4-L1(%eax), %eax
|
||||
#
|
||||
# .data
|
||||
#_x:
|
||||
# .long _undef
|
||||
# .long _test - .
|
||||
# .long _test+3 - .
|
||||
#
|
||||
|
||||
--- !mach-o
|
||||
arch: x86
|
||||
file-type: MH_OBJECT
|
||||
flags: [ ]
|
||||
OS: unknown
|
||||
sections:
|
||||
- segment: __TEXT
|
||||
section: __text
|
||||
type: S_REGULAR
|
||||
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
|
||||
address: 0x0000000000000000
|
||||
content: [ 0xE8, 0xFB, 0xFF, 0xFF, 0xFF, 0xE8, 0xF8, 0xFF,
|
||||
0xFF, 0xFF, 0x66, 0xE8, 0xF2, 0xFF, 0xA1, 0x00,
|
||||
0x00, 0x00, 0x00, 0xA1, 0x24, 0x00, 0x00, 0x00,
|
||||
0x8B, 0x80, 0x16, 0x00, 0x00, 0x00, 0x8B, 0x80,
|
||||
0x1A, 0x00, 0x00, 0x00 ]
|
||||
relocations:
|
||||
- offset: 0x00000020
|
||||
scattered: true
|
||||
type: GENERIC_RELOC_LOCAL_SECTDIFF
|
||||
length: 2
|
||||
pc-rel: false
|
||||
value: 0x00000024
|
||||
- offset: 0x00000000
|
||||
scattered: true
|
||||
type: GENERIC_RELOC_PAIR
|
||||
length: 2
|
||||
pc-rel: false
|
||||
value: 0x0000000E
|
||||
- offset: 0x0000001A
|
||||
scattered: true
|
||||
type: GENERIC_RELOC_LOCAL_SECTDIFF
|
||||
length: 2
|
||||
pc-rel: false
|
||||
value: 0x00000024
|
||||
- offset: 0x00000000
|
||||
scattered: true
|
||||
type: GENERIC_RELOC_PAIR
|
||||
length: 2
|
||||
pc-rel: false
|
||||
value: 0x0000000E
|
||||
- offset: 0x00000014
|
||||
type: GENERIC_RELOC_VANILLA
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: false
|
||||
symbol: 2
|
||||
- offset: 0x0000000F
|
||||
type: GENERIC_RELOC_VANILLA
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 2
|
||||
- offset: 0x0000000C
|
||||
type: GENERIC_RELOC_VANILLA
|
||||
length: 1
|
||||
pc-rel: true
|
||||
extern: true
|
||||
symbol: 2
|
||||
- offset: 0x00000006
|
||||
type: GENERIC_RELOC_VANILLA
|
||||
length: 2
|
||||
pc-rel: true
|
||||
extern: true
|
||||
symbol: 2
|
||||
- offset: 0x00000001
|
||||
type: GENERIC_RELOC_VANILLA
|
||||
length: 2
|
||||
pc-rel: true
|
||||
extern: true
|
||||
symbol: 2
|
||||
- segment: __DATA
|
||||
section: __data
|
||||
type: S_REGULAR
|
||||
attributes: [ ]
|
||||
address: 0x0000000000000024
|
||||
content: [ 0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xFF, 0xFF,
|
||||
0xD7, 0xFF, 0xFF, 0xFF ]
|
||||
relocations:
|
||||
- offset: 0x00000008
|
||||
scattered: true
|
||||
type: GENERIC_RELOC_LOCAL_SECTDIFF
|
||||
length: 2
|
||||
pc-rel: false
|
||||
value: 0x00000000
|
||||
- offset: 0x00000000
|
||||
scattered: true
|
||||
type: GENERIC_RELOC_PAIR
|
||||
length: 2
|
||||
pc-rel: false
|
||||
value: 0x0000002C
|
||||
- offset: 0x00000004
|
||||
scattered: true
|
||||
type: GENERIC_RELOC_LOCAL_SECTDIFF
|
||||
length: 2
|
||||
pc-rel: false
|
||||
value: 0x00000000
|
||||
- offset: 0x00000000
|
||||
scattered: true
|
||||
type: GENERIC_RELOC_PAIR
|
||||
length: 2
|
||||
pc-rel: false
|
||||
value: 0x00000028
|
||||
- offset: 0x00000000
|
||||
type: GENERIC_RELOC_VANILLA
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 2
|
||||
local-symbols:
|
||||
- name: _test
|
||||
type: N_SECT
|
||||
sect: 1
|
||||
value: 0x0000000000000000
|
||||
- name: _x
|
||||
type: N_SECT
|
||||
sect: 2
|
||||
value: 0x0000000000000024
|
||||
undefined-symbols:
|
||||
- name: _undef
|
||||
type: N_UNDF
|
||||
scope: [ N_EXT ]
|
||||
value: 0x0000000000000000
|
||||
...
|
||||
|
||||
# CHECK: defined-atoms:
|
||||
# CHECK: - name: _x
|
||||
# CHECK: type: data
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: pointer32
|
||||
# CHECK: offset: 0
|
||||
# CHECK: target: _undef
|
||||
# CHECK: - kind: delta32
|
||||
# CHECK: offset: 4
|
||||
# CHECK: target: _test
|
||||
# CHECK: - kind: delta32
|
||||
# CHECK: offset: 8
|
||||
# CHECK: target: _test
|
||||
# CHECK: addend: 3
|
||||
# CHECK: - name: _test
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: branch32
|
||||
# CHECK: offset: 1
|
||||
# CHECK: target: _undef
|
||||
# CHECK-NOT: addend:
|
||||
# CHECK: - kind: branch32
|
||||
# CHECK: offset: 6
|
||||
# CHECK: target: _undef
|
||||
# CHECK: addend: 2
|
||||
# CHECK: - kind: branch16
|
||||
# CHECK: offset: 12
|
||||
# CHECK: target: _undef
|
||||
# CHECK: - kind: abs32
|
||||
# CHECK: offset: 15
|
||||
# CHECK: target: _undef
|
||||
# CHECK: - kind: abs32
|
||||
# CHECK: offset: 20
|
||||
# CHECK: target: _x
|
||||
# CHECK: - kind: funcRel32
|
||||
# CHECK: offset: 26
|
||||
# CHECK: target: _x
|
||||
# CHECK: addend: -14
|
||||
# CHECK: - kind: funcRel32
|
||||
# CHECK: offset: 32
|
||||
# CHECK: target: _x
|
||||
# CHECK: addend: -10
|
||||
|
Loading…
Reference in New Issue
Block a user