From 4576c115ac8bdca6122ba6b35b5c9dff624973f3 Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Fri, 4 Jul 2014 00:11:09 +0000 Subject: [PATCH] [mach-o] Add parsing of arm/thumb relocations This converts the very complicated mach-o arm relocations into the simple Reference Kinds in lld. The next patch will use the internal Reference kinds to fix up arm/thumb code. llvm-svn: 212306 --- lld/lib/ReaderWriter/MachO/Atoms.h | 13 +- lld/lib/ReaderWriter/MachO/File.h | 13 +- .../MachO/MachONormalizedFileToAtoms.cpp | 15 +- lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp | 510 +++++++++++-- lld/lib/ReaderWriter/MachO/ReferenceKinds.h | 72 +- lld/test/mach-o/parse-arm-relocs.yaml | 791 +++++++++++++++++++++ 6 files changed, 1319 insertions(+), 95 deletions(-) create mode 100644 lld/test/mach-o/parse-arm-relocs.yaml diff --git a/lld/lib/ReaderWriter/MachO/Atoms.h b/lld/lib/ReaderWriter/MachO/Atoms.h index 80cad29..13d546f 100644 --- a/lld/lib/ReaderWriter/MachO/Atoms.h +++ b/lld/lib/ReaderWriter/MachO/Atoms.h @@ -17,10 +17,10 @@ namespace mach_o { class MachODefinedAtom : public SimpleDefinedAtom { public: MachODefinedAtom(const File &f, const StringRef name, Scope scope, - ContentType type, Merge merge, + ContentType type, Merge merge, bool thumb, const ArrayRef content) : SimpleDefinedAtom(f), _name(name), _content(content), - _contentType(type), _scope(scope), _merge(merge) {} + _contentType(type), _scope(scope), _merge(merge), _thumb(thumb) {} // Constructor for zero-fill content MachODefinedAtom(const File &f, const StringRef name, Scope scope, @@ -28,7 +28,7 @@ public: : SimpleDefinedAtom(f), _name(name), _content(ArrayRef(nullptr, size)), _contentType(DefinedAtom::typeZeroFill), - _scope(scope), _merge(mergeNo) {} + _scope(scope), _merge(mergeNo), _thumb(false) {} uint64_t size() const override { return _content.size(); } @@ -53,6 +53,8 @@ public: return _content; } + bool isThumb() const { return _thumb; } + void addReference(uint32_t offsetInAtom, uint16_t relocType, const Atom *target, Reference::Addend addend, Reference::KindArch arch = Reference::KindArch::x86_64, @@ -66,15 +68,16 @@ private: const ContentType _contentType; const Scope _scope; const Merge _merge; + const bool _thumb; }; class MachODefinedCustomSectionAtom : public MachODefinedAtom { public: MachODefinedCustomSectionAtom(const File &f, const StringRef name, Scope scope, ContentType type, Merge merge, - const ArrayRef content, + bool thumb, const ArrayRef content, StringRef sectionName) - : MachODefinedAtom(f, name, scope, type, merge, content), + : MachODefinedAtom(f, name, scope, type, merge, thumb, content), _sectionName(sectionName) {} SectionChoice sectionChoice() const override { diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h index d50e3ff..0cafc4c 100644 --- a/lld/lib/ReaderWriter/MachO/File.h +++ b/lld/lib/ReaderWriter/MachO/File.h @@ -30,7 +30,7 @@ public: void addDefinedAtom(StringRef name, Atom::Scope scope, DefinedAtom::ContentType type, DefinedAtom::Merge merge, - uint64_t sectionOffset, uint64_t contentSize, + uint64_t sectionOffset, uint64_t contentSize, bool thumb, bool copyRefs, const Section *inSection) { assert(sectionOffset+contentSize <= inSection->content.size()); ArrayRef content = inSection->content.slice(sectionOffset, @@ -41,14 +41,14 @@ public: content = content.copy(_allocator); } MachODefinedAtom *atom = - new (_allocator) MachODefinedAtom(*this, name, scope, type, merge, - content); + new (_allocator) MachODefinedAtom(*this, name, scope, type, merge, + thumb, content); addAtomForSection(inSection, atom, sectionOffset); } void addDefinedAtomInCustomSection(StringRef name, Atom::Scope scope, DefinedAtom::ContentType type, DefinedAtom::Merge merge, - uint64_t sectionOffset, uint64_t contentSize, + bool thumb, uint64_t sectionOffset, uint64_t contentSize, StringRef sectionName, bool copyRefs, const Section *inSection) { assert(sectionOffset+contentSize <= inSection->content.size()); @@ -61,8 +61,9 @@ public: sectionName = sectionName.copy(_allocator); } MachODefinedCustomSectionAtom *atom = - new (_allocator) MachODefinedCustomSectionAtom(*this, name, scope, type, - merge, content, sectionName); + new (_allocator) MachODefinedCustomSectionAtom(*this, name, scope, type, + merge, thumb, content, + sectionName); addAtomForSection(inSection, atom, sectionOffset); } diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index af7c244..7e8f6c3 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -231,6 +231,7 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion, } else { DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF) ? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo; + bool thumb = (symbolDescFlags & N_ARM_THUMB_DEF); if (atomType == DefinedAtom::typeUnknown) { // Mach-O needs a segment and section name. Concatentate those two // with a / seperator (e.g. "seg/sect") to fit into the lld model @@ -238,15 +239,15 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion, std::string segSectName = section.segmentName.str() + "/" + section.sectionName.str(); file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType, - merge, offset, size, segSectName, true, - §ion); + merge, thumb,offset, size, segSectName, + true, §ion); } else { if ((atomType == lld::DefinedAtom::typeCode) && (symbolDescFlags & N_SYMBOL_RESOLVER)) { atomType = lld::DefinedAtom::typeResolver; } file.addDefinedAtom(symbolName, symbolScope, atomType, merge, - offset, size, copyRefs, §ion); + offset, size, thumb, copyRefs, §ion); } } } @@ -418,7 +419,7 @@ std::error_code processSection(DefinedAtom::ContentType atomType, "not zero terminated."); } file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size, - copyRefs, §ion); + false, copyRefs, §ion); offset += size; } } @@ -614,12 +615,6 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, } } - // TEMP BEGIN: until all KindHandlers switched to new interface. - if ((normalizedFile.arch != lld::MachOLinkingContext::arch_x86_64) && - (normalizedFile.arch != lld::MachOLinkingContext::arch_x86)) - return std::unique_ptr(std::move(file)); - // TEMP END - // Convert mach-o relocations to References std::unique_ptr handler = KindHandler::create(normalizedFile.arch); diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp index 1d06bed..da15cfe 100644 --- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp +++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp @@ -10,6 +10,7 @@ #include "ReferenceKinds.h" #include "MachONormalizedFileBinaryUtils.h" +#include "Atoms.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" @@ -93,37 +94,6 @@ int64_t KindHandler::readS64(bool swap, const uint8_t *addr) { } -bool KindHandler::isPairedReloc(const Relocation &reloc) { - llvm_unreachable("abstract"); -} - -std::error_code -KindHandler::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) { - llvm_unreachable("abstract"); -} - -std::error_code -KindHandler::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) { - llvm_unreachable("abstract"); -} - //===----------------------------------------------------------------------===// // KindHandler_x86_64 //===----------------------------------------------------------------------===// @@ -564,7 +534,7 @@ KindHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1, uint32_t ta = fromAddress + value - toAddress; *addend = ta - offsetInFrom; } else { - *addend= fromAddress + value - toAddress; + *addend = fromAddress + value - toAddress; } return std::error_code(); break; @@ -622,36 +592,447 @@ KindHandler_arm::~KindHandler_arm() { } const Registry::KindStrings KindHandler_arm::kindStrings[] = { - LLD_KIND_STRING_ENTRY(ARM_RELOC_BR24), - LLD_KIND_STRING_ENTRY(ARM_THUMB_RELOC_BR22), - LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_THUMB_ABS_LO16), - LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_THUMB_ABS_HI16), - LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_THUMB_REL_LO16), - LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_THUMB_REL_HI16), - LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_ABS32), - LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_POINTER32), - LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_LAZY_TARGET), - LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_LAZY_IMMEDIATE), + LLD_KIND_STRING_ENTRY(thumb_b22), + LLD_KIND_STRING_ENTRY(thumb_movw), + LLD_KIND_STRING_ENTRY(thumb_movt), + LLD_KIND_STRING_ENTRY(thumb_movw_funcRel), + LLD_KIND_STRING_ENTRY(thumb_movt_funcRel), + LLD_KIND_STRING_ENTRY(arm_b24), + LLD_KIND_STRING_ENTRY(arm_movw), + LLD_KIND_STRING_ENTRY(arm_movt), + LLD_KIND_STRING_ENTRY(arm_movw_funcRel), + LLD_KIND_STRING_ENTRY(arm_movt_funcRel), + 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_arm::isCallSite(const Reference &ref) { - return (ref.kindValue() == ARM_THUMB_RELOC_BR22) || - (ref.kindValue() == ARM_RELOC_BR24); + return (ref.kindValue() == thumb_b22) || + (ref.kindValue() == arm_b24); } bool KindHandler_arm::isPointer(const Reference &ref) { - return (ref.kindValue() == LLD_ARM_RELOC_POINTER32); + return (ref.kindValue() == pointer32); } bool KindHandler_arm::isLazyImmediate(const Reference &ref) { - return (ref.kindValue() == LLD_ARM_RELOC_LAZY_IMMEDIATE); + return (ref.kindValue() == lazyImmediateLocation); } bool KindHandler_arm::isLazyTarget(const Reference &ref) { - return (ref.kindValue() == LLD_ARM_RELOC_LAZY_TARGET); + return (ref.kindValue() == lazyPointer); +} + +bool KindHandler_arm::isPairedReloc(const Relocation &reloc) { + switch (reloc.type) { + case ARM_RELOC_SECTDIFF: + case ARM_RELOC_LOCAL_SECTDIFF: + case ARM_RELOC_HALF_SECTDIFF: + case ARM_RELOC_HALF: + return true; + default: + return false; + } +} + + +int32_t KindHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction) { + uint32_t s = (instruction >> 10) & 0x1; + uint32_t j1 = (instruction >> 29) & 0x1; + uint32_t j2 = (instruction >> 27) & 0x1; + uint32_t imm10 = instruction & 0x3FF; + uint32_t imm11 = (instruction >> 16) & 0x7FF; + uint32_t i1 = (j1 == s); + uint32_t i2 = (j2 == s); + uint32_t dis = (s << 24) | (i1 << 23) | (i2 << 22) + | (imm10 << 12) | (imm11 << 1); + int32_t sdis = dis; + if (s) + return (sdis | 0xFE000000); + else + return sdis; +} + +int32_t KindHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) { + // Sign-extend imm24 + int32_t displacement = (instruction & 0x00FFFFFF) << 2; + if ( (displacement & 0x02000000) != 0 ) + displacement |= 0xFC000000; + // If this is BLX and H bit set, add 2. + if ((instruction & 0xFF000000) == 0xFB000000) + displacement += 2; + return displacement; +} + + +uint16_t KindHandler_arm::getWordFromThumbMov(uint32_t instruction) { + uint32_t i = ((instruction & 0x00000400) >> 10); + uint32_t imm4 = (instruction & 0x0000000F); + uint32_t imm3 = ((instruction & 0x70000000) >> 28); + uint32_t imm8 = ((instruction & 0x00FF0000) >> 16); + return (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; +} + +uint16_t KindHandler_arm::getWordFromArmMov(uint32_t instruction) { + uint32_t imm4 = ((instruction & 0x000F0000) >> 16); + uint32_t imm12 = (instruction & 0x00000FFF); + return (imm4 << 12) | imm12; +} + +uint32_t KindHandler_arm::clearThumbBit(uint32_t value, const Atom* target) { + // The assembler often adds one to the address of a thumb function. + // We need to undo that so it does not look like an addend. + if (value & 1) { + if (isa(target)) { + const MachODefinedAtom *machoTarget = reinterpret_cast< + const MachODefinedAtom*>(target); + if (machoTarget->isThumb()) + value &= -2; // mask off thumb-bit + } + } + return value; } +std::error_code +KindHandler_arm::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; + const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; + uint64_t targetAddress; + uint32_t instruction = readU32(swap, fixupContent); + int32_t displacement; + switch (relocPattern(reloc)) { + case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4: + // ex: bl _foo (and _foo is undefined) + *kind = thumb_b22; + if (E ec = atomFromSymbolIndex(reloc.symbol, target)) + return ec; + // Instruction contains branch to addend. + displacement = getDisplacementFromThumbBranch(instruction); + *addend = fixupAddress + 4 + displacement; + return std::error_code(); + case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4: + // ex: bl _foo (and _foo is defined) + *kind = thumb_b22; + displacement = getDisplacementFromThumbBranch(instruction); + targetAddress = fixupAddress + 4 + displacement; + return atomFromAddress(reloc.symbol, targetAddress, target, addend); + case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4: + // ex: bl _foo+4 (and _foo is defined) + *kind = thumb_b22; + displacement = getDisplacementFromThumbBranch(instruction); + targetAddress = fixupAddress + 4 + displacement; + if (E ec = atomFromAddress(0, reloc.value, target, addend)) + return ec; + // reloc.value is target atom's address. Instruction contains branch + // to atom+addend. + *addend += (targetAddress - reloc.value); + return std::error_code(); + case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4: + // ex: bl _foo (and _foo is undefined) + *kind = arm_b24; + if (E ec = atomFromSymbolIndex(reloc.symbol, target)) + return ec; + // Instruction contains branch to addend. + displacement = getDisplacementFromArmBranch(instruction); + *addend = fixupAddress + 8 + displacement; + return std::error_code(); + case ARM_RELOC_BR24 | rPcRel | rLength4: + // ex: bl _foo (and _foo is defined) + *kind = arm_b24; + displacement = getDisplacementFromArmBranch(instruction); + targetAddress = fixupAddress + 8 + displacement; + return atomFromAddress(reloc.symbol, targetAddress, target, addend); + case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4: + // ex: bl _foo+4 (and _foo is defined) + *kind = arm_b24; + displacement = getDisplacementFromArmBranch(instruction); + targetAddress = fixupAddress + 8 + displacement; + if (E ec = atomFromAddress(0, reloc.value, target, addend)) + return ec; + // reloc.value is target atom's address. Instruction contains branch + // to atom+addend. + *addend += (targetAddress - reloc.value); + return std::error_code(); + case ARM_RELOC_VANILLA | rExtern | rLength4: + // ex: .long _foo (and _foo is undefined) + *kind = pointer32; + if (E ec = atomFromSymbolIndex(reloc.symbol, target)) + return ec; + *addend = instruction; + return std::error_code(); + case ARM_RELOC_VANILLA | rLength4: + // ex: .long _foo (and _foo is defined) + *kind = pointer32; + if (E ec = atomFromAddress(reloc.symbol, instruction, target, addend)) + return ec; + *addend = clearThumbBit((uint32_t)*addend, *target); + return std::error_code(); + case ARM_RELOC_VANILLA | rScattered | rLength4: + // ex: .long _foo+a (and _foo is defined) + *kind = pointer32; + if (E ec = atomFromAddress(0, reloc.value, target, addend)) + return ec; + *addend += (clearThumbBit(instruction, *target) - reloc.value); + return std::error_code(); + default: + return make_dynamic_error_code(Twine("unsupported arm relocation type")); + } + return std::error_code(); +} + + +std::error_code +KindHandler_arm::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) { + bool pointerDiff = false; + bool funcRel; + bool top; + bool thumbReloc; + switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) { + case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLength4) << 16 | + ARM_RELOC_PAIR | rScattered | rLength4): + // ex: movw r1, :lower16:(_x-L1) [thumb mode] + *kind = thumb_movw_funcRel; + funcRel = true; + top = false; + thumbReloc = true; + break; + case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLength8) << 16 | + ARM_RELOC_PAIR | rScattered | rLength8): + // ex: movt r1, :upper16:(_x-L1) [thumb mode] + *kind = thumb_movt_funcRel; + funcRel = true; + top = true; + thumbReloc = true; + break; + case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLength1) << 16 | + ARM_RELOC_PAIR | rScattered | rLength1): + // ex: movw r1, :lower16:(_x-L1) [arm mode] + *kind = arm_movw_funcRel; + funcRel = true; + top = false; + thumbReloc = false; + break; + case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLength2) << 16 | + ARM_RELOC_PAIR | rScattered | rLength2): + // ex: movt r1, :upper16:(_x-L1) [arm mode] + *kind = arm_movt_funcRel; + funcRel = true; + top = true; + thumbReloc = false; + break; + case ((ARM_RELOC_HALF | rLength4) << 16 | + ARM_RELOC_PAIR | rLength4): + // ex: movw r1, :lower16:_x [thumb mode] + *kind = thumb_movw; + funcRel = false; + top = false; + thumbReloc = true; + break; + case ((ARM_RELOC_HALF | rLength8) << 16 | + ARM_RELOC_PAIR | rLength8): + // ex: movt r1, :upper16:_x [thumb mode] + *kind = thumb_movt; + funcRel = false; + top = true; + thumbReloc = true; + break; + case ((ARM_RELOC_HALF | rLength1) << 16 | + ARM_RELOC_PAIR | rLength1): + // ex: movw r1, :lower16:_x [arm mode] + *kind = arm_movw; + funcRel = false; + top = false; + thumbReloc = false; + break; + case ((ARM_RELOC_HALF | rLength2) << 16 | + ARM_RELOC_PAIR | rLength2): + // ex: movt r1, :upper16:_x [arm mode] + *kind = arm_movt; + funcRel = false; + top = true; + thumbReloc = false; + break; + case ((ARM_RELOC_HALF | rScattered | rLength4) << 16 | + ARM_RELOC_PAIR | rLength4): + // ex: movw r1, :lower16:_x+a [thumb mode] + *kind = thumb_movw; + funcRel = false; + top = false; + thumbReloc = true; + break; + case ((ARM_RELOC_HALF | rScattered | rLength8) << 16 | + ARM_RELOC_PAIR | rLength8): + // ex: movt r1, :upper16:_x+a [thumb mode] + *kind = thumb_movt; + funcRel = false; + top = true; + thumbReloc = true; + break; + case ((ARM_RELOC_HALF | rScattered | rLength1) << 16 | + ARM_RELOC_PAIR | rLength1): + // ex: movw r1, :lower16:_x+a [arm mode] + *kind = arm_movw; + funcRel = false; + top = false; + thumbReloc = false; + break; + case ((ARM_RELOC_HALF | rScattered | rLength2) << 16 | + ARM_RELOC_PAIR | rLength2): + // ex: movt r1, :upper16:_x+a [arm mode] + *kind = arm_movt; + funcRel = false; + top = true; + thumbReloc = false; + break; + case ((ARM_RELOC_HALF | rExtern | rLength4) << 16 | + ARM_RELOC_PAIR | rLength4): + // ex: movw r1, :lower16:_undef [thumb mode] + *kind = thumb_movw; + funcRel = false; + top = false; + thumbReloc = true; + break; + case ((ARM_RELOC_HALF | rExtern | rLength8) << 16 | + ARM_RELOC_PAIR | rLength8): + // ex: movt r1, :upper16:_undef [thumb mode] + *kind = thumb_movt; + funcRel = false; + top = true; + thumbReloc = true; + break; + case ((ARM_RELOC_HALF | rExtern | rLength1) << 16 | + ARM_RELOC_PAIR | rLength1): + // ex: movw r1, :lower16:_undef [arm mode] + *kind = arm_movw; + funcRel = false; + top = false; + thumbReloc = false; + break; + case ((ARM_RELOC_HALF | rExtern | rLength2) << 16 | + ARM_RELOC_PAIR | rLength2): + // ex: movt r1, :upper16:_undef [arm mode] + *kind = arm_movt; + funcRel = false; + top = true; + thumbReloc = false; + break; + case ((ARM_RELOC_SECTDIFF | rScattered | rLength4) << 16 | + ARM_RELOC_PAIR | rScattered | rLength4): + case ((ARM_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 | + ARM_RELOC_PAIR | rScattered | rLength4): + // ex: .long _foo - . + pointerDiff = true; + break; + default: + return make_dynamic_error_code(Twine("unsupported arm relocation pair")); + } + const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; + std::error_code ec; + uint32_t instruction = readU32(swap, fixupContent); + uint32_t value; + uint32_t fromAddress; + uint32_t toAddress; + uint16_t instruction16; + uint16_t other16; + const lld::Atom *fromTarget; + Reference::Addend offsetInTo; + Reference::Addend offsetInFrom; + if (pointerDiff) { + toAddress = reloc1.value; + fromAddress = reloc2.value; + 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 = delta32; + value = clearThumbBit(instruction, *target); + *addend = value - (toAddress - fromAddress); + } else if (funcRel) { + toAddress = reloc1.value; + fromAddress = reloc2.value; + 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("ARM_RELOC_HALF_SECTDIFF relocation " + "where subtrahend label is not in atom")); + other16 = (reloc2.offset & 0xFFFF); + if (thumbReloc) + instruction16 = getWordFromThumbMov(instruction); + else + instruction16 = getWordFromArmMov(instruction); + if (top) + value = (instruction16 << 16) | other16; + else + value = (other16 << 16) | instruction16; + value = clearThumbBit(value, *target); + int64_t ta = (int64_t)value - (toAddress - fromAddress); + *addend = ta - offsetInFrom; + return std::error_code(); + } else { + uint32_t sectIndex; + if (thumbReloc) + instruction16 = getWordFromThumbMov(instruction); + else + instruction16 = getWordFromArmMov(instruction); + other16 = (reloc2.offset & 0xFFFF); + if (top) + value = (instruction16 << 16) | other16; + else + value = (other16 << 16) | instruction16; + if (reloc1.isExtern) { + ec = atomFromSymbolIndex(reloc1.symbol, target); + if (ec) + return ec; + *addend = value; + } else { + if (reloc1.scattered) { + toAddress = reloc1.value; + sectIndex = 0; + } else { + toAddress = value; + sectIndex = reloc1.symbol; + } + ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo); + if (ec) + return ec; + *addend = value - toAddress; + } + } + + return std::error_code(); +} + + + void KindHandler_arm::applyFixup(Reference::KindNamespace ns, Reference::KindArch arch, Reference::KindValue kindValue, @@ -663,36 +1044,49 @@ void KindHandler_arm::applyFixup(Reference::KindNamespace ns, return; assert(arch == Reference::KindArch::ARM); //int32_t *loc32 = reinterpret_cast(location); + // FIXME: these writes may need a swap. switch (kindValue) { - case ARM_THUMB_RELOC_BR22: + case thumb_b22: + // FIXME + break; + case thumb_movw: + // FIXME + break; + case thumb_movt: // FIXME break; - case ARM_RELOC_BR24: + case thumb_movw_funcRel: // FIXME break; - case LLD_ARM_RELOC_THUMB_ABS_LO16: + case thumb_movt_funcRel: // FIXME break; - case LLD_ARM_RELOC_THUMB_ABS_HI16: + case arm_b24: // FIXME break; - case LLD_ARM_RELOC_THUMB_REL_LO16: + case arm_movw: // FIXME break; - case LLD_ARM_RELOC_THUMB_REL_HI16: + case arm_movt: // FIXME break; - case LLD_ARM_RELOC_ABS32: + case arm_movw_funcRel: // FIXME break; - case LLD_ARM_RELOC_POINTER32: + case arm_movt_funcRel: // FIXME break; - case LLD_ARM_RELOC_LAZY_TARGET: - case LLD_ARM_RELOC_LAZY_IMMEDIATE: + case pointer32: + // FIXME + break; + case delta32: + // FIXME + break; + case lazyPointer: + case lazyImmediateLocation: // do nothing break; - default: + case invalid: llvm_unreachable("invalid ARM Reference Kind"); break; } diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h index c2d265f..f8a48b2 100644 --- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h +++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h @@ -23,18 +23,6 @@ namespace lld { namespace mach_o { -// Additional Reference Kind values used internally. -enum { - LLD_ARM_RELOC_THUMB_ABS_LO16 = 100, // thumb movw of absolute address - LLD_ARM_RELOC_THUMB_ABS_HI16 = 101, // thumb movt of absolute address - LLD_ARM_RELOC_THUMB_REL_LO16 = 102, // thumb movw of (target - pc) - LLD_ARM_RELOC_THUMB_REL_HI16 = 103, // thumb movt of (target - pc) - LLD_ARM_RELOC_ABS32 = 104, // 32-bit constant pointer - LLD_ARM_RELOC_POINTER32 = 105, // 32-bit data pointer - LLD_ARM_RELOC_LAZY_TARGET = 106, - LLD_ARM_RELOC_LAZY_IMMEDIATE = 107, -}; - /// /// The KindHandler class is the abstract interface to Reference::Kind /// values for mach-o files. Particular Kind values (e.g. 3) has a different @@ -52,7 +40,7 @@ public: virtual bool isLazyTarget(const Reference &) = 0; /// Returns true if the specified relocation is paired to the next relocation. - virtual bool isPairedReloc(const normalized::Relocation &); + virtual bool isPairedReloc(const normalized::Relocation &) = 0; /// Prototype for a helper function. Given a sectionIndex and address, /// finds the atom and offset with that atom of that address. @@ -63,7 +51,7 @@ public: /// Prototype for a helper function. Given a symbolIndex, finds the atom /// representing that symbol. typedef std::function FindAtomBySymbolIndex; + const lld::Atom **)> FindAtomBySymbolIndex; /// Analyzes a relocation from a .o file and returns the info /// (kind, target, addend) needed to instantiate a Reference. @@ -78,7 +66,7 @@ public: FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, - Reference::Addend *addend); + Reference::Addend *addend) = 0; /// Analyzes a pair of relocations from a .o file and returns the info /// (kind, target, addend) needed to instantiate a Reference. @@ -94,7 +82,7 @@ public: FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, - Reference::Addend *addend); + Reference::Addend *addend) = 0; /// Fixup an atom when generating a final linked binary. virtual void applyFixup(Reference::KindNamespace ns, Reference::KindArch arch, @@ -278,11 +266,63 @@ public: bool isPointer(const Reference &) override; bool isLazyImmediate(const Reference &) override; bool isLazyTarget(const Reference &) override; + 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, uint64_t inAtomAddress) override; + +private: + enum : Reference::KindValue { + invalid, /// for error condition + + // Kinds found in mach-o .o files: + thumb_b22, /// ex: bl _foo + thumb_movw, /// ex: movw r1, :lower16:_foo + thumb_movt, /// ex: movt r1, :lower16:_foo + thumb_movw_funcRel, /// ex: movw r1, :lower16:(_foo-(L1+4)) + thumb_movt_funcRel, /// ex: movt r1, :upper16:(_foo-(L1+4)) + arm_b24, /// ex: bl _foo + arm_movw, /// ex: movw r1, :lower16:_foo + arm_movt, /// ex: movt r1, :lower16:_foo + arm_movw_funcRel, /// ex: movw r1, :lower16:(_foo-(L1+4)) + arm_movt_funcRel, /// ex: movt r1, :upper16:(_foo-(L1+4)) + 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. + }; + + int32_t getDisplacementFromThumbBranch(uint32_t instruction); + int32_t getDisplacementFromArmBranch(uint32_t instruction); + uint16_t getWordFromThumbMov(uint32_t instruction); + uint16_t getWordFromArmMov(uint32_t instruction); + uint32_t clearThumbBit(uint32_t value, const Atom* target); + }; } // namespace mach_o diff --git a/lld/test/mach-o/parse-arm-relocs.yaml b/lld/test/mach-o/parse-arm-relocs.yaml new file mode 100644 index 0000000..2deb89e --- /dev/null +++ b/lld/test/mach-o/parse-arm-relocs.yaml @@ -0,0 +1,791 @@ +# RUN: lld -flavor darwin -arch armv7 -r -print_atoms %s -o %t | FileCheck %s +# +# Test parsing of armv7 relocations. +# +# + +--- !mach-o +arch: armv7 +file-type: MH_OBJECT +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ] +has-UUID: false +OS: unknown +sections: + - segment: __TEXT + section: __text + type: S_REGULAR + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] + alignment: 2 + address: 0x0000000000000000 + content: [ 0x00, 0xF0, 0x4A, 0xF8, 0x00, 0xF0, 0x4A, 0xF8, + 0xFF, 0xF7, 0xFA, 0xFF, 0xFF, 0xF7, 0xFA, 0xFF, + 0x40, 0xF2, 0x6E, 0x01, 0xC0, 0xF2, 0x00, 0x01, + 0x40, 0xF2, 0x76, 0x02, 0xC0, 0xF2, 0x00, 0x02, + 0x40, 0xF2, 0x29, 0x01, 0xC0, 0xF2, 0x00, 0x01, + 0x79, 0x44, 0x40, 0xF2, 0x98, 0x03, 0xC0, 0xF2, + 0x00, 0x03, 0x40, 0xF2, 0xA0, 0x04, 0xC0, 0xF2, + 0x00, 0x04, 0x40, 0xF2, 0x53, 0x03, 0xC0, 0xF2, + 0x00, 0x03, 0x40, 0xF2, 0x00, 0x05, 0xC0, 0xF2, + 0x00, 0x05, 0x40, 0xF2, 0x08, 0x06, 0xC0, 0xF2, + 0x00, 0x06, 0xC0, 0x46, 0x0F, 0x00, 0x00, 0xEB, + 0x0F, 0x00, 0x00, 0xEB, 0xE7, 0xFF, 0xFF, 0xEB, + 0xE7, 0xFF, 0xFF, 0xEB, 0x20, 0x10, 0x00, 0xE3, + 0x00, 0x10, 0x40, 0xE3, 0x28, 0x20, 0x00, 0xE3, + 0x00, 0x20, 0x40, 0xE3, 0x0F, 0x10, 0x81, 0xE0, + 0x98, 0x30, 0x00, 0xE3, 0x00, 0x30, 0x40, 0xE3, + 0xA0, 0x40, 0x00, 0xE3, 0x00, 0x40, 0x40, 0xE3, + 0x00, 0x50, 0x00, 0xE3, 0x00, 0x50, 0x40, 0xE3, + 0x08, 0x60, 0x00, 0xE3, 0x00, 0x60, 0x40, 0xE3 ] + relocations: + - offset: 0x00000094 + type: ARM_RELOC_HALF + length: 1 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000008 + type: ARM_RELOC_PAIR + length: 1 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000090 + type: ARM_RELOC_HALF + length: 0 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 0 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x0000008C + type: ARM_RELOC_HALF + length: 1 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 1 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000088 + type: ARM_RELOC_HALF + length: 0 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 0 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000084 + scattered: true + type: ARM_RELOC_HALF + length: 1 + pc-rel: false + value: 0x00000098 + - offset: 0x000000A0 + type: ARM_RELOC_PAIR + length: 1 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000080 + scattered: true + type: ARM_RELOC_HALF + length: 0 + pc-rel: false + value: 0x00000098 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 0 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x0000007C + type: ARM_RELOC_HALF + length: 1 + pc-rel: false + extern: false + symbol: 2 + - offset: 0x00000098 + type: ARM_RELOC_PAIR + length: 1 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000078 + type: ARM_RELOC_HALF + length: 0 + pc-rel: false + extern: false + symbol: 2 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 0 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000070 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 1 + pc-rel: false + value: 0x00000098 + - offset: 0x00000028 + scattered: true + type: ARM_RELOC_PAIR + length: 1 + pc-rel: false + value: 0x00000078 + - offset: 0x0000006C + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 0 + pc-rel: false + value: 0x00000098 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 0 + pc-rel: false + value: 0x00000078 + - offset: 0x00000068 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 1 + pc-rel: false + value: 0x00000098 + - offset: 0x00000020 + scattered: true + type: ARM_RELOC_PAIR + length: 1 + pc-rel: false + value: 0x00000078 + - offset: 0x00000064 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 0 + pc-rel: false + value: 0x00000098 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 0 + pc-rel: false + value: 0x00000078 + - offset: 0x00000060 + type: ARM_RELOC_BR24 + length: 2 + pc-rel: true + extern: true + symbol: 4 + - offset: 0x0000005C + type: ARM_RELOC_BR24 + length: 2 + pc-rel: true + extern: true + symbol: 4 + - offset: 0x00000058 + scattered: true + type: ARM_RELOC_BR24 + length: 2 + pc-rel: true + value: 0x00000098 + - offset: 0x00000054 + type: ARM_RELOC_BR24 + length: 2 + pc-rel: true + extern: false + symbol: 2 + - offset: 0x0000004E + type: ARM_RELOC_HALF + length: 3 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000008 + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x0000004A + type: ARM_RELOC_HALF + length: 2 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000046 + type: ARM_RELOC_HALF + length: 3 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000042 + type: ARM_RELOC_HALF + length: 2 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x0000003E + type: ARM_RELOC_HALF + length: 3 + pc-rel: false + extern: false + symbol: 1 + - offset: 0x00000053 + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x0000003A + type: ARM_RELOC_HALF + length: 2 + pc-rel: false + extern: false + symbol: 1 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000036 + scattered: true + type: ARM_RELOC_HALF + length: 3 + pc-rel: false + value: 0x00000098 + - offset: 0x000000A0 + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000032 + scattered: true + type: ARM_RELOC_HALF + length: 2 + pc-rel: false + value: 0x00000098 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x0000002E + type: ARM_RELOC_HALF + length: 3 + pc-rel: false + extern: false + symbol: 2 + - offset: 0x00000098 + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x0000002A + type: ARM_RELOC_HALF + length: 2 + pc-rel: false + extern: false + symbol: 2 + - offset: 0x00000000 + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + extern: false + symbol: 16777215 + - offset: 0x00000024 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 3 + pc-rel: false + value: 0x00000052 + - offset: 0x00000028 + scattered: true + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + value: 0x0000002A + - offset: 0x00000020 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 2 + pc-rel: false + value: 0x00000052 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + value: 0x0000002A + - offset: 0x0000001C + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 3 + pc-rel: false + value: 0x00000098 + - offset: 0x00000076 + scattered: true + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + value: 0x0000002A + - offset: 0x00000018 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 2 + pc-rel: false + value: 0x00000098 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + value: 0x0000002A + - offset: 0x00000014 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 3 + pc-rel: false + value: 0x00000098 + - offset: 0x0000006E + scattered: true + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + value: 0x0000002A + - offset: 0x00000010 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 2 + pc-rel: false + value: 0x00000098 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + value: 0x0000002A + - offset: 0x0000000C + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: true + symbol: 4 + - offset: 0x00000008 + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: true + symbol: 4 + - offset: 0x00000004 + scattered: true + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + value: 0x00000098 + - offset: 0x00000000 + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: false + symbol: 2 + - segment: __DATA + section: __data + type: S_REGULAR + attributes: [ ] + address: 0x0000000000000098 + content: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xA8, 0xFF, 0xFF, 0xFF, + 0xA8, 0xFF, 0xFF, 0xFF, 0x4D, 0xFF, 0xFF, 0xFF, + 0x4D, 0xFF, 0xFF, 0xFF ] + relocations: + - offset: 0x00000020 + scattered: true + type: ARM_RELOC_SECTDIFF + length: 2 + pc-rel: false + value: 0x00000000 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + value: 0x000000B8 + - offset: 0x0000001C + scattered: true + type: ARM_RELOC_SECTDIFF + length: 2 + pc-rel: false + value: 0x00000000 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + value: 0x000000B4 + - offset: 0x00000018 + scattered: true + type: ARM_RELOC_SECTDIFF + length: 2 + pc-rel: false + value: 0x00000054 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + value: 0x000000B0 + - offset: 0x00000014 + scattered: true + type: ARM_RELOC_SECTDIFF + length: 2 + pc-rel: false + value: 0x00000054 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + value: 0x000000AC + - offset: 0x00000010 + type: ARM_RELOC_VANILLA + length: 2 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x0000000C + type: ARM_RELOC_VANILLA + length: 2 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000008 + scattered: true + type: ARM_RELOC_VANILLA + length: 2 + pc-rel: false + value: 0x00000000 + - offset: 0x00000004 + type: ARM_RELOC_VANILLA + length: 2 + pc-rel: false + extern: false + symbol: 1 +local-symbols: + - name: _foo_thumb + type: N_SECT + sect: 1 + desc: [ N_ARM_THUMB_DEF ] + value: 0x0000000000000000 + - name: _x + type: N_SECT + sect: 2 + value: 0x0000000000000098 + - name: _t1 + type: N_SECT + sect: 1 + desc: [ N_ARM_THUMB_DEF ] + value: 0x0000000000000052 + - name: _foo_arm + type: N_SECT + sect: 1 + value: 0x0000000000000054 +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: 4 +# CHECK: target: _foo_thumb +# CHECK-NOT: addend: +# CHECK: - kind: pointer32 +# CHECK: offset: 8 +# CHECK: target: _foo_thumb +# CHECK: addend: 4 +# CHECK: - kind: pointer32 +# CHECK: offset: 12 +# CHECK: target: _undef +# CHECK-NOT: addend: +# CHECK: - kind: pointer32 +# CHECK: offset: 16 +# CHECK: target: _undef +# CHECK: addend: 4 +# CHECK: - kind: delta32 +# CHECK: offset: 20 +# CHECK: target: _foo_arm +# CHECK-NOT: addend: +# CHECK: - kind: delta32 +# CHECK: offset: 24 +# CHECK: target: _foo_arm +# CHECK: addend: 4 +# CHECK: - kind: delta32 +# CHECK: offset: 28 +# CHECK: target: _foo_thumb +# CHECK-NOT: addend: +# CHECK: - kind: delta32 +# CHECK: offset: 32 +# CHECK: target: _foo_thumb +# CHECK: addend: 4 +# CHECK: - name: _foo_thumb +# CHECK: references: +# CHECK: - kind: thumb_b22 +# CHECK: offset: 0 +# CHECK: target: _x +# CHECK-NOT: addend: +# CHECK: - kind: thumb_b22 +# CHECK: offset: 4 +# CHECK: target: _x +# CHECK: addend: 4 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 8 +# CHECK: target: _undef +# CHECK-NOT: addend: +# CHECK: - kind: thumb_b22 +# CHECK: offset: 12 +# CHECK: target: _undef +# CHECK: addend: 4 +# CHECK: - kind: thumb_movw_funcRel +# CHECK: offset: 16 +# CHECK: target: _x +# CHECK: addend: -42 +# CHECK: - kind: thumb_movt_funcRel +# CHECK: offset: 20 +# CHECK: target: _x +# CHECK: addend: -42 +# CHECK: - kind: thumb_movw_funcRel +# CHECK: offset: 24 +# CHECK: target: _x +# CHECK: addend: -34 +# CHECK: - kind: thumb_movt_funcRel +# CHECK: offset: 28 +# CHECK: target: _x +# CHECK: addend: -34 +# CHECK: - kind: thumb_movw_funcRel +# CHECK: offset: 32 +# CHECK: target: _t1 +# CHECK: addend: -42 +# CHECK: - kind: thumb_movt_funcRel +# CHECK: offset: 36 +# CHECK: target: _t1 +# CHECK: addend: -42 +# CHECK: - kind: thumb_movw +# CHECK: offset: 42 +# CHECK: target: _x +# CHECK-NOT: addend: +# CHECK: - kind: thumb_movt +# CHECK: offset: 46 +# CHECK: target: _x +# CHECK-NOT: addend: +# CHECK: - kind: thumb_movw +# CHECK: offset: 50 +# CHECK: target: _x +# CHECK: addend: 8 +# CHECK: - kind: thumb_movt +# CHECK: offset: 54 +# CHECK: target: _x +# CHECK: addend: 8 +# CHECK: - kind: thumb_movw +# CHECK: offset: 58 +# CHECK: target: _t1 +# CHECK-NOT: addend: +# CHECK: - kind: thumb_movt +# CHECK: offset: 62 +# CHECK: target: _t1 +# CHECK-NOT: addend: +# CHECK: - kind: thumb_movw +# CHECK: offset: 66 +# CHECK: target: _undef +# CHECK-NOT: addend: +# CHECK: - kind: thumb_movt +# CHECK: offset: 70 +# CHECK: target: _undef +# CHECK-NOT: addend: +# CHECK: - kind: thumb_movw +# CHECK: offset: 74 +# CHECK: target: _undef +# CHECK: addend: 8 +# CHECK: - kind: thumb_movt +# CHECK: offset: 78 +# CHECK: target: _undef +# CHECK: addend: 8 +# CHECK: - name: _t1 +# CHECK: content: [ C0, 46 ] +# CHECK: - name: _foo_arm +# CHECK: references: +# CHECK: - kind: arm_b24 +# CHECK: offset: 0 +# CHECK: target: _x +# CHECK-NOT: addend: +# CHECK: - kind: arm_b24 +# CHECK: offset: 4 +# CHECK: target: _x +# CHECK: addend: 4 +# CHECK: - kind: arm_b24 +# CHECK: offset: 8 +# CHECK: target: _undef +# CHECK-NOT: addend: +# CHECK: - kind: arm_b24 +# CHECK: offset: 12 +# CHECK: target: _undef +# CHECK: addend: 4 +# CHECK: - kind: arm_movw_funcRel +# CHECK: offset: 16 +# CHECK: target: _x +# CHECK: addend: -36 +# CHECK: - kind: arm_movt_funcRel +# CHECK: offset: 20 +# CHECK: target: _x +# CHECK: addend: -36 +# CHECK: - kind: arm_movw_funcRel +# CHECK: offset: 24 +# CHECK: target: _x +# CHECK: addend: -28 +# CHECK: - kind: arm_movt_funcRel +# CHECK: offset: 28 +# CHECK: target: _x +# CHECK: addend: -28 +# CHECK: - kind: arm_movw +# CHECK: offset: 36 +# CHECK: target: _x +# CHECK-NOT: addend: +# CHECK: - kind: arm_movt +# CHECK: offset: 40 +# CHECK: target: _x +# CHECK-NOT: addend: +# CHECK: - kind: arm_movw +# CHECK: offset: 44 +# CHECK: target: _x +# CHECK: addend: 8 +# CHECK: - kind: arm_movt +# CHECK: offset: 48 +# CHECK: target: _x +# CHECK: addend: 8 +# CHECK: - kind: arm_movw +# CHECK: offset: 52 +# CHECK: target: _undef +# CHECK-NOT: addend: +# CHECK: - kind: arm_movt +# CHECK: offset: 56 +# CHECK: target: _undef +# CHECK-NOT: addend: +# CHECK: - kind: arm_movw +# CHECK: offset: 60 +# CHECK: target: _undef +# CHECK: addend: 8 +# CHECK: - kind: arm_movt +# CHECK: offset: 64 +# CHECK: target: _undef +# CHECK: addend: 8 +# CHECK: undefined-atoms: +# CHECK: - name: _undef + + + + +# .align 2 +# .code 16 +# .thumb_func _foo_thumb +#_foo_thumb: +# bl _x +# bl _x+4 +# bl _undef +# bl _undef+4 +# movw r1, :lower16:(_x-L1) +# movt r1, :upper16:(_x-L1) +# movw r2, :lower16:(_x+8-L1) +# movt r2, :upper16:(_x+8-L1) +# movw r1, :lower16:(_t1-L1) +# movt r1, :upper16:(_t1-L1) +# add r1, pc +#L1: +# movw r3, :lower16:_x +# movt r3, :upper16:_x +# movw r4, :lower16:_x+8 +# movt r4, :upper16:_x+8 +# movw r3, :lower16:_t1 +# movt r3, :upper16:_t1 +# movw r5, :lower16:_undef +# movt r5, :upper16:_undef +# movw r6, :lower16:_undef+8 +# movt r6, :upper16:_undef+8 +# +# .thumb_func _t1 +#_t1: +# nop +# +# +# .code 32 +# .align 2 +#_foo_arm: +# bl _x +# bl _x+4 +# bl _undef +# bl _undef+4 +# movw r1, :lower16:(_x-L2) +# movt r1, :upper16:(_x-L2) +# movw r2, :lower16:(_x+8-L2) +# movt r2, :upper16:(_x+8-L2) +# add r1, pc +#L2: +# movw r3, :lower16:_x +# movt r3, :upper16:_x +# movw r4, :lower16:_x+8 +# movt r4, :upper16:_x+8 +# movw r5, :lower16:_undef +# movt r5, :upper16:_undef +# movw r6, :lower16:_undef+8 +# movt r6, :upper16:_undef+8 +# +# +# .data +#_x: .long 0 +# .long _foo_thumb +# .long _foo_thumb+4 +# .long _undef +# .long _undef+4 +# .long _foo_arm - . +# .long _foo_arm+4- . +# .long _foo_thumb - . +# .long _foo_thumb+4 - . +# -- 2.7.4