forked from OSchip/llvm-project
110 lines
2.7 KiB
C++
110 lines
2.7 KiB
C++
|
//===- lib/FileFormat/MachO/ArchHandler.cpp -------------------------------===//
|
||
|
//
|
||
|
// The LLVM Linker
|
||
|
//
|
||
|
// This file is distributed under the University of Illinois Open Source
|
||
|
// License. See LICENSE.TXT for details.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
|
||
|
#include "ArchHandler.h"
|
||
|
#include "Atoms.h"
|
||
|
#include "MachONormalizedFileBinaryUtils.h"
|
||
|
|
||
|
#include "llvm/ADT/StringRef.h"
|
||
|
#include "llvm/ADT/StringSwitch.h"
|
||
|
#include "llvm/ADT/Triple.h"
|
||
|
|
||
|
#include "llvm/Support/ErrorHandling.h"
|
||
|
|
||
|
using namespace llvm::MachO;
|
||
|
using namespace lld::mach_o::normalized;
|
||
|
|
||
|
namespace lld {
|
||
|
namespace mach_o {
|
||
|
|
||
|
|
||
|
ArchHandler::ArchHandler() {
|
||
|
}
|
||
|
|
||
|
ArchHandler::~ArchHandler() {
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create(
|
||
|
MachOLinkingContext::Arch arch) {
|
||
|
switch (arch) {
|
||
|
case MachOLinkingContext::arch_x86_64:
|
||
|
return create_x86_64();
|
||
|
case MachOLinkingContext::arch_x86:
|
||
|
return create_x86();
|
||
|
case MachOLinkingContext::arch_armv6:
|
||
|
case MachOLinkingContext::arch_armv7:
|
||
|
case MachOLinkingContext::arch_armv7s:
|
||
|
return create_arm();
|
||
|
default:
|
||
|
llvm_unreachable("Unknown arch");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
bool ArchHandler::isLazyPointer(const Reference &ref) {
|
||
|
// A lazy bind entry is needed for a lazy pointer.
|
||
|
const StubInfo &info = stubInfo();
|
||
|
if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
|
||
|
return false;
|
||
|
if (ref.kindArch() != info.lazyPointerReferenceToFinal.arch)
|
||
|
return false;
|
||
|
return (ref.kindValue() == info.lazyPointerReferenceToFinal.kind);
|
||
|
}
|
||
|
|
||
|
|
||
|
ArchHandler::RelocPattern ArchHandler::relocPattern(const Relocation &reloc) {
|
||
|
assert((reloc.type & 0xFFF0) == 0);
|
||
|
uint16_t result = reloc.type;
|
||
|
if (reloc.scattered)
|
||
|
result |= rScattered;
|
||
|
if (reloc.pcRel)
|
||
|
result |= rPcRel;
|
||
|
if (reloc.isExtern)
|
||
|
result |= rExtern;
|
||
|
switch(reloc.length) {
|
||
|
case 0:
|
||
|
break;
|
||
|
case 1:
|
||
|
result |= rLength2;
|
||
|
break;
|
||
|
case 2:
|
||
|
result |= rLength4;
|
||
|
break;
|
||
|
case 3:
|
||
|
result |= rLength8;
|
||
|
break;
|
||
|
default:
|
||
|
llvm_unreachable("bad r_length");
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
int16_t ArchHandler::readS16(bool swap, const uint8_t *addr) {
|
||
|
return read16(swap, *reinterpret_cast<const uint16_t*>(addr));
|
||
|
}
|
||
|
|
||
|
int32_t ArchHandler::readS32(bool swap, const uint8_t *addr) {
|
||
|
return read32(swap, *reinterpret_cast<const uint32_t*>(addr));
|
||
|
}
|
||
|
|
||
|
uint32_t ArchHandler::readU32(bool swap, const uint8_t *addr) {
|
||
|
return read32(swap, *reinterpret_cast<const uint32_t*>(addr));
|
||
|
}
|
||
|
|
||
|
int64_t ArchHandler::readS64(bool swap, const uint8_t *addr) {
|
||
|
return read64(swap, *reinterpret_cast<const uint64_t*>(addr));
|
||
|
}
|
||
|
|
||
|
} // namespace mach_o
|
||
|
} // namespace lld
|
||
|
|
||
|
|
||
|
|