RuntimeDyldELF.cpp revision 61425c0a7f4e3608a85f7bbf254cd052a15b7446
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"
23using namespace llvm;
24using namespace llvm::object;
25
26namespace llvm {
27
28namespace {
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
33void 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
52bool 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
157void 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
172void 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
221void 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
257void RuntimeDyldELF::resolveArmRelocation(StringRef Name,
258                                          uint8_t *Addr,
259                                          const RelocationEntry &RE) {
260}
261
262void 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
281void 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.
297void 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
309bool 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
314