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