flesh out mach-o Reference Kinds

llvm-svn: 158375
This commit is contained in:
Nick Kledzik 2012-06-12 23:01:30 +00:00
parent b47d6ca3a5
commit c890ae41e2
4 changed files with 218 additions and 96 deletions

View File

@ -53,25 +53,39 @@ KindHandler_x86_64::~KindHandler_x86_64() {
Reference::Kind KindHandler_x86_64::stringToKind(StringRef str) { Reference::Kind KindHandler_x86_64::stringToKind(StringRef str) {
if ( str.equals("none") ) if ( str.equals("none") )
return KindHandler_x86_64::none; return none;
else if ( str.equals("call32") ) else if ( str.equals("branch32") )
return KindHandler_x86_64::call32; return branch32;
else if ( str.equals("ripRel32") ) else if ( str.equals("ripRel32") )
return KindHandler_x86_64::ripRel32; return ripRel32;
else if ( str.equals("gotLoad32") ) else if ( str.equals("ripRel32_1") )
return KindHandler_x86_64::gotLoad32; return ripRel32_1;
else if ( str.equals("gotUse32") ) else if ( str.equals("ripRel32_2") )
return KindHandler_x86_64::gotUse32; return ripRel32_2;
else if ( str.equals("ripRel32_4") )
return ripRel32_4;
else if ( str.equals("gotLoadRipRel32") )
return gotLoadRipRel32;
else if ( str.equals("gotLoadRipRel32NowLea") )
return gotLoadRipRel32NowLea;
else if ( str.equals("gotUseRipRel32") )
return gotUseRipRel32;
else if ( str.equals("tlvLoadRipRel32") )
return tlvLoadRipRel32;
else if ( str.equals("tlvLoadRipRel32NowLea") )
return tlvLoadRipRel32NowLea;
else if ( str.equals("pointer64") ) else if ( str.equals("pointer64") )
return KindHandler_x86_64::pointer64; return pointer64;
else if ( str.equals("lea32WasGot") ) else if ( str.equals("pointerRel32") )
return KindHandler_x86_64::lea32WasGot; return pointerRel32;
else if ( str.equals("lazyTarget") ) else if ( str.equals("lazyTarget") )
return KindHandler_x86_64::lazyTarget; return lazyTarget;
else if ( str.equals("lazyImm") ) else if ( str.equals("lazyImmediate") )
return KindHandler_x86_64::lazyImm; return lazyImmediate;
else if ( str.equals("gotTarget") ) else if ( str.equals("subordinateFDE") )
return KindHandler_x86_64::gotTarget; return subordinateFDE;
else if ( str.equals("subordinateLSDA") )
return subordinateLSDA;
assert(0 && "invalid x86_64 Reference kind"); assert(0 && "invalid x86_64 Reference kind");
return 0; return 0;
@ -81,68 +95,100 @@ StringRef KindHandler_x86_64::kindToString(Reference::Kind kind) {
switch ( (Kinds)kind ) { switch ( (Kinds)kind ) {
case none: case none:
return StringRef("none"); return StringRef("none");
case call32: case branch32:
return StringRef("call32"); return StringRef("branch32");
case ripRel32: case ripRel32:
return StringRef("ripRel32"); return StringRef("ripRel32");
case gotLoad32: case ripRel32_1:
return StringRef("gotLoad32"); return StringRef("ripRel32_1");
case gotUse32: case ripRel32_2:
return StringRef("gotUse32"); return StringRef("ripRel32_2");
case ripRel32_4:
return StringRef("ripRel32_4");
case gotLoadRipRel32:
return StringRef("gotLoadRipRel32");
case gotLoadRipRel32NowLea:
return StringRef("gotLoadRipRel32NowLea");
case gotUseRipRel32:
return StringRef("gotUseRipRel32");
case tlvLoadRipRel32:
return StringRef("tlvLoadRipRel32");
case tlvLoadRipRel32NowLea:
return StringRef("tlvLoadRipRel32NowLea");
case pointer64: case pointer64:
return StringRef("pointer64"); return StringRef("pointer64");
case lea32WasGot: case pointerRel32:
return StringRef("lea32WasGot"); return StringRef("pointerRel32");
case lazyTarget: case lazyTarget:
return StringRef("lazyTarget"); return StringRef("lazyTarget");
case lazyImm: case lazyImmediate:
return StringRef("lazyImm"); return StringRef("lazyImmediate");
case gotTarget: case subordinateFDE:
return StringRef("gotTarget"); return StringRef("subordinateFDE");
case subordinateLSDA:
return StringRef("subordinateLSDA");
} }
assert(0 && "invalid x86_64 Reference kind"); assert(0 && "invalid x86_64 Reference kind");
return StringRef(); return StringRef();
} }
bool KindHandler_x86_64::isCallSite(Kind kind) { bool KindHandler_x86_64::isCallSite(Kind kind) {
return (kind == call32); return (kind == branch32);
} }
bool KindHandler_x86_64::isPointer(Kind kind) { bool KindHandler_x86_64::isPointer(Kind kind) {
return (kind == pointer64); return (kind == pointer64);
} }
bool KindHandler_x86_64::isLazyImmediate(Kind kind) { bool KindHandler_x86_64::isLazyImmediate(Kind kind) {
return (kind == lazyImm); return (kind == lazyImmediate);
} }
bool KindHandler_x86_64::isLazyTarget(Kind kind) { bool KindHandler_x86_64::isLazyTarget(Kind kind) {
return (kind == lazyTarget); return (kind == lazyTarget);
} }
void KindHandler_x86_64::applyFixup(Kind kind, uint64_t addend, uint8_t *location, void KindHandler_x86_64::applyFixup(Kind kind, uint64_t addend,
uint64_t fixupAddress, uint64_t targetAddress) { uint8_t *location, uint64_t fixupAddress,
uint64_t targetAddress) {
int32_t *loc32 = reinterpret_cast<int32_t*>(location); int32_t *loc32 = reinterpret_cast<int32_t*>(location);
uint64_t* loc64 = reinterpret_cast<uint64_t*>(location); uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
switch ( (Kinds)kind ) { switch ( (Kinds)kind ) {
case call32: case branch32:
case ripRel32: case ripRel32:
case gotLoad32: case gotLoadRipRel32:
case gotUse32: case gotUseRipRel32:
case tlvLoadRipRel32:
*loc32 = (targetAddress - (fixupAddress+4)) + addend; *loc32 = (targetAddress - (fixupAddress+4)) + addend;
break; break;
case pointer64: case pointer64:
*loc64 = targetAddress + addend; *loc64 = targetAddress + addend;
break; break;
case lea32WasGot: case ripRel32_1:
*loc32 = (targetAddress - (fixupAddress+5)) + addend;
break;
case ripRel32_2:
*loc32 = (targetAddress - (fixupAddress+6)) + addend;
break;
case ripRel32_4:
*loc32 = (targetAddress - (fixupAddress+8)) + addend;
break;
case pointerRel32:
*loc32 = (targetAddress - fixupAddress) + addend;
break;
case gotLoadRipRel32NowLea:
case tlvLoadRipRel32NowLea:
// Change MOVQ to LEA
assert(location[-2] == 0x8B);
location[-2] = 0x8D;
*loc32 = (targetAddress - (fixupAddress+4)) + addend;
break; break;
case none: case none:
case lazyTarget: case lazyTarget:
case lazyImm: case lazyImmediate:
case gotTarget: case subordinateFDE:
case subordinateLSDA:
// do nothing // do nothing
break; break;
} }
@ -158,17 +204,19 @@ KindHandler_x86::~KindHandler_x86() {
Reference::Kind KindHandler_x86::stringToKind(StringRef str) { Reference::Kind KindHandler_x86::stringToKind(StringRef str) {
if ( str.equals("none") ) if ( str.equals("none") )
return KindHandler_x86::none; return none;
else if ( str.equals("call32") ) else if ( str.equals("branch32") )
return KindHandler_x86::call32; return branch32;
else if ( str.equals("abs32") ) else if ( str.equals("abs32") )
return KindHandler_x86::abs32; return abs32;
else if ( str.equals("funcRel32") )
return funcRel32;
else if ( str.equals("pointer32") ) else if ( str.equals("pointer32") )
return KindHandler_x86::pointer32; return pointer32;
else if ( str.equals("lazyTarget") ) else if ( str.equals("lazyTarget") )
return KindHandler_x86::lazyTarget; return lazyTarget;
else if ( str.equals("lazyImm") ) else if ( str.equals("lazyImmediate") )
return KindHandler_x86::lazyImm; return lazyImmediate;
assert(0 && "invalid x86 Reference kind"); assert(0 && "invalid x86 Reference kind");
return 0; return 0;
@ -178,23 +226,29 @@ StringRef KindHandler_x86::kindToString(Reference::Kind kind) {
switch ( (Kinds)kind ) { switch ( (Kinds)kind ) {
case none: case none:
return StringRef("none"); return StringRef("none");
case call32: case branch32:
return StringRef("call32"); return StringRef("branch32");
case abs32: case abs32:
return StringRef("abs32"); return StringRef("abs32");
case funcRel32:
return StringRef("funcRel32");
case pointer32: case pointer32:
return StringRef("pointer32"); return StringRef("pointer32");
case lazyTarget: case lazyTarget:
return StringRef("lazyTarget"); return StringRef("lazyTarget");
case lazyImm: case lazyImmediate:
return StringRef("lazyImm"); return StringRef("lazyImmediate");
case subordinateFDE:
return StringRef("subordinateFDE");
case subordinateLSDA:
return StringRef("subordinateLSDA");
} }
assert(0 && "invalid x86 Reference kind"); assert(0 && "invalid x86 Reference kind");
return StringRef(); return StringRef();
} }
bool KindHandler_x86::isCallSite(Kind kind) { bool KindHandler_x86::isCallSite(Kind kind) {
return (kind == call32); return (kind == branch32);
} }
bool KindHandler_x86::isPointer(Kind kind) { bool KindHandler_x86::isPointer(Kind kind) {
@ -203,7 +257,7 @@ bool KindHandler_x86::isPointer(Kind kind) {
bool KindHandler_x86::isLazyImmediate(Kind kind) { bool KindHandler_x86::isLazyImmediate(Kind kind) {
return (kind == lazyImm); return (kind == lazyImmediate);
} }
@ -216,16 +270,21 @@ void KindHandler_x86::applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress) { uint64_t fixupAddress, uint64_t targetAddress) {
int32_t *loc32 = reinterpret_cast<int32_t*>(location); int32_t *loc32 = reinterpret_cast<int32_t*>(location);
switch ( (Kinds)kind ) { switch ( (Kinds)kind ) {
case call32: case branch32:
*loc32 = (targetAddress - (fixupAddress+4)) + addend; *loc32 = (targetAddress - (fixupAddress+4)) + addend;
break; break;
case pointer32: case pointer32:
case abs32: case abs32:
*loc32 = targetAddress + addend; *loc32 = targetAddress + addend;
break; break;
case funcRel32:
*loc32 = targetAddress + addend;
break;
case none: case none:
case lazyTarget: case lazyTarget:
case lazyImm: case lazyImmediate:
case subordinateFDE:
case subordinateLSDA:
// do nothing // do nothing
break; break;
} }
@ -241,15 +300,29 @@ KindHandler_arm::~KindHandler_arm() {
Reference::Kind KindHandler_arm::stringToKind(StringRef str) { Reference::Kind KindHandler_arm::stringToKind(StringRef str) {
if ( str.equals("none") ) if ( str.equals("none") )
return KindHandler_arm::none; return none;
else if ( str.equals("br22") ) else if ( str.equals("thumbBranch22") )
return KindHandler_arm::br22; return thumbBranch22;
else if ( str.equals("armBranch24") )
return armBranch24;
else if ( str.equals("thumbAbsLow16") )
return thumbAbsLow16;
else if ( str.equals("thumbAbsHigh16") )
return thumbAbsHigh16;
else if ( str.equals("thumbPcRelLow16") )
return thumbPcRelLow16;
else if ( str.equals("thumbPcRelHigh16") )
return thumbPcRelHigh16;
else if ( str.equals("abs32") )
return abs32;
else if ( str.equals("pointer32") ) else if ( str.equals("pointer32") )
return KindHandler_arm::pointer32; return pointer32;
else if ( str.equals("lazyTarget") ) else if ( str.equals("lazyTarget") )
return KindHandler_arm::lazyTarget; return lazyTarget;
else if ( str.equals("lazyImm") ) else if ( str.equals("lazyImmediate") )
return KindHandler_arm::lazyImm; return lazyImmediate;
else if ( str.equals("subordinateLSDA") )
return subordinateLSDA;
assert(0 && "invalid ARM Reference kind"); assert(0 && "invalid ARM Reference kind");
return 0; return 0;
@ -259,21 +332,35 @@ StringRef KindHandler_arm::kindToString(Reference::Kind kind) {
switch ( (Kinds)kind ) { switch ( (Kinds)kind ) {
case none: case none:
return StringRef("none"); return StringRef("none");
case br22: case thumbBranch22:
return StringRef("br22"); return StringRef("thumbBranch22");
case armBranch24:
return StringRef("armBranch24");
case thumbAbsLow16:
return StringRef("thumbAbsLow16");
case thumbAbsHigh16:
return StringRef("thumbAbsHigh16");
case thumbPcRelLow16:
return StringRef("thumbPcRelLow16");
case thumbPcRelHigh16:
return StringRef("thumbPcRelHigh16");
case abs32:
return StringRef("abs32");
case pointer32: case pointer32:
return StringRef("pointer32"); return StringRef("pointer32");
case lazyTarget: case lazyTarget:
return StringRef("lazyTarget"); return StringRef("lazyTarget");
case lazyImm: case lazyImmediate:
return StringRef("lazyImm"); return StringRef("lazyImmediate");
case subordinateLSDA:
return StringRef("subordinateLSDA");
} }
assert(0 && "invalid ARM Reference kind"); assert(0 && "invalid ARM Reference kind");
return StringRef(); return StringRef();
} }
bool KindHandler_arm::isCallSite(Kind kind) { bool KindHandler_arm::isCallSite(Kind kind) {
return (kind == br22); return (kind == thumbBranch22) || (kind == armBranch24);
} }
bool KindHandler_arm::isPointer(Kind kind) { bool KindHandler_arm::isPointer(Kind kind) {
@ -282,7 +369,7 @@ bool KindHandler_arm::isPointer(Kind kind) {
bool KindHandler_arm::isLazyImmediate(Kind kind) { bool KindHandler_arm::isLazyImmediate(Kind kind) {
return (kind == lazyImm); return (kind == lazyImmediate);
} }
@ -295,7 +382,25 @@ void KindHandler_arm::applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress) { uint64_t fixupAddress, uint64_t targetAddress) {
//int32_t *loc32 = reinterpret_cast<int32_t*>(location); //int32_t *loc32 = reinterpret_cast<int32_t*>(location);
switch ( (Kinds)kind ) { switch ( (Kinds)kind ) {
case br22: case thumbBranch22:
// FIXME
break;
case armBranch24:
// FIXME
break;
case thumbAbsLow16:
// FIXME
break;
case thumbAbsHigh16:
// FIXME
break;
case thumbPcRelLow16:
// FIXME
break;
case thumbPcRelHigh16:
// FIXME
break;
case abs32:
// FIXME // FIXME
break; break;
case pointer32: case pointer32:
@ -303,7 +408,8 @@ void KindHandler_arm::applyFixup(Kind kind, uint64_t addend, uint8_t *location,
break; break;
case none: case none:
case lazyTarget: case lazyTarget:
case lazyImm: case lazyImmediate:
case subordinateLSDA:
// do nothing // do nothing
break; break;
} }

View File

@ -48,16 +48,23 @@ protected:
class KindHandler_x86_64 : public KindHandler { class KindHandler_x86_64 : public KindHandler {
public: public:
enum Kinds { enum Kinds {
none = 0, none,
call32 = 1, branch32, // CALL or JMP 32-bit pc-rel
ripRel32 = 2, ripRel32, // RIP-rel access pc-rel to fix up location
gotLoad32 = 3, ripRel32_1, // RIP-rel access pc-rel to fix up location + 1
gotUse32 = 4, ripRel32_2, // RIP-rel access pc-rel to fix up location + 2
lea32WasGot = 5, ripRel32_4, // RIP-rel access pc-rel to fix up location + 4
lazyTarget = 6, gotLoadRipRel32, // RIP-rel load of GOT slot (can be optimized)
lazyImm = 7, gotLoadRipRel32NowLea, // RIP-rel movq load of GOT slot optimized to LEA
gotTarget = 8, gotUseRipRel32, // RIP-rel non-load of GOT slot (not a movq load of GOT)
pointer64 = 9 tlvLoadRipRel32, // RIP-rel load of thread local pointer (can be optimized)
tlvLoadRipRel32NowLea, // RIP-rel movq load of TLV pointer optimized to LEA
pointer64, // 64-bit data pointer
pointerRel32, // 32-bit pc-rel offset
lazyTarget, // Used in lazy pointers to reference ultimate target
lazyImmediate, // Location in stub where lazy info offset to be stored
subordinateFDE, // Reference to unwind info for this function
subordinateLSDA // Reference to excecption info for this function
}; };
virtual ~KindHandler_x86_64(); virtual ~KindHandler_x86_64();
@ -76,12 +83,15 @@ public:
class KindHandler_x86 : public KindHandler { class KindHandler_x86 : public KindHandler {
public: public:
enum Kinds { enum Kinds {
none = 0, none,
call32 = 1, branch32, // CALL or JMP 32-bit pc-rel
abs32 = 2, abs32, // 32-bit absolute address embedded in instruction
pointer32 = 3, funcRel32, // 32-bit offset to target from start of function
lazyTarget = 4, pointer32, // 32-bit data pointer
lazyImm = 5 lazyTarget, // Used in lazy pointers to reference ultimate target
lazyImmediate, // Location in stub where lazy info offset to be stored
subordinateFDE, // Reference to unwind info for this function
subordinateLSDA // Reference to excecption info for this function
}; };
virtual ~KindHandler_x86(); virtual ~KindHandler_x86();
@ -99,12 +109,18 @@ public:
class KindHandler_arm : public KindHandler { class KindHandler_arm : public KindHandler {
public: public:
enum Kinds { enum Kinds {
none = 0, none,
br22 = 1, thumbBranch22, // thumb b or bl with 22/24-bits of displacement
pointer32 = 2, armBranch24, // arm b or bl with 24-bits of displacement
lazyTarget = 3, thumbAbsLow16, // thumb movw of absolute address
lazyImm = 4 thumbAbsHigh16, // thumb movt of absolute address
// FIXME thumbPcRelLow16, // thumb movw of (target - pc)
thumbPcRelHigh16,// thumb movt of (target - pc)
abs32, // 32-bit absolute address embedded in instructions
pointer32, // 32-bit data pointer
lazyTarget, // Used in lazy pointers to reference ultimate target
lazyImmediate, // Location in stub where lazy info offset to be stored
subordinateLSDA // Reference to excecption info for this function
}; };
virtual ~KindHandler_arm(); virtual ~KindHandler_arm();

View File

@ -100,8 +100,8 @@ class X86StubHelperAtom : public SimpleDefinedAtom {
public: public:
X86StubHelperAtom(const File &file, const Atom &helperCommon) X86StubHelperAtom(const File &file, const Atom &helperCommon)
: SimpleDefinedAtom(file) { : SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86::lazyImm, 1, nullptr, 0); this->addReference(KindHandler_x86::lazyImmediate, 1, nullptr, 0);
this->addReference(KindHandler_x86::call32, 6, &helperCommon, 0); this->addReference(KindHandler_x86::branch32, 6, &helperCommon, 0);
} }
virtual ContentType contentType() const { virtual ContentType contentType() const {

View File

@ -101,7 +101,7 @@ class X86_64StubHelperAtom : public SimpleDefinedAtom {
public: public:
X86_64StubHelperAtom(const File &file, const Atom &helperCommon) X86_64StubHelperAtom(const File &file, const Atom &helperCommon)
: SimpleDefinedAtom(file) { : SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86_64::lazyImm, 1, nullptr, 0); this->addReference(KindHandler_x86_64::lazyImmediate, 1, nullptr, 0);
this->addReference(KindHandler_x86_64::ripRel32, 6, &helperCommon, 0); this->addReference(KindHandler_x86_64::ripRel32, 6, &helperCommon, 0);
} }