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 "RuntimeDyldELF.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 llvm_unreachable("Non-function relocation not implemented yet!"); 185 } 186 187 switch (RE.Type) { 188 default: llvm_unreachable("Relocation type not implemented yet!"); 189 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 198 assert((RE.Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) || 199 (RE.Type == ELF::R_X86_64_32S && 200 (Value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL)); 201 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 219 void RuntimeDyldELF::resolveX86Relocation(StringRef Name, 220 uint8_t *Addr, 221 const RelocationEntry &RE) { 222 uint8_t *TargetAddr; 223 if (RE.IsFunctionRelative) { 224 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; 229 } else { 230 // FIXME: Get the address of the target section and add that to RE.Offset 231 llvm_unreachable("Non-function relocation not implemented yet!"); 232 } 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 250 llvm_unreachable("Relocation type not implemented yet!"); 251 } 252 } 253 254 void RuntimeDyldELF::resolveArmRelocation(StringRef Name, 255 uint8_t *Addr, 256 const RelocationEntry &RE) { 257 } 258 259 void 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; 272 default: llvm_unreachable("Unsupported CPU type!"); 273 } 274 } 275 276 void RuntimeDyldELF::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { 277 // 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!"); 282 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 290 // Assign an address to a symbol name and resolve all the relocations 291 // associated with it. 292 void 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 304 bool 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 309