forked from OSchip/llvm-project
[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
This commit is contained in:
parent
d7f75eeffc
commit
4576c115ac
|
@ -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<uint8_t> 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<uint8_t>(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<uint8_t> content,
|
||||
bool thumb, const ArrayRef<uint8_t> content,
|
||||
StringRef sectionName)
|
||||
: MachODefinedAtom(f, name, scope, type, merge, content),
|
||||
: MachODefinedAtom(f, name, scope, type, merge, thumb, content),
|
||||
_sectionName(sectionName) {}
|
||||
|
||||
SectionChoice sectionChoice() const override {
|
||||
|
|
|
@ -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<uint8_t> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<File>(std::move(file));
|
||||
// TEMP END
|
||||
|
||||
// Convert mach-o relocations to References
|
||||
std::unique_ptr<mach_o::KindHandler> handler
|
||||
= KindHandler::create(normalizedFile.arch);
|
||||
|
|
|
@ -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<DefinedAtom>(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<int32_t*>(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 ARM_RELOC_BR24:
|
||||
case thumb_movt:
|
||||
// FIXME
|
||||
break;
|
||||
case LLD_ARM_RELOC_THUMB_ABS_LO16:
|
||||
case thumb_movw_funcRel:
|
||||
// FIXME
|
||||
break;
|
||||
case LLD_ARM_RELOC_THUMB_ABS_HI16:
|
||||
case thumb_movt_funcRel:
|
||||
// FIXME
|
||||
break;
|
||||
case LLD_ARM_RELOC_THUMB_REL_LO16:
|
||||
case arm_b24:
|
||||
// FIXME
|
||||
break;
|
||||
case LLD_ARM_RELOC_THUMB_REL_HI16:
|
||||
case arm_movw:
|
||||
// FIXME
|
||||
break;
|
||||
case LLD_ARM_RELOC_ABS32:
|
||||
case arm_movt:
|
||||
// FIXME
|
||||
break;
|
||||
case LLD_ARM_RELOC_POINTER32:
|
||||
case arm_movw_funcRel:
|
||||
// FIXME
|
||||
break;
|
||||
case LLD_ARM_RELOC_LAZY_TARGET:
|
||||
case LLD_ARM_RELOC_LAZY_IMMEDIATE:
|
||||
case arm_movt_funcRel:
|
||||
// FIXME
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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<std::error_code (uint32_t symbolIndex,
|
||||
const lld::Atom**)> 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
|
||||
|
|
|
@ -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 - .
|
||||
#
|
Loading…
Reference in New Issue