1 //===- lib/FileFormat/MachO/ArchHandler.cpp -------------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "ArchHandler.h"
13 #include "MachONormalizedFileBinaryUtils.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/ADT/Triple.h"
17 #include "llvm/Support/ErrorHandling.h"
19 using namespace llvm::MachO;
20 using namespace lld::mach_o::normalized;
26 ArchHandler::ArchHandler() {
29 ArchHandler::~ArchHandler() {
32 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create(
33 MachOLinkingContext::Arch arch) {
35 case MachOLinkingContext::arch_x86_64:
36 return create_x86_64();
37 case MachOLinkingContext::arch_x86:
39 case MachOLinkingContext::arch_armv6:
40 case MachOLinkingContext::arch_armv7:
41 case MachOLinkingContext::arch_armv7s:
43 case MachOLinkingContext::arch_arm64:
44 return create_arm64();
46 llvm_unreachable("Unknown arch");
51 bool ArchHandler::isLazyPointer(const Reference &ref) {
52 // A lazy bind entry is needed for a lazy pointer.
53 const StubInfo &info = stubInfo();
54 if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
56 if (ref.kindArch() != info.lazyPointerReferenceToFinal.arch)
58 return (ref.kindValue() == info.lazyPointerReferenceToFinal.kind);
62 ArchHandler::RelocPattern ArchHandler::relocPattern(const Relocation &reloc) {
63 assert((reloc.type & 0xFFF0) == 0);
64 uint16_t result = reloc.type;
71 switch(reloc.length) {
84 llvm_unreachable("bad r_length");
89 normalized::Relocation
90 ArchHandler::relocFromPattern(ArchHandler::RelocPattern pattern) {
91 normalized::Relocation result;
93 result.scattered = (pattern & rScattered);
94 result.type = (RelocationInfoType)(pattern & 0xF);
95 result.pcRel = (pattern & rPcRel);
96 result.isExtern = (pattern & rExtern);
99 switch (pattern & 0x300) {
116 void ArchHandler::appendReloc(normalized::Relocations &relocs, uint32_t offset,
117 uint32_t symbol, uint32_t value,
118 RelocPattern pattern) {
119 normalized::Relocation reloc = relocFromPattern(pattern);
120 reloc.offset = offset;
121 reloc.symbol = symbol;
123 relocs.push_back(reloc);
127 int16_t ArchHandler::readS16(const uint8_t *addr, bool isBig) {
128 return read16(addr, isBig);
131 int32_t ArchHandler::readS32(const uint8_t *addr, bool isBig) {
132 return read32(addr, isBig);
135 uint32_t ArchHandler::readU32(const uint8_t *addr, bool isBig) {
136 return read32(addr, isBig);
139 int64_t ArchHandler::readS64(const uint8_t *addr, bool isBig) {
140 return read64(addr, isBig);
143 bool ArchHandler::isDwarfCIE(bool isBig, const DefinedAtom *atom) {
144 assert(atom->contentType() == DefinedAtom::typeCFI);
145 if (atom->rawContent().size() < sizeof(uint32_t))
147 uint32_t size = read32(atom->rawContent().data(), isBig);
149 uint32_t idOffset = sizeof(uint32_t);
150 if (size == 0xffffffffU)
151 idOffset += sizeof(uint64_t);
153 return read32(atom->rawContent().data() + idOffset, isBig) == 0;
156 const Atom *ArchHandler::fdeTargetFunction(const DefinedAtom *fde) {
157 for (auto ref : *fde) {
158 if (ref->kindNamespace() == Reference::KindNamespace::mach_o &&
159 ref->kindValue() == unwindRefToFunctionKind()) {
160 assert(ref->kindArch() == kindArch() && "unexpected Reference arch");
161 return ref->target();
168 } // namespace mach_o