Tidy up.
[oota-llvm.git] / lib / ExecutionEngine / RuntimeDyld / RuntimeDyldELF.cpp
1 //===-- RuntimeDyldELF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Implementation of ELF support for the MC-JIT runtime dynamic linker.
11 //
12 //===----------------------------------------------------------------------===//
13
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 "llvm/ADT/IntervalMap.h"
19 #include "RuntimeDyldImpl.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Support/ELF.h"
22 #include "llvm/ADT/Triple.h"
23 using namespace llvm;
24 using namespace llvm::object;
25
26 namespace llvm {
27
28 namespace {
29
30 // FIXME: this function should probably not live here...
31 //
32 // Returns the name and address of an unrelocated symbol in an ELF section
33 void getSymbolInfo(symbol_iterator Sym, uint64_t &Addr, StringRef &Name) {
34   //FIXME: error checking here required to catch corrupt ELF objects...
35   error_code Err = Sym->getName(Name);
36
37   uint64_t AddrInSection;
38   Err = Sym->getAddress(AddrInSection);
39
40   SectionRef empty_section;
41   section_iterator Section(empty_section);
42   Err = Sym->getSection(Section);
43
44   StringRef SectionContents;
45   Section->getContents(SectionContents);
46
47   Addr = reinterpret_cast<uint64_t>(SectionContents.data()) + AddrInSection;
48 }
49
50 }
51
52 bool RuntimeDyldELF::loadObject(MemoryBuffer *InputBuffer) {
53   if (!isCompatibleFormat(InputBuffer))
54     return true;
55
56   OwningPtr<ObjectFile> Obj(ObjectFile::createELFObjectFile(InputBuffer));
57
58   Arch = Obj->getArch();
59
60   // Map address in the Object file image to function names
61   IntervalMap<uint64_t, StringRef>::Allocator A;
62   IntervalMap<uint64_t, StringRef> FuncMap(A);
63
64   // This is a bit of a hack.  The ObjectFile we've just loaded reports
65   // section addresses as 0 and doesn't provide access to the section
66   // offset (from which we could calculate the address.  Instead,
67   // we're storing the address when it comes up in the ST_Debug case
68   // below.
69   //
70   StringMap<uint64_t> DebugSymbolMap;
71
72   symbol_iterator SymEnd = Obj->end_symbols();
73   error_code Err;
74   for (symbol_iterator Sym = Obj->begin_symbols();
75        Sym != SymEnd; Sym.increment(Err)) {
76     SymbolRef::Type Type;
77     Sym->getType(Type);
78     if (Type == SymbolRef::ST_Function) {
79       StringRef Name;
80       uint64_t Addr;
81       getSymbolInfo(Sym, Addr, Name);
82
83       uint64_t Size;
84       Err = Sym->getSize(Size);
85
86       uint8_t *Start;
87       uint8_t *End;
88       Start = reinterpret_cast<uint8_t*>(Addr);
89       End   = reinterpret_cast<uint8_t*>(Addr + Size - 1);
90
91       extractFunction(Name, Start, End);
92       FuncMap.insert(Addr, Addr + Size - 1, Name);
93     } else if (Type == SymbolRef::ST_Debug) {
94       // This case helps us find section addresses
95       StringRef Name;
96       uint64_t Addr;
97       getSymbolInfo(Sym, Addr, Name);
98       DebugSymbolMap[Name] = Addr;
99     }
100   }
101
102   // Iterate through the relocations for this object
103   section_iterator SecEnd = Obj->end_sections();
104   for (section_iterator Sec = Obj->begin_sections();
105        Sec != SecEnd; Sec.increment(Err)) {
106     StringRef SecName;
107     uint64_t  SecAddr;
108     Sec->getName(SecName);
109     // Ignore sections that aren't in our map
110     if (DebugSymbolMap.find(SecName) == DebugSymbolMap.end()) {
111       continue;
112     }
113     SecAddr = DebugSymbolMap[SecName];
114     relocation_iterator RelEnd = Sec->end_relocations();
115     for (relocation_iterator Rel = Sec->begin_relocations();
116          Rel != RelEnd; Rel.increment(Err)) {
117       uint64_t RelOffset;
118       uint64_t RelType;
119       int64_t RelAddend;
120       SymbolRef RelSym;
121       StringRef SymName;
122       uint64_t SymAddr;
123       uint64_t SymOffset;
124
125       Rel->getAddress(RelOffset);
126       Rel->getType(RelType);
127       Rel->getAdditionalInfo(RelAddend);
128       Rel->getSymbol(RelSym);
129       RelSym.getName(SymName);
130       RelSym.getAddress(SymAddr);
131       RelSym.getFileOffset(SymOffset);
132
133       // If this relocation is inside a function, we want to store the
134       // function name and a function-relative offset
135       IntervalMap<uint64_t, StringRef>::iterator ContainingFunc
136         = FuncMap.find(SecAddr + RelOffset);
137       if (ContainingFunc.valid()) {
138         // Re-base the relocation to make it relative to the target function
139         RelOffset = (SecAddr + RelOffset) - ContainingFunc.start();
140         Relocations[SymName].push_back(RelocationEntry(ContainingFunc.value(),
141                                                        RelOffset,
142                                                        RelType,
143                                                        RelAddend,
144                                                        true));
145       } else {
146         Relocations[SymName].push_back(RelocationEntry(SecName,
147                                                        RelOffset,
148                                                        RelType,
149                                                        RelAddend,
150                                                        false));
151       }
152     }
153   }
154   return false;
155 }
156
157 void RuntimeDyldELF::resolveRelocations() {
158   // FIXME: deprecated. should be changed to use the by-section
159   // allocation and relocation scheme.
160
161   // Just iterate over the symbols in our symbol table and assign their
162   // addresses.
163   StringMap<SymbolLoc>::iterator i = SymbolTable.begin();
164   StringMap<SymbolLoc>::iterator e = SymbolTable.end();
165   for (;i != e; ++i) {
166     assert (i->getValue().second == 0 && "non-zero offset in by-function sym!");
167     reassignSymbolAddress(i->getKey(),
168                           (uint8_t*)Sections[i->getValue().first].base());
169   }
170 }
171
172 void RuntimeDyldELF::resolveX86_64Relocation(StringRef Name,
173                                              uint8_t *Addr,
174                                              const RelocationEntry &RE) {
175   uint8_t *TargetAddr;
176   if (RE.IsFunctionRelative) {
177     StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(RE.Target);
178     assert(Loc != SymbolTable.end() && "Function for relocation not found");
179     TargetAddr =
180       reinterpret_cast<uint8_t*>(Sections[Loc->second.first].base()) +
181       Loc->second.second + RE.Offset;
182   } else {
183     // FIXME: Get the address of the target section and add that to RE.Offset
184     assert(0 && ("Non-function relocation not implemented yet!"));
185   }
186
187   switch (RE.Type) {
188   default:
189     assert(0 && ("Relocation type not implemented yet!"));
190   break;
191   case ELF::R_X86_64_64: {
192     uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
193     *Target = Addr + RE.Addend;
194     break;
195   }
196   case ELF::R_X86_64_32:
197   case ELF::R_X86_64_32S: {
198     uint64_t Value = reinterpret_cast<uint64_t>(Addr) + RE.Addend;
199     // FIXME: Handle the possibility of this assertion failing
200     assert((RE.Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
201            (RE.Type == ELF::R_X86_64_32S &&
202             (Value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL));
203     uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
204     uint32_t *Target = reinterpret_cast<uint32_t*>(TargetAddr);
205     *Target = TruncatedAddr;
206     break;
207   }
208   case ELF::R_X86_64_PC32: {
209     uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
210     uint64_t RealOffset = *Placeholder +
211                            reinterpret_cast<uint64_t>(Addr) +
212                            RE.Addend - reinterpret_cast<uint64_t>(TargetAddr);
213     assert((RealOffset & 0xFFFFFFFF) == RealOffset);
214     uint32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
215     *Placeholder = TruncOffset;
216     break;
217   }
218   }
219 }
220
221 void RuntimeDyldELF::resolveX86Relocation(StringRef Name,
222                                           uint8_t *Addr,
223                                           const RelocationEntry &RE) {
224   uint8_t *TargetAddr;
225   if (RE.IsFunctionRelative) {
226     StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(RE.Target);
227     assert(Loc != SymbolTable.end() && "Function for relocation not found");
228     TargetAddr =
229       reinterpret_cast<uint8_t*>(Sections[Loc->second.first].base()) +
230       Loc->second.second + RE.Offset;
231   } else {
232     // FIXME: Get the address of the target section and add that to RE.Offset
233     assert(0 && ("Non-function relocation not implemented yet!"));
234   }
235
236   switch (RE.Type) {
237   case ELF::R_386_32: {
238     uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
239     *Target = Addr + RE.Addend;
240     break;
241   }
242   case ELF::R_386_PC32: {
243     uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
244     uint32_t RealOffset = *Placeholder + reinterpret_cast<uintptr_t>(Addr) +
245                            RE.Addend - reinterpret_cast<uintptr_t>(TargetAddr);
246     *Placeholder = RealOffset;
247     break;
248     }
249     default:
250       // There are other relocation types, but it appears these are the
251       //  only ones currently used by the LLVM ELF object writer
252       assert(0 && ("Relocation type not implemented yet!"));
253       break;
254   }
255 }
256
257 void RuntimeDyldELF::resolveArmRelocation(StringRef Name,
258                                           uint8_t *Addr,
259                                           const RelocationEntry &RE) {
260 }
261
262 void RuntimeDyldELF::resolveRelocation(StringRef Name,
263                                        uint8_t *Addr,
264                                        const RelocationEntry &RE) {
265   switch (Arch) {
266   case Triple::x86_64:
267     resolveX86_64Relocation(Name, Addr, RE);
268     break;
269   case Triple::x86:
270     resolveX86Relocation(Name, Addr, RE);
271     break;
272   case Triple::arm:
273     resolveArmRelocation(Name, Addr, RE);
274     break;
275   default:
276     assert(0 && "Unsupported CPU type!");
277     break;
278   }
279 }
280
281 void RuntimeDyldELF::reassignSymbolAddress(StringRef Name, uint8_t *Addr) {
282   // FIXME: deprecated. switch to reassignSectionAddress() instead.
283   //
284   // Actually moving the symbol address requires by-section mapping.
285   assert(Sections[SymbolTable.lookup(Name).first].base() == (void*)Addr &&
286          "Unable to relocate section in by-function JIT allocation model!");
287
288   RelocationList &Relocs = Relocations[Name];
289   for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
290     RelocationEntry &RE = Relocs[i];
291     resolveRelocation(Name, Addr, RE);
292   }
293 }
294
295 // Assign an address to a symbol name and resolve all the relocations
296 // associated with it.
297 void RuntimeDyldELF::reassignSectionAddress(unsigned SectionID, uint64_t Addr) {
298   // The address to use for relocation resolution is not
299   // the address of the local section buffer. We must be doing
300   // a remote execution environment of some sort. Re-apply any
301   // relocations referencing this section with the given address.
302   //
303   // Addr is a uint64_t because we can't assume the pointer width
304   // of the target is the same as that of the host. Just use a generic
305   // "big enough" type.
306   assert(0);
307 }
308
309 bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {
310   StringRef Magic = InputBuffer->getBuffer().slice(0, ELF::EI_NIDENT);
311   return (memcmp(Magic.data(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
312 }
313 } // namespace llvm