424 lines
11 KiB
C++
424 lines
11 KiB
C++
//===- lib/FileFormat/MachO/ReferenceKinds.cpp ----------------------===//
|
|
//
|
|
// The LLVM Linker
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
#include "ReferenceKinds.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
|
|
namespace lld {
|
|
namespace mach_o {
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// KindHandler
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
KindHandler::KindHandler() {
|
|
}
|
|
|
|
KindHandler::~KindHandler() {
|
|
}
|
|
|
|
KindHandler *KindHandler::makeHandler(WriterOptionsMachO::Architecture arch) {
|
|
switch( arch ) {
|
|
case WriterOptionsMachO::arch_x86_64:
|
|
return new KindHandler_x86_64();
|
|
break;
|
|
case WriterOptionsMachO::arch_x86:
|
|
return new KindHandler_x86();
|
|
break;
|
|
case WriterOptionsMachO::arch_armv6:
|
|
case WriterOptionsMachO::arch_armv7:
|
|
return new KindHandler_arm();
|
|
break;
|
|
default:
|
|
assert(0 && "arch not supported");
|
|
}
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// KindHandler_x86_64
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
KindHandler_x86_64::~KindHandler_x86_64() {
|
|
}
|
|
|
|
Reference::Kind KindHandler_x86_64::stringToKind(StringRef str) {
|
|
if ( str.equals("none") )
|
|
return none;
|
|
else if ( str.equals("branch32") )
|
|
return branch32;
|
|
else if ( str.equals("ripRel32") )
|
|
return ripRel32;
|
|
else if ( str.equals("ripRel32_1") )
|
|
return ripRel32_1;
|
|
else if ( str.equals("ripRel32_2") )
|
|
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") )
|
|
return pointer64;
|
|
else if ( str.equals("pointerRel32") )
|
|
return pointerRel32;
|
|
else if ( str.equals("lazyTarget") )
|
|
return lazyTarget;
|
|
else if ( str.equals("lazyImmediate") )
|
|
return lazyImmediate;
|
|
else if ( str.equals("subordinateFDE") )
|
|
return subordinateFDE;
|
|
else if ( str.equals("subordinateLSDA") )
|
|
return subordinateLSDA;
|
|
|
|
assert(0 && "invalid x86_64 Reference kind");
|
|
return 0;
|
|
}
|
|
|
|
StringRef KindHandler_x86_64::kindToString(Reference::Kind kind) {
|
|
switch ( (Kinds)kind ) {
|
|
case none:
|
|
return StringRef("none");
|
|
case branch32:
|
|
return StringRef("branch32");
|
|
case ripRel32:
|
|
return StringRef("ripRel32");
|
|
case ripRel32_1:
|
|
return StringRef("ripRel32_1");
|
|
case ripRel32_2:
|
|
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:
|
|
return StringRef("pointer64");
|
|
case pointerRel32:
|
|
return StringRef("pointerRel32");
|
|
case lazyTarget:
|
|
return StringRef("lazyTarget");
|
|
case lazyImmediate:
|
|
return StringRef("lazyImmediate");
|
|
case subordinateFDE:
|
|
return StringRef("subordinateFDE");
|
|
case subordinateLSDA:
|
|
return StringRef("subordinateLSDA");
|
|
}
|
|
assert(0 && "invalid x86_64 Reference kind");
|
|
return StringRef();
|
|
}
|
|
|
|
bool KindHandler_x86_64::isCallSite(Kind kind) {
|
|
return (kind == branch32);
|
|
}
|
|
|
|
bool KindHandler_x86_64::isPointer(Kind kind) {
|
|
return (kind == pointer64);
|
|
}
|
|
|
|
bool KindHandler_x86_64::isLazyImmediate(Kind kind) {
|
|
return (kind == lazyImmediate);
|
|
}
|
|
|
|
bool KindHandler_x86_64::isLazyTarget(Kind kind) {
|
|
return (kind == lazyTarget);
|
|
}
|
|
|
|
|
|
void KindHandler_x86_64::applyFixup(Kind kind, uint64_t addend,
|
|
uint8_t *location, uint64_t fixupAddress,
|
|
uint64_t targetAddress) {
|
|
int32_t *loc32 = reinterpret_cast<int32_t*>(location);
|
|
uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
|
|
switch ( (Kinds)kind ) {
|
|
case branch32:
|
|
case ripRel32:
|
|
case gotLoadRipRel32:
|
|
case gotUseRipRel32:
|
|
case tlvLoadRipRel32:
|
|
*loc32 = (targetAddress - (fixupAddress+4)) + addend;
|
|
break;
|
|
case pointer64:
|
|
*loc64 = targetAddress + addend;
|
|
break;
|
|
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;
|
|
case none:
|
|
case lazyTarget:
|
|
case lazyImmediate:
|
|
case subordinateFDE:
|
|
case subordinateLSDA:
|
|
// do nothing
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// KindHandler_x86
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
KindHandler_x86::~KindHandler_x86() {
|
|
}
|
|
|
|
Reference::Kind KindHandler_x86::stringToKind(StringRef str) {
|
|
if ( str.equals("none") )
|
|
return none;
|
|
else if ( str.equals("branch32") )
|
|
return branch32;
|
|
else if ( str.equals("abs32") )
|
|
return abs32;
|
|
else if ( str.equals("funcRel32") )
|
|
return funcRel32;
|
|
else if ( str.equals("pointer32") )
|
|
return pointer32;
|
|
else if ( str.equals("lazyTarget") )
|
|
return lazyTarget;
|
|
else if ( str.equals("lazyImmediate") )
|
|
return lazyImmediate;
|
|
|
|
assert(0 && "invalid x86 Reference kind");
|
|
return 0;
|
|
}
|
|
|
|
StringRef KindHandler_x86::kindToString(Reference::Kind kind) {
|
|
switch ( (Kinds)kind ) {
|
|
case none:
|
|
return StringRef("none");
|
|
case branch32:
|
|
return StringRef("branch32");
|
|
case abs32:
|
|
return StringRef("abs32");
|
|
case funcRel32:
|
|
return StringRef("funcRel32");
|
|
case pointer32:
|
|
return StringRef("pointer32");
|
|
case lazyTarget:
|
|
return StringRef("lazyTarget");
|
|
case lazyImmediate:
|
|
return StringRef("lazyImmediate");
|
|
case subordinateFDE:
|
|
return StringRef("subordinateFDE");
|
|
case subordinateLSDA:
|
|
return StringRef("subordinateLSDA");
|
|
}
|
|
assert(0 && "invalid x86 Reference kind");
|
|
return StringRef();
|
|
}
|
|
|
|
bool KindHandler_x86::isCallSite(Kind kind) {
|
|
return (kind == branch32);
|
|
}
|
|
|
|
bool KindHandler_x86::isPointer(Kind kind) {
|
|
return (kind == pointer32);
|
|
}
|
|
|
|
|
|
bool KindHandler_x86::isLazyImmediate(Kind kind) {
|
|
return (kind == lazyImmediate);
|
|
}
|
|
|
|
|
|
bool KindHandler_x86::isLazyTarget(Kind kind) {
|
|
return (kind == lazyTarget);
|
|
}
|
|
|
|
|
|
void KindHandler_x86::applyFixup(Kind kind, uint64_t addend, uint8_t *location,
|
|
uint64_t fixupAddress, uint64_t targetAddress) {
|
|
int32_t *loc32 = reinterpret_cast<int32_t*>(location);
|
|
switch ( (Kinds)kind ) {
|
|
case branch32:
|
|
*loc32 = (targetAddress - (fixupAddress+4)) + addend;
|
|
break;
|
|
case pointer32:
|
|
case abs32:
|
|
*loc32 = targetAddress + addend;
|
|
break;
|
|
case funcRel32:
|
|
*loc32 = targetAddress + addend;
|
|
break;
|
|
case none:
|
|
case lazyTarget:
|
|
case lazyImmediate:
|
|
case subordinateFDE:
|
|
case subordinateLSDA:
|
|
// do nothing
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// KindHandler_arm
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
KindHandler_arm::~KindHandler_arm() {
|
|
}
|
|
|
|
Reference::Kind KindHandler_arm::stringToKind(StringRef str) {
|
|
if ( str.equals("none") )
|
|
return none;
|
|
else if ( str.equals("thumbBranch22") )
|
|
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") )
|
|
return pointer32;
|
|
else if ( str.equals("lazyTarget") )
|
|
return lazyTarget;
|
|
else if ( str.equals("lazyImmediate") )
|
|
return lazyImmediate;
|
|
else if ( str.equals("subordinateLSDA") )
|
|
return subordinateLSDA;
|
|
|
|
assert(0 && "invalid ARM Reference kind");
|
|
return 0;
|
|
}
|
|
|
|
StringRef KindHandler_arm::kindToString(Reference::Kind kind) {
|
|
switch ( (Kinds)kind ) {
|
|
case none:
|
|
return StringRef("none");
|
|
case thumbBranch22:
|
|
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:
|
|
return StringRef("pointer32");
|
|
case lazyTarget:
|
|
return StringRef("lazyTarget");
|
|
case lazyImmediate:
|
|
return StringRef("lazyImmediate");
|
|
case subordinateLSDA:
|
|
return StringRef("subordinateLSDA");
|
|
}
|
|
assert(0 && "invalid ARM Reference kind");
|
|
return StringRef();
|
|
}
|
|
|
|
bool KindHandler_arm::isCallSite(Kind kind) {
|
|
return (kind == thumbBranch22) || (kind == armBranch24);
|
|
}
|
|
|
|
bool KindHandler_arm::isPointer(Kind kind) {
|
|
return (kind == pointer32);
|
|
}
|
|
|
|
|
|
bool KindHandler_arm::isLazyImmediate(Kind kind) {
|
|
return (kind == lazyImmediate);
|
|
}
|
|
|
|
|
|
bool KindHandler_arm::isLazyTarget(Kind kind) {
|
|
return (kind == lazyTarget);
|
|
}
|
|
|
|
|
|
void KindHandler_arm::applyFixup(Kind kind, uint64_t addend, uint8_t *location,
|
|
uint64_t fixupAddress, uint64_t targetAddress) {
|
|
//int32_t *loc32 = reinterpret_cast<int32_t*>(location);
|
|
switch ( (Kinds)kind ) {
|
|
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
|
|
break;
|
|
case pointer32:
|
|
// FIXME
|
|
break;
|
|
case none:
|
|
case lazyTarget:
|
|
case lazyImmediate:
|
|
case subordinateLSDA:
|
|
// do nothing
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace mach_o
|
|
} // namespace lld
|
|
|
|
|
|
|