1 //===- lib/FileFormat/MachO/ArchHandler.cpp -------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 11 #include "ArchHandler.h" 12 #include "Atoms.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" 18 19 using namespace llvm::MachO; 20 using namespace lld::mach_o::normalized; 21 22 namespace lld { 23 namespace mach_o { 24 25 26 ArchHandler::ArchHandler() { 27 } 28 29 ArchHandler::~ArchHandler() { 30 } 31 32 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create( 33 MachOLinkingContext::Arch arch) { 34 switch (arch) { 35 case MachOLinkingContext::arch_x86_64: 36 return create_x86_64(); 37 case MachOLinkingContext::arch_x86: 38 return create_x86(); 39 case MachOLinkingContext::arch_armv6: 40 case MachOLinkingContext::arch_armv7: 41 case MachOLinkingContext::arch_armv7s: 42 return create_arm(); 43 case MachOLinkingContext::arch_arm64: 44 return create_arm64(); 45 default: 46 llvm_unreachable("Unknown arch"); 47 } 48 } 49 50 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) 55 return false; 56 if (ref.kindArch() != info.lazyPointerReferenceToFinal.arch) 57 return false; 58 return (ref.kindValue() == info.lazyPointerReferenceToFinal.kind); 59 } 60 61 62 ArchHandler::RelocPattern ArchHandler::relocPattern(const Relocation &reloc) { 63 assert((reloc.type & 0xFFF0) == 0); 64 uint16_t result = reloc.type; 65 if (reloc.scattered) 66 result |= rScattered; 67 if (reloc.pcRel) 68 result |= rPcRel; 69 if (reloc.isExtern) 70 result |= rExtern; 71 switch(reloc.length) { 72 case 0: 73 break; 74 case 1: 75 result |= rLength2; 76 break; 77 case 2: 78 result |= rLength4; 79 break; 80 case 3: 81 result |= rLength8; 82 break; 83 default: 84 llvm_unreachable("bad r_length"); 85 } 86 return result; 87 } 88 89 normalized::Relocation 90 ArchHandler::relocFromPattern(ArchHandler::RelocPattern pattern) { 91 normalized::Relocation result; 92 result.offset = 0; 93 result.scattered = (pattern & rScattered); 94 result.type = (RelocationInfoType)(pattern & 0xF); 95 result.pcRel = (pattern & rPcRel); 96 result.isExtern = (pattern & rExtern); 97 result.value = 0; 98 result.symbol = 0; 99 switch (pattern & 0x300) { 100 case rLength1: 101 result.length = 0; 102 break; 103 case rLength2: 104 result.length = 1; 105 break; 106 case rLength4: 107 result.length = 2; 108 break; 109 case rLength8: 110 result.length = 3; 111 break; 112 } 113 return result; 114 } 115 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; 122 reloc.value = value; 123 relocs.push_back(reloc); 124 } 125 126 127 int16_t ArchHandler::readS16(const uint8_t *addr, bool isBig) { 128 return read16(addr, isBig); 129 } 130 131 int32_t ArchHandler::readS32(const uint8_t *addr, bool isBig) { 132 return read32(addr, isBig); 133 } 134 135 uint32_t ArchHandler::readU32(const uint8_t *addr, bool isBig) { 136 return read32(addr, isBig); 137 } 138 139 int64_t ArchHandler::readS64(const uint8_t *addr, bool isBig) { 140 return read64(addr, isBig); 141 } 142 143 bool ArchHandler::isDwarfCIE(bool isBig, const DefinedAtom *atom) { 144 assert(atom->contentType() == DefinedAtom::typeCFI); 145 if (atom->rawContent().size() < sizeof(uint32_t)) 146 return false; 147 uint32_t size = read32(atom->rawContent().data(), isBig); 148 149 uint32_t idOffset = sizeof(uint32_t); 150 if (size == 0xffffffffU) 151 idOffset += sizeof(uint64_t); 152 153 return read32(atom->rawContent().data() + idOffset, isBig) == 0; 154 } 155 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(); 162 } 163 } 164 165 return nullptr; 166 } 167 168 } // namespace mach_o 169 } // namespace lld 170 171 172 173