]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/ReaderWriter/MachO/ArchHandler.cpp
Vendor import of lld trunk r233088:
[FreeBSD/FreeBSD.git] / lib / ReaderWriter / MachO / ArchHandler.cpp
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