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" 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::resolveX86_64Relocation(StringRef Name, 158 uint8_t *Addr, 159 const RelocationEntry &RE) { 160 uint8_t *TargetAddr; 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()) + 167 RE.Offset; 168 } else { 169 // FIXME: Get the address of the target section and add that to RE.Offset 170 assert(0 && ("Non-function relocation not implemented yet!")); 171 } 172 173 switch (RE.Type) { 174 default: 175 assert(0 && ("Relocation type not implemented yet!")); 176 break; 177 case ELF::R_X86_64_64: { 178 uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr); 179 *Target = Addr + RE.Addend; 180 break; 181 } 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 & 0xFFFFFFFF00000000ULL)) || 187 (RE.Type == ELF::R_X86_64_32S && 188 (Value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL)); 189 uint32_t TruncatedAddr = (Value & 0xFFFFFFFF); 190 uint32_t *Target = reinterpret_cast<uint32_t*>(TargetAddr); 191 *Target = TruncatedAddr; 192 break; 193 } 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; 202 break; 203 } 204 } 205 } 206 207 void RuntimeDyldELF::resolveX86Relocation(StringRef Name, 208 uint8_t *Addr, 209 const RelocationEntry &RE) { 210 uint8_t *TargetAddr; 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; 218 } else { 219 // FIXME: Get the address of the target section and add that to RE.Offset 220 assert(0 && ("Non-function relocation not implemented yet!")); 221 } 222 223 switch (RE.Type) { 224 case ELF::R_386_32: { 225 uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr); 226 *Target = Addr + RE.Addend; 227 break; 228 } 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; 234 break; 235 } 236 default: 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!")); 240 break; 241 } 242 } 243 244 void RuntimeDyldELF::resolveArmRelocation(StringRef Name, 245 uint8_t *Addr, 246 const RelocationEntry &RE) { 247 } 248 249 void RuntimeDyldELF::resolveRelocation(StringRef Name, 250 uint8_t *Addr, 251 const RelocationEntry &RE) { 252 switch (Arch) { 253 case Triple::x86_64: 254 resolveX86_64Relocation(Name, Addr, RE); 255 break; 256 case Triple::x86: 257 resolveX86Relocation(Name, Addr, RE); 258 break; 259 case Triple::arm: 260 resolveArmRelocation(Name, Addr, RE); 261 break; 262 default: 263 assert(0 && "Unsupported CPU type!"); 264 break; 265 } 266 } 267 268 void RuntimeDyldELF::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { 269 SymbolTable[Name] = Addr; 270 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); 275 } 276 } 277 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; 281 } 282 } // namespace llvm 283