blob: e15b200c5e098d3e260264e62aa876b7f4218586 [file] [log] [blame]
Jim Grosbache0934be2012-01-16 23:50:58 +00001//===-- RuntimeDyldELF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-===//
Eli Benderskya66a1852012-01-16 08:56:09 +00002//
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"
Eli Bendersky76463fd2012-01-22 07:05:02 +000019#include "RuntimeDyldELF.h"
Eli Benderskya66a1852012-01-16 08:56:09 +000020#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
Jim Grosbach61425c02012-01-16 22:26:39 +0000157void 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
Eli Benderskya66a1852012-01-16 08:56:09 +0000172void RuntimeDyldELF::resolveX86_64Relocation(StringRef Name,
173 uint8_t *Addr,
174 const RelocationEntry &RE) {
175 uint8_t *TargetAddr;
176 if (RE.IsFunctionRelative) {
Jim Grosbach61425c02012-01-16 22:26:39 +0000177 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;
Eli Benderskya66a1852012-01-16 08:56:09 +0000182 } else {
183 // FIXME: Get the address of the target section and add that to RE.Offset
Duncan Sands408a25c2012-02-05 14:14:35 +0000184 llvm_unreachable("Non-function relocation not implemented yet!");
Eli Benderskya66a1852012-01-16 08:56:09 +0000185 }
186
187 switch (RE.Type) {
Craig Topper85814382012-02-07 05:05:23 +0000188 default: llvm_unreachable("Relocation type not implemented yet!");
Eli Benderskya66a1852012-01-16 08:56:09 +0000189 case ELF::R_X86_64_64: {
190 uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
191 *Target = Addr + RE.Addend;
192 break;
193 }
194 case ELF::R_X86_64_32:
195 case ELF::R_X86_64_32S: {
196 uint64_t Value = reinterpret_cast<uint64_t>(Addr) + RE.Addend;
197 // FIXME: Handle the possibility of this assertion failing
Eli Bendersky92238222012-01-16 09:31:10 +0000198 assert((RE.Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
Eli Benderskya66a1852012-01-16 08:56:09 +0000199 (RE.Type == ELF::R_X86_64_32S &&
Eli Bendersky92238222012-01-16 09:31:10 +0000200 (Value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL));
Eli Benderskya66a1852012-01-16 08:56:09 +0000201 uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
202 uint32_t *Target = reinterpret_cast<uint32_t*>(TargetAddr);
203 *Target = TruncatedAddr;
204 break;
205 }
206 case ELF::R_X86_64_PC32: {
207 uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
208 uint64_t RealOffset = *Placeholder +
209 reinterpret_cast<uint64_t>(Addr) +
210 RE.Addend - reinterpret_cast<uint64_t>(TargetAddr);
211 assert((RealOffset & 0xFFFFFFFF) == RealOffset);
212 uint32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
213 *Placeholder = TruncOffset;
214 break;
215 }
216 }
217}
218
219void RuntimeDyldELF::resolveX86Relocation(StringRef Name,
220 uint8_t *Addr,
221 const RelocationEntry &RE) {
222 uint8_t *TargetAddr;
223 if (RE.IsFunctionRelative) {
Jim Grosbach61425c02012-01-16 22:26:39 +0000224 StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(RE.Target);
225 assert(Loc != SymbolTable.end() && "Function for relocation not found");
226 TargetAddr =
227 reinterpret_cast<uint8_t*>(Sections[Loc->second.first].base()) +
228 Loc->second.second + RE.Offset;
Eli Benderskya66a1852012-01-16 08:56:09 +0000229 } else {
230 // FIXME: Get the address of the target section and add that to RE.Offset
Duncan Sands408a25c2012-02-05 14:14:35 +0000231 llvm_unreachable("Non-function relocation not implemented yet!");
Eli Benderskya66a1852012-01-16 08:56:09 +0000232 }
233
234 switch (RE.Type) {
235 case ELF::R_386_32: {
236 uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
237 *Target = Addr + RE.Addend;
238 break;
239 }
240 case ELF::R_386_PC32: {
241 uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
242 uint32_t RealOffset = *Placeholder + reinterpret_cast<uintptr_t>(Addr) +
243 RE.Addend - reinterpret_cast<uintptr_t>(TargetAddr);
244 *Placeholder = RealOffset;
245 break;
246 }
247 default:
248 // There are other relocation types, but it appears these are the
249 // only ones currently used by the LLVM ELF object writer
Craig Topper85814382012-02-07 05:05:23 +0000250 llvm_unreachable("Relocation type not implemented yet!");
Eli Benderskya66a1852012-01-16 08:56:09 +0000251 }
252}
253
254void RuntimeDyldELF::resolveArmRelocation(StringRef Name,
255 uint8_t *Addr,
256 const RelocationEntry &RE) {
257}
258
259void RuntimeDyldELF::resolveRelocation(StringRef Name,
260 uint8_t *Addr,
261 const RelocationEntry &RE) {
262 switch (Arch) {
263 case Triple::x86_64:
264 resolveX86_64Relocation(Name, Addr, RE);
265 break;
266 case Triple::x86:
267 resolveX86Relocation(Name, Addr, RE);
268 break;
269 case Triple::arm:
270 resolveArmRelocation(Name, Addr, RE);
271 break;
Craig Topper85814382012-02-07 05:05:23 +0000272 default: llvm_unreachable("Unsupported CPU type!");
Eli Benderskya66a1852012-01-16 08:56:09 +0000273 }
274}
275
276void RuntimeDyldELF::reassignSymbolAddress(StringRef Name, uint8_t *Addr) {
Jim Grosbach61425c02012-01-16 22:26:39 +0000277 // FIXME: deprecated. switch to reassignSectionAddress() instead.
278 //
279 // Actually moving the symbol address requires by-section mapping.
280 assert(Sections[SymbolTable.lookup(Name).first].base() == (void*)Addr &&
281 "Unable to relocate section in by-function JIT allocation model!");
Eli Benderskya66a1852012-01-16 08:56:09 +0000282
283 RelocationList &Relocs = Relocations[Name];
284 for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
285 RelocationEntry &RE = Relocs[i];
286 resolveRelocation(Name, Addr, RE);
287 }
288}
289
Jim Grosbach61425c02012-01-16 22:26:39 +0000290// Assign an address to a symbol name and resolve all the relocations
291// associated with it.
292void RuntimeDyldELF::reassignSectionAddress(unsigned SectionID, uint64_t Addr) {
293 // The address to use for relocation resolution is not
294 // the address of the local section buffer. We must be doing
295 // a remote execution environment of some sort. Re-apply any
296 // relocations referencing this section with the given address.
297 //
298 // Addr is a uint64_t because we can't assume the pointer width
299 // of the target is the same as that of the host. Just use a generic
300 // "big enough" type.
301 assert(0);
302}
303
Eli Benderskya66a1852012-01-16 08:56:09 +0000304bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {
305 StringRef Magic = InputBuffer->getBuffer().slice(0, ELF::EI_NIDENT);
306 return (memcmp(Magic.data(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
307}
308} // namespace llvm