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) {
|
inline uint32_t read32(bool swap, uint32_t value) {
|
||||||
return (swap ? getSwappedBytes(value) : value);
|
return (swap ? getSwappedBytes(value) : value);
|
||||||
|
@ -438,10 +438,25 @@ std::error_code convertRelocs(const Section §ion,
|
|||||||
if (sectIndex > normalizedFile.sections.size())
|
if (sectIndex > normalizedFile.sections.size())
|
||||||
return make_dynamic_error_code(Twine("out of range section "
|
return make_dynamic_error_code(Twine("out of range section "
|
||||||
"index (") + Twine(sectIndex) + ")");
|
"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;
|
uint32_t offsetInTarget;
|
||||||
uint64_t offsetInSect = addr - sect.address;
|
uint64_t offsetInSect = addr - sect->address;
|
||||||
*atom = file.findAtomCoveringAddress(sect, offsetInSect, &offsetInTarget);
|
*atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
|
||||||
*addend = offsetInTarget;
|
*addend = offsetInTarget;
|
||||||
return std::error_code();
|
return std::error_code();
|
||||||
};
|
};
|
||||||
@ -534,7 +549,7 @@ std::error_code convertRelocs(const Section §ion,
|
|||||||
+ " (r_address=" + Twine::utohexstr(reloc.offset)
|
+ " (r_address=" + Twine::utohexstr(reloc.offset)
|
||||||
+ ", r_type=" + Twine(reloc.type)
|
+ ", r_type=" + Twine(reloc.type)
|
||||||
+ ", r_extern=" + Twine(reloc.isExtern)
|
+ ", r_extern=" + Twine(reloc.isExtern)
|
||||||
+ ", r_length=" + Twine(reloc.length)
|
+ ", r_length=" + Twine((int)reloc.length)
|
||||||
+ ", r_pcrel=" + Twine(reloc.pcRel)
|
+ ", r_pcrel=" + Twine(reloc.pcRel)
|
||||||
+ (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
|
+ (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
|
||||||
: (Twine(", r_scattered=1, r_value=")
|
: (Twine(", r_scattered=1, r_value=")
|
||||||
@ -542,7 +557,17 @@ std::error_code convertRelocs(const Section §ion,
|
|||||||
+ ")" );
|
+ ")" );
|
||||||
} else {
|
} else {
|
||||||
// Instantiate an lld::Reference object and add to its atom.
|
// 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();
|
return std::error_code();
|
||||||
@ -580,7 +605,8 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TEMP BEGIN: until all KindHandlers switched to new interface.
|
// 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));
|
return std::unique_ptr<File>(std::move(file));
|
||||||
// TEMP END
|
// TEMP END
|
||||||
|
|
||||||
|
@ -76,6 +76,23 @@ KindHandler::RelocPattern KindHandler::relocPattern(const Relocation &reloc) {
|
|||||||
return result;
|
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) {
|
bool KindHandler::isPairedReloc(const Relocation &reloc) {
|
||||||
llvm_unreachable("abstract");
|
llvm_unreachable("abstract");
|
||||||
}
|
}
|
||||||
@ -169,13 +186,6 @@ bool KindHandler_x86_64::isPairedReloc(const Relocation &reloc) {
|
|||||||
return (reloc.type == X86_64_RELOC_SUBTRACTOR);
|
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
|
Reference::KindValue
|
||||||
KindHandler_x86_64::kindFromReloc(const Relocation &reloc) {
|
KindHandler_x86_64::kindFromReloc(const Relocation &reloc) {
|
||||||
@ -400,29 +410,166 @@ KindHandler_x86::~KindHandler_x86() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Registry::KindStrings KindHandler_x86::kindStrings[] = {
|
const Registry::KindStrings KindHandler_x86::kindStrings[] = {
|
||||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_BRANCH32),
|
LLD_KIND_STRING_ENTRY(invalid),
|
||||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_ABS32),
|
LLD_KIND_STRING_ENTRY(branch32),
|
||||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_FUNC_REL32),
|
LLD_KIND_STRING_ENTRY(branch16),
|
||||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_POINTER32),
|
LLD_KIND_STRING_ENTRY(abs32),
|
||||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_LAZY_TARGET),
|
LLD_KIND_STRING_ENTRY(funcRel32),
|
||||||
LLD_KIND_STRING_ENTRY(LLD_X86_RELOC_LAZY_IMMEDIATE),
|
LLD_KIND_STRING_ENTRY(pointer32),
|
||||||
|
LLD_KIND_STRING_ENTRY(delta32),
|
||||||
|
LLD_KIND_STRING_ENTRY(lazyPointer),
|
||||||
|
LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
|
||||||
LLD_KIND_STRING_END
|
LLD_KIND_STRING_END
|
||||||
};
|
};
|
||||||
|
|
||||||
bool KindHandler_x86::isCallSite(const Reference &ref) {
|
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) {
|
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) {
|
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) {
|
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,
|
void KindHandler_x86::applyFixup(Reference::KindNamespace ns,
|
||||||
|
@ -126,6 +126,10 @@ protected:
|
|||||||
};
|
};
|
||||||
static RelocPattern relocPattern(const normalized::Relocation &reloc);
|
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 isPointer(const Reference &) override;
|
||||||
bool isLazyImmediate(const Reference &) override;
|
bool isLazyImmediate(const Reference &) override;
|
||||||
bool isLazyTarget(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,
|
Reference::KindValue kindValue, uint64_t addend,
|
||||||
uint8_t *location, uint64_t fixupAddress,
|
uint8_t *location, uint64_t fixupAddress,
|
||||||
uint64_t targetAddress) override;
|
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 {
|
class KindHandler_arm : public KindHandler {
|
||||||
public:
|
public:
|
||||||
static const Registry::KindStrings kindStrings[];
|
static const Registry::KindStrings kindStrings[];
|
||||||
|
@ -39,7 +39,7 @@ sections:
|
|||||||
length: 2
|
length: 2
|
||||||
pc-rel: false
|
pc-rel: false
|
||||||
extern: true
|
extern: true
|
||||||
symbol: 1
|
symbol: 0
|
||||||
- offset: 0x00000008
|
- offset: 0x00000008
|
||||||
type: GENERIC_RELOC_VANILLA
|
type: GENERIC_RELOC_VANILLA
|
||||||
length: 2
|
length: 2
|
||||||
@ -51,7 +51,7 @@ sections:
|
|||||||
length: 2
|
length: 2
|
||||||
pc-rel: false
|
pc-rel: false
|
||||||
extern: true
|
extern: true
|
||||||
symbol: 1
|
symbol: 0
|
||||||
undefined-symbols:
|
undefined-symbols:
|
||||||
- name: ___CFConstantStringClassReference
|
- name: ___CFConstantStringClassReference
|
||||||
type: N_UNDF
|
type: N_UNDF
|
||||||
@ -60,19 +60,35 @@ undefined-symbols:
|
|||||||
...
|
...
|
||||||
|
|
||||||
# CHECK: defined-atoms:
|
# CHECK: defined-atoms:
|
||||||
# CHECK: - scope: hidden
|
# CHECK: - ref-name: [[STR1:L[L0-9]+]]
|
||||||
|
# CHECK: scope: hidden
|
||||||
# CHECK: type: c-string
|
# CHECK: type: c-string
|
||||||
# CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ]
|
# CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ]
|
||||||
# CHECK: merge: by-content
|
# CHECK: merge: by-content
|
||||||
# CHECK: - scope: hidden
|
# CHECK: - ref-name: [[STR2:L[L0-9]+]]
|
||||||
|
# CHECK: scope: hidden
|
||||||
# CHECK: type: c-string
|
# CHECK: type: c-string
|
||||||
# CHECK: content: [ 74, 68, 65, 72, 65, 00 ]
|
# CHECK: content: [ 74, 68, 65, 72, 65, 00 ]
|
||||||
# CHECK: merge: by-content
|
# CHECK: merge: by-content
|
||||||
# CHECK: - scope: hidden
|
# CHECK: - scope: hidden
|
||||||
# CHECK: type: cfstring
|
# CHECK: type: cfstring
|
||||||
# CHECK: merge: by-content
|
# 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: - scope: hidden
|
||||||
# CHECK: type: cfstring
|
# CHECK: type: cfstring
|
||||||
# CHECK: merge: by-content
|
# 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:undefined-atoms:
|
||||||
# CHECK: - name: ___CFConstantStringClassReference
|
# CHECK: - name: ___CFConstantStringClassReference
|
||||||
|
@ -71,11 +71,13 @@ undefined-symbols:
|
|||||||
|
|
||||||
|
|
||||||
# CHECK:defined-atoms:
|
# CHECK:defined-atoms:
|
||||||
# CHECK: - scope: hidden
|
# CHECK: - ref-name: [[GOT1:L[L0-9]+]]
|
||||||
|
# CHECK: scope: hidden
|
||||||
# CHECK: type: got
|
# CHECK: type: got
|
||||||
# CHECK: content: [ 00, 00, 00, 00 ]
|
# CHECK: content: [ 00, 00, 00, 00 ]
|
||||||
# CHECK: merge: by-content
|
# CHECK: merge: by-content
|
||||||
# CHECK: - scope: hidden
|
# CHECK: - ref-name: [[GOT2:L[L0-9]+]]
|
||||||
|
# CHECK: scope: hidden
|
||||||
# CHECK: type: got
|
# CHECK: type: got
|
||||||
# CHECK: content: [ 00, 00, 00, 00 ]
|
# CHECK: content: [ 00, 00, 00, 00 ]
|
||||||
# CHECK: merge: by-content
|
# CHECK: merge: by-content
|
||||||
@ -83,6 +85,13 @@ undefined-symbols:
|
|||||||
# CHECK: scope: global
|
# CHECK: scope: global
|
||||||
# CHECK: content: [ 55, 89, E5, E8, 00, 00, 00, 00, 59, 8D, 81, 14,
|
# 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: 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: - name: _foo
|
||||||
# CHECK: content: [ 55, 89, E5, 5D, C3 ]
|
# 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