summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2014-07-02 23:52:22 +0000
committerNick Kledzik <kledzik@apple.com>2014-07-02 23:52:22 +0000
commitde0860aae4b2723f1a66005a07de2ea244faa082 (patch)
tree3123be3233d76ed8c45053a26f5271e4942bf303
parentbcb70eee1a38a6676ef9f9aa60575df2cec23219 (diff)
downloadbcm5719-llvm-de0860aae4b2723f1a66005a07de2ea244faa082.tar.gz
bcm5719-llvm-de0860aae4b2723f1a66005a07de2ea244faa082.zip
[mach-o] add parsing of x86 relocations
llvm-svn: 212239
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h3
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp38
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp191
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.h57
-rw-r--r--lld/test/mach-o/parse-cfstring32.yaml24
-rw-r--r--lld/test/mach-o/parse-non-lazy-pointers.yaml13
-rw-r--r--lld/test/mach-o/parse-relocs-x86.yaml190
7 files changed, 480 insertions, 36 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
index 8041fc4ea1d..5a61314b3d6 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
@@ -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);
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 5846c3e12e9..8fb834d8b7d 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -438,10 +438,25 @@ std::error_code convertRelocs(const Section &section,
if (sectIndex > normalizedFile.sections.size())
return make_dynamic_error_code(Twine("out of range section "
"index (") + Twine(sectIndex) + ")");
- const Section &sect = 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 &section,
+ " (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 &section,
+ ")" );
} 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
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
index fe9caec5c7d..28cacf307ab 100644
--- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
@@ -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,
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
index 994c384f099..46bf585dedb 100644
--- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
@@ -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[];
diff --git a/lld/test/mach-o/parse-cfstring32.yaml b/lld/test/mach-o/parse-cfstring32.yaml
index 8f4b041655a..657e733a779 100644
--- a/lld/test/mach-o/parse-cfstring32.yaml
+++ b/lld/test/mach-o/parse-cfstring32.yaml
@@ -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
diff --git a/lld/test/mach-o/parse-non-lazy-pointers.yaml b/lld/test/mach-o/parse-non-lazy-pointers.yaml
index afdf2e68ace..0b0ec5cf36e 100644
--- a/lld/test/mach-o/parse-non-lazy-pointers.yaml
+++ b/lld/test/mach-o/parse-non-lazy-pointers.yaml
@@ -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 ]
diff --git a/lld/test/mach-o/parse-relocs-x86.yaml b/lld/test/mach-o/parse-relocs-x86.yaml
new file mode 100644
index 00000000000..c9feb244d75
--- /dev/null
+++ b/lld/test/mach-o/parse-relocs-x86.yaml
@@ -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
+
OpenPOWER on IntegriCloud