1 //===-- RuntimeDyldELF.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 ELF support for 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 "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"
24 using namespace llvm::object;
30 // FIXME: this function should probably not live here...
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);
37 uint64_t AddrInSection;
38 Err = Sym->getAddress(AddrInSection);
40 SectionRef empty_section;
41 section_iterator Section(empty_section);
42 Err = Sym->getSection(Section);
44 StringRef SectionContents;
45 Section->getContents(SectionContents);
47 Addr = reinterpret_cast<uint64_t>(SectionContents.data()) + AddrInSection;
52 bool RuntimeDyldELF::loadObject(MemoryBuffer *InputBuffer) {
53 if (!isCompatibleFormat(InputBuffer))
56 OwningPtr<ObjectFile> Obj(ObjectFile::createELFObjectFile(InputBuffer));
58 Arch = Obj->getArch();
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);
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
70 StringMap<uint64_t> DebugSymbolMap;
72 symbol_iterator SymEnd = Obj->end_symbols();
74 for (symbol_iterator Sym = Obj->begin_symbols();
75 Sym != SymEnd; Sym.increment(Err)) {
78 if (Type == SymbolRef::ST_Function) {
81 getSymbolInfo(Sym, Addr, Name);
84 Err = Sym->getSize(Size);
88 Start = reinterpret_cast<uint8_t*>(Addr);
89 End = reinterpret_cast<uint8_t*>(Addr + Size - 1);
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
97 getSymbolInfo(Sym, Addr, Name);
98 DebugSymbolMap[Name] = Addr;
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)) {
108 Sec->getName(SecName);
109 // Ignore sections that aren't in our map
110 if (DebugSymbolMap.find(SecName) == DebugSymbolMap.end()) {
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)) {
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);
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(),
146 Relocations[SymName].push_back(RelocationEntry(SecName,
157 void RuntimeDyldELF::resolveX86_64Relocation(StringRef Name,
159 const RelocationEntry &RE) {
161 if (RE.IsFunctionRelative) {
162 StringMap<sys::MemoryBlock>::iterator ContainingFunc
163 = Functions.find(RE.Target);
164 assert(ContainingFunc != Functions.end()
165 && "Function for relocation not found");
166 TargetAddr = reinterpret_cast<uint8_t*>(ContainingFunc->getValue().base()) +
169 // FIXME: Get the address of the target section and add that to RE.Offset
170 assert(0 && ("Non-function relocation not implemented yet!"));
175 assert(0 && ("Relocation type not implemented yet!"));
177 case ELF::R_X86_64_64: {
178 uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
179 *Target = Addr + RE.Addend;
182 case ELF::R_X86_64_32:
183 case ELF::R_X86_64_32S: {
184 uint64_t Value = reinterpret_cast<uint64_t>(Addr) + RE.Addend;
185 // FIXME: Handle the possibility of this assertion failing
186 assert((RE.Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000)) ||
187 (RE.Type == ELF::R_X86_64_32S &&
188 (Value & 0xFFFFFFFF00000000) == 0xFFFFFFFF00000000));
189 uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
190 uint32_t *Target = reinterpret_cast<uint32_t*>(TargetAddr);
191 *Target = TruncatedAddr;
194 case ELF::R_X86_64_PC32: {
195 uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
196 uint64_t RealOffset = *Placeholder +
197 reinterpret_cast<uint64_t>(Addr) +
198 RE.Addend - reinterpret_cast<uint64_t>(TargetAddr);
199 assert((RealOffset & 0xFFFFFFFF) == RealOffset);
200 uint32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
201 *Placeholder = TruncOffset;
207 void RuntimeDyldELF::resolveX86Relocation(StringRef Name,
209 const RelocationEntry &RE) {
211 if (RE.IsFunctionRelative) {
212 StringMap<sys::MemoryBlock>::iterator ContainingFunc
213 = Functions.find(RE.Target);
214 assert(ContainingFunc != Functions.end()
215 && "Function for relocation not found");
216 TargetAddr = reinterpret_cast<uint8_t*>(
217 ContainingFunc->getValue().base()) + RE.Offset;
219 // FIXME: Get the address of the target section and add that to RE.Offset
220 assert(0 && ("Non-function relocation not implemented yet!"));
224 case ELF::R_386_32: {
225 uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
226 *Target = Addr + RE.Addend;
229 case ELF::R_386_PC32: {
230 uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
231 uint32_t RealOffset = *Placeholder + reinterpret_cast<uintptr_t>(Addr) +
232 RE.Addend - reinterpret_cast<uintptr_t>(TargetAddr);
233 *Placeholder = RealOffset;
237 // There are other relocation types, but it appears these are the
238 // only ones currently used by the LLVM ELF object writer
239 assert(0 && ("Relocation type not implemented yet!"));
244 void RuntimeDyldELF::resolveArmRelocation(StringRef Name,
246 const RelocationEntry &RE) {
249 void RuntimeDyldELF::resolveRelocation(StringRef Name,
251 const RelocationEntry &RE) {
254 resolveX86_64Relocation(Name, Addr, RE);
257 resolveX86Relocation(Name, Addr, RE);
260 resolveArmRelocation(Name, Addr, RE);
263 assert(0 && "Unsupported CPU type!");
268 void RuntimeDyldELF::reassignSymbolAddress(StringRef Name, uint8_t *Addr) {
269 SymbolTable[Name] = Addr;
271 RelocationList &Relocs = Relocations[Name];
272 for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
273 RelocationEntry &RE = Relocs[i];
274 resolveRelocation(Name, Addr, RE);
278 bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {
279 StringRef Magic = InputBuffer->getBuffer().slice(0, ELF::EI_NIDENT);
280 return (memcmp(Magic.data(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;