1 //===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Implementation of the MC-JIT runtime dynamic linker.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "dyld"
15 #include "llvm/ADT/OwningPtr.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "RuntimeDyldMachO.h"
20 using namespace llvm::object;
24 void RuntimeDyldMachO::resolveRelocation(uint8_t *LocalAddress,
25 uint64_t FinalAddress,
29 bool isPCRel = (Type >> 24) & 1;
30 unsigned MachoType = (Type >> 28) & 0xf;
31 unsigned Size = 1 << ((Type >> 25) & 3);
33 DEBUG(dbgs() << "resolveRelocation LocalAddress: "
34 << format("%p", LocalAddress)
35 << " FinalAddress: " << format("%p", FinalAddress)
36 << " Value: " << format("%p", Value)
37 << " Addend: " << Addend
38 << " isPCRel: " << isPCRel
39 << " MachoType: " << MachoType
43 // This just dispatches to the proper target specific routine.
45 default: llvm_unreachable("Unsupported CPU type!");
47 resolveX86_64Relocation(LocalAddress,
56 resolveI386Relocation(LocalAddress,
64 case Triple::arm: // Fall through.
66 resolveARMRelocation(LocalAddress,
77 bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress,
78 uint64_t FinalAddress,
85 Value -= FinalAddress + 4; // see resolveX86_64Relocation
89 llvm_unreachable("Invalid relocation type!");
90 case macho::RIT_Vanilla: {
91 uint8_t *p = LocalAddress;
92 uint64_t ValueToWrite = Value + Addend;
93 for (unsigned i = 0; i < Size; ++i) {
94 *p++ = (uint8_t)(ValueToWrite & 0xff);
98 case macho::RIT_Difference:
99 case macho::RIT_Generic_LocalDifference:
100 case macho::RIT_Generic_PreboundLazyPointer:
101 return Error("Relocation type not implemented yet!");
105 bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress,
106 uint64_t FinalAddress,
112 // If the relocation is PC-relative, the value to be encoded is the
113 // pointer difference.
115 // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
116 // address. Is that expected? Only for branches, perhaps?
117 Value -= FinalAddress + 4;
121 llvm_unreachable("Invalid relocation type!");
122 case macho::RIT_X86_64_Signed1:
123 case macho::RIT_X86_64_Signed2:
124 case macho::RIT_X86_64_Signed4:
125 case macho::RIT_X86_64_Signed:
126 case macho::RIT_X86_64_Unsigned:
127 case macho::RIT_X86_64_Branch: {
129 // Mask in the target value a byte at a time (we don't have an alignment
130 // guarantee for the target address, so this is safest).
131 uint8_t *p = (uint8_t*)LocalAddress;
132 for (unsigned i = 0; i < Size; ++i) {
133 *p++ = (uint8_t)Value;
138 case macho::RIT_X86_64_GOTLoad:
139 case macho::RIT_X86_64_GOT:
140 case macho::RIT_X86_64_Subtractor:
141 case macho::RIT_X86_64_TLV:
142 return Error("Relocation type not implemented yet!");
146 bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress,
147 uint64_t FinalAddress,
153 // If the relocation is PC-relative, the value to be encoded is the
154 // pointer difference.
156 Value -= FinalAddress;
157 // ARM PCRel relocations have an effective-PC offset of two instructions
158 // (four bytes in Thumb mode, 8 bytes in ARM mode).
159 // FIXME: For now, assume ARM mode.
165 llvm_unreachable("Invalid relocation type!");
166 case macho::RIT_Vanilla: {
167 // Mask in the target value a byte at a time (we don't have an alignment
168 // guarantee for the target address, so this is safest).
169 uint8_t *p = (uint8_t*)LocalAddress;
170 for (unsigned i = 0; i < Size; ++i) {
171 *p++ = (uint8_t)Value;
176 case macho::RIT_ARM_Branch24Bit: {
177 // Mask the value into the target address. We know instructions are
178 // 32-bit aligned, so we can do it all at once.
179 uint32_t *p = (uint32_t*)LocalAddress;
180 // The low two bits of the value are not encoded.
182 // Mask the value to 24 bits.
184 // FIXME: If the destination is a Thumb function (and the instruction
185 // is a non-predicated BL instruction), we need to change it to a BLX
186 // instruction instead.
188 // Insert the value into the instruction.
189 *p = (*p & ~0xffffff) | Value;
192 case macho::RIT_ARM_ThumbBranch22Bit:
193 case macho::RIT_ARM_ThumbBranch32Bit:
194 case macho::RIT_ARM_Half:
195 case macho::RIT_ARM_HalfDifference:
196 case macho::RIT_Pair:
197 case macho::RIT_Difference:
198 case macho::RIT_ARM_LocalDifference:
199 case macho::RIT_ARM_PreboundLazyPointer:
200 return Error("Relocation type not implemented yet!");
205 void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
207 ObjSectionToIDMap &ObjSectionToID,
208 const SymbolTableMap &Symbols,
211 uint32_t RelType = (uint32_t) (Rel.Type & 0xffffffffL);
212 RelocationValueRef Value;
213 SectionEntry &Section = Sections[Rel.SectionID];
214 uint8_t *Target = Section.Address + Rel.Offset;
216 bool isExtern = (RelType >> 27) & 1;
218 // Obtain the symbol name which is referenced in the relocation
219 StringRef TargetName;
220 const SymbolRef &Symbol = Rel.Symbol;
221 Symbol.getName(TargetName);
222 // First search for the symbol in the local symbol table
223 SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
224 if (lsi != Symbols.end()) {
225 Value.SectionID = lsi->second.first;
226 Value.Addend = lsi->second.second;
228 // Search for the symbol in the global symbol table
229 SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data());
230 if (gsi != GlobalSymbolTable.end()) {
231 Value.SectionID = gsi->second.first;
232 Value.Addend = gsi->second.second;
234 Value.SymbolName = TargetName.data();
238 uint8_t sectionIndex = static_cast<uint8_t>(RelType & 0xFF);
239 section_iterator si = Obj.begin_sections(),
240 se = Obj.end_sections();
241 for (uint8_t i = 1; i < sectionIndex; i++) {
247 assert(si != se && "No section containing relocation!");
248 Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID);
249 Value.Addend = *(const intptr_t *)Target;
251 // The MachO addend is an offset from the current section. We need it
252 // to be an offset from the destination section
253 Value.Addend += Section.ObjAddress - Sections[Value.SectionID].ObjAddress;
257 if (Arch == Triple::arm && RelType == macho::RIT_ARM_Branch24Bit) {
258 // This is an ARM branch relocation, need to use a stub function.
260 // Look up for existing stub.
261 StubMap::const_iterator i = Stubs.find(Value);
262 if (i != Stubs.end())
263 resolveRelocation(Target, (uint64_t)Target,
264 (uint64_t)Section.Address + i->second,
267 // Create a new stub function.
268 Stubs[Value] = Section.StubOffset;
269 uint8_t *StubTargetAddr = createStubFunction(Section.Address +
271 RelocationEntry RE(Rel.SectionID, StubTargetAddr - Section.Address,
272 macho::RIT_Vanilla, Value.Addend);
273 if (Value.SymbolName)
274 addRelocationForSymbol(RE, Value.SymbolName);
276 addRelocationForSection(RE, Value.SectionID);
277 resolveRelocation(Target, (uint64_t)Target,
278 (uint64_t)Section.Address + Section.StubOffset,
280 Section.StubOffset += getMaxStubSize();
283 RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend);
284 if (Value.SymbolName)
285 addRelocationForSymbol(RE, Value.SymbolName);
287 addRelocationForSection(RE, Value.SectionID);
292 bool RuntimeDyldMachO::isCompatibleFormat(
293 const MemoryBuffer *InputBuffer) const {
294 StringRef Magic = InputBuffer->getBuffer().slice(0, 4);
295 if (Magic == "\xFE\xED\xFA\xCE") return true;
296 if (Magic == "\xCE\xFA\xED\xFE") return true;
297 if (Magic == "\xFE\xED\xFA\xCF") return true;
298 if (Magic == "\xCF\xFA\xED\xFE") return true;
302 } // end namespace llvm