RuntimeDyldMachO.cpp revision 263508
1//===-- RuntimeDyldMachO.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 the MC-JIT runtime dynamic linker. 11// 12//===----------------------------------------------------------------------===// 13 14#define DEBUG_TYPE "dyld" 15#include "RuntimeDyldMachO.h" 16#include "llvm/ADT/OwningPtr.h" 17#include "llvm/ADT/STLExtras.h" 18#include "llvm/ADT/StringRef.h" 19using namespace llvm; 20using namespace llvm::object; 21 22namespace llvm { 23 24static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, intptr_t DeltaForEH) { 25 uint32_t Length = *((uint32_t*)P); 26 P += 4; 27 unsigned char *Ret = P + Length; 28 uint32_t Offset = *((uint32_t*)P); 29 if (Offset == 0) // is a CIE 30 return Ret; 31 32 P += 4; 33 intptr_t FDELocation = *((intptr_t*)P); 34 intptr_t NewLocation = FDELocation - DeltaForText; 35 *((intptr_t*)P) = NewLocation; 36 P += sizeof(intptr_t); 37 38 // Skip the FDE address range 39 P += sizeof(intptr_t); 40 41 uint8_t Augmentationsize = *P; 42 P += 1; 43 if (Augmentationsize != 0) { 44 intptr_t LSDA = *((intptr_t*)P); 45 intptr_t NewLSDA = LSDA - DeltaForEH; 46 *((intptr_t*)P) = NewLSDA; 47 } 48 49 return Ret; 50} 51 52static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { 53 intptr_t ObjDistance = A->ObjAddress - B->ObjAddress; 54 intptr_t MemDistance = A->LoadAddress - B->LoadAddress; 55 return ObjDistance - MemDistance; 56} 57 58void RuntimeDyldMachO::registerEHFrames() { 59 60 if (!MemMgr) 61 return; 62 for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { 63 EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; 64 if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || 65 SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) 66 continue; 67 SectionEntry *Text = &Sections[SectionInfo.TextSID]; 68 SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; 69 SectionEntry *ExceptTab = NULL; 70 if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) 71 ExceptTab = &Sections[SectionInfo.ExceptTabSID]; 72 73 intptr_t DeltaForText = computeDelta(Text, EHFrame); 74 intptr_t DeltaForEH = 0; 75 if (ExceptTab) 76 DeltaForEH = computeDelta(ExceptTab, EHFrame); 77 78 unsigned char *P = EHFrame->Address; 79 unsigned char *End = P + EHFrame->Size; 80 do { 81 P = processFDE(P, DeltaForText, DeltaForEH); 82 } while(P != End); 83 84 MemMgr->registerEHFrames(EHFrame->Address, 85 EHFrame->LoadAddress, 86 EHFrame->Size); 87 } 88 UnregisteredEHFrameSections.clear(); 89} 90 91void RuntimeDyldMachO::finalizeLoad(ObjSectionToIDMap &SectionMap) { 92 unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; 93 unsigned TextSID = RTDYLD_INVALID_SECTION_ID; 94 unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; 95 ObjSectionToIDMap::iterator i, e; 96 for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { 97 const SectionRef &Section = i->first; 98 StringRef Name; 99 Section.getName(Name); 100 if (Name == "__eh_frame") 101 EHFrameSID = i->second; 102 else if (Name == "__text") 103 TextSID = i->second; 104 else if (Name == "__gcc_except_tab") 105 ExceptTabSID = i->second; 106 } 107 UnregisteredEHFrameSections.push_back(EHFrameRelatedSections(EHFrameSID, 108 TextSID, 109 ExceptTabSID)); 110} 111 112// The target location for the relocation is described by RE.SectionID and 113// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each 114// SectionEntry has three members describing its location. 115// SectionEntry::Address is the address at which the section has been loaded 116// into memory in the current (host) process. SectionEntry::LoadAddress is the 117// address that the section will have in the target process. 118// SectionEntry::ObjAddress is the address of the bits for this section in the 119// original emitted object image (also in the current address space). 120// 121// Relocations will be applied as if the section were loaded at 122// SectionEntry::LoadAddress, but they will be applied at an address based 123// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to 124// Target memory contents if they are required for value calculations. 125// 126// The Value parameter here is the load address of the symbol for the 127// relocation to be applied. For relocations which refer to symbols in the 128// current object Value will be the LoadAddress of the section in which 129// the symbol resides (RE.Addend provides additional information about the 130// symbol location). For external symbols, Value will be the address of the 131// symbol in the target address space. 132void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE, 133 uint64_t Value) { 134 const SectionEntry &Section = Sections[RE.SectionID]; 135 return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, 136 RE.IsPCRel, RE.Size); 137} 138 139void RuntimeDyldMachO::resolveRelocation(const SectionEntry &Section, 140 uint64_t Offset, 141 uint64_t Value, 142 uint32_t Type, 143 int64_t Addend, 144 bool isPCRel, 145 unsigned LogSize) { 146 uint8_t *LocalAddress = Section.Address + Offset; 147 uint64_t FinalAddress = Section.LoadAddress + Offset; 148 unsigned MachoType = Type; 149 unsigned Size = 1 << LogSize; 150 151 DEBUG(dbgs() << "resolveRelocation LocalAddress: " 152 << format("%p", LocalAddress) 153 << " FinalAddress: " << format("%p", FinalAddress) 154 << " Value: " << format("%p", Value) 155 << " Addend: " << Addend 156 << " isPCRel: " << isPCRel 157 << " MachoType: " << MachoType 158 << " Size: " << Size 159 << "\n"); 160 161 // This just dispatches to the proper target specific routine. 162 switch (Arch) { 163 default: llvm_unreachable("Unsupported CPU type!"); 164 case Triple::x86_64: 165 resolveX86_64Relocation(LocalAddress, 166 FinalAddress, 167 (uintptr_t)Value, 168 isPCRel, 169 MachoType, 170 Size, 171 Addend); 172 break; 173 case Triple::x86: 174 resolveI386Relocation(LocalAddress, 175 FinalAddress, 176 (uintptr_t)Value, 177 isPCRel, 178 MachoType, 179 Size, 180 Addend); 181 break; 182 case Triple::arm: // Fall through. 183 case Triple::thumb: 184 resolveARMRelocation(LocalAddress, 185 FinalAddress, 186 (uintptr_t)Value, 187 isPCRel, 188 MachoType, 189 Size, 190 Addend); 191 break; 192 } 193} 194 195bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress, 196 uint64_t FinalAddress, 197 uint64_t Value, 198 bool isPCRel, 199 unsigned Type, 200 unsigned Size, 201 int64_t Addend) { 202 if (isPCRel) 203 Value -= FinalAddress + 4; // see resolveX86_64Relocation 204 205 switch (Type) { 206 default: 207 llvm_unreachable("Invalid relocation type!"); 208 case MachO::GENERIC_RELOC_VANILLA: { 209 uint8_t *p = LocalAddress; 210 uint64_t ValueToWrite = Value + Addend; 211 for (unsigned i = 0; i < Size; ++i) { 212 *p++ = (uint8_t)(ValueToWrite & 0xff); 213 ValueToWrite >>= 8; 214 } 215 return false; 216 } 217 case MachO::GENERIC_RELOC_SECTDIFF: 218 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: 219 case MachO::GENERIC_RELOC_PB_LA_PTR: 220 return Error("Relocation type not implemented yet!"); 221 } 222} 223 224bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, 225 uint64_t FinalAddress, 226 uint64_t Value, 227 bool isPCRel, 228 unsigned Type, 229 unsigned Size, 230 int64_t Addend) { 231 // If the relocation is PC-relative, the value to be encoded is the 232 // pointer difference. 233 if (isPCRel) 234 // FIXME: It seems this value needs to be adjusted by 4 for an effective PC 235 // address. Is that expected? Only for branches, perhaps? 236 Value -= FinalAddress + 4; 237 238 switch(Type) { 239 default: 240 llvm_unreachable("Invalid relocation type!"); 241 case MachO::X86_64_RELOC_SIGNED_1: 242 case MachO::X86_64_RELOC_SIGNED_2: 243 case MachO::X86_64_RELOC_SIGNED_4: 244 case MachO::X86_64_RELOC_SIGNED: 245 case MachO::X86_64_RELOC_UNSIGNED: 246 case MachO::X86_64_RELOC_BRANCH: { 247 Value += Addend; 248 // Mask in the target value a byte at a time (we don't have an alignment 249 // guarantee for the target address, so this is safest). 250 uint8_t *p = (uint8_t*)LocalAddress; 251 for (unsigned i = 0; i < Size; ++i) { 252 *p++ = (uint8_t)Value; 253 Value >>= 8; 254 } 255 return false; 256 } 257 case MachO::X86_64_RELOC_GOT_LOAD: 258 case MachO::X86_64_RELOC_GOT: 259 case MachO::X86_64_RELOC_SUBTRACTOR: 260 case MachO::X86_64_RELOC_TLV: 261 return Error("Relocation type not implemented yet!"); 262 } 263} 264 265bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, 266 uint64_t FinalAddress, 267 uint64_t Value, 268 bool isPCRel, 269 unsigned Type, 270 unsigned Size, 271 int64_t Addend) { 272 // If the relocation is PC-relative, the value to be encoded is the 273 // pointer difference. 274 if (isPCRel) { 275 Value -= FinalAddress; 276 // ARM PCRel relocations have an effective-PC offset of two instructions 277 // (four bytes in Thumb mode, 8 bytes in ARM mode). 278 // FIXME: For now, assume ARM mode. 279 Value -= 8; 280 } 281 282 switch(Type) { 283 default: 284 llvm_unreachable("Invalid relocation type!"); 285 case MachO::ARM_RELOC_VANILLA: { 286 // Mask in the target value a byte at a time (we don't have an alignment 287 // guarantee for the target address, so this is safest). 288 uint8_t *p = (uint8_t*)LocalAddress; 289 for (unsigned i = 0; i < Size; ++i) { 290 *p++ = (uint8_t)Value; 291 Value >>= 8; 292 } 293 break; 294 } 295 case MachO::ARM_RELOC_BR24: { 296 // Mask the value into the target address. We know instructions are 297 // 32-bit aligned, so we can do it all at once. 298 uint32_t *p = (uint32_t*)LocalAddress; 299 // The low two bits of the value are not encoded. 300 Value >>= 2; 301 // Mask the value to 24 bits. 302 Value &= 0xffffff; 303 // FIXME: If the destination is a Thumb function (and the instruction 304 // is a non-predicated BL instruction), we need to change it to a BLX 305 // instruction instead. 306 307 // Insert the value into the instruction. 308 *p = (*p & ~0xffffff) | Value; 309 break; 310 } 311 case MachO::ARM_THUMB_RELOC_BR22: 312 case MachO::ARM_THUMB_32BIT_BRANCH: 313 case MachO::ARM_RELOC_HALF: 314 case MachO::ARM_RELOC_HALF_SECTDIFF: 315 case MachO::ARM_RELOC_PAIR: 316 case MachO::ARM_RELOC_SECTDIFF: 317 case MachO::ARM_RELOC_LOCAL_SECTDIFF: 318 case MachO::ARM_RELOC_PB_LA_PTR: 319 return Error("Relocation type not implemented yet!"); 320 } 321 return false; 322} 323 324void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, 325 RelocationRef RelI, 326 ObjectImage &Obj, 327 ObjSectionToIDMap &ObjSectionToID, 328 const SymbolTableMap &Symbols, 329 StubMap &Stubs) { 330 const ObjectFile *OF = Obj.getObjectFile(); 331 const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF); 332 MachO::any_relocation_info RE= MachO->getRelocation(RelI.getRawDataRefImpl()); 333 334 uint32_t RelType = MachO->getAnyRelocationType(RE); 335 336 // FIXME: Properly handle scattered relocations. 337 // For now, optimistically skip these: they can often be ignored, as 338 // the static linker will already have applied the relocation, and it 339 // only needs to be reapplied if symbols move relative to one another. 340 // Note: This will fail horribly where the relocations *do* need to be 341 // applied, but that was already the case. 342 if (MachO->isRelocationScattered(RE)) 343 return; 344 345 RelocationValueRef Value; 346 SectionEntry &Section = Sections[SectionID]; 347 348 bool isExtern = MachO->getPlainRelocationExternal(RE); 349 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 350 unsigned Size = MachO->getAnyRelocationLength(RE); 351 uint64_t Offset; 352 RelI.getOffset(Offset); 353 uint8_t *LocalAddress = Section.Address + Offset; 354 unsigned NumBytes = 1 << Size; 355 uint64_t Addend = 0; 356 memcpy(&Addend, LocalAddress, NumBytes); 357 358 if (isExtern) { 359 // Obtain the symbol name which is referenced in the relocation 360 symbol_iterator Symbol = RelI.getSymbol(); 361 StringRef TargetName; 362 Symbol->getName(TargetName); 363 // First search for the symbol in the local symbol table 364 SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); 365 if (lsi != Symbols.end()) { 366 Value.SectionID = lsi->second.first; 367 Value.Addend = lsi->second.second + Addend; 368 } else { 369 // Search for the symbol in the global symbol table 370 SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data()); 371 if (gsi != GlobalSymbolTable.end()) { 372 Value.SectionID = gsi->second.first; 373 Value.Addend = gsi->second.second + Addend; 374 } else { 375 Value.SymbolName = TargetName.data(); 376 Value.Addend = Addend; 377 } 378 } 379 } else { 380 SectionRef Sec = MachO->getRelocationSection(RE); 381 Value.SectionID = findOrEmitSection(Obj, Sec, true, ObjSectionToID); 382 uint64_t Addr; 383 Sec.getAddress(Addr); 384 Value.Addend = Addend - Addr; 385 } 386 387 if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT || 388 RelType == MachO::X86_64_RELOC_GOT_LOAD)) { 389 assert(IsPCRel); 390 assert(Size == 2); 391 StubMap::const_iterator i = Stubs.find(Value); 392 uint8_t *Addr; 393 if (i != Stubs.end()) { 394 Addr = Section.Address + i->second; 395 } else { 396 Stubs[Value] = Section.StubOffset; 397 uint8_t *GOTEntry = Section.Address + Section.StubOffset; 398 RelocationEntry RE(SectionID, Section.StubOffset, 399 MachO::X86_64_RELOC_UNSIGNED, 0, false, 3); 400 if (Value.SymbolName) 401 addRelocationForSymbol(RE, Value.SymbolName); 402 else 403 addRelocationForSection(RE, Value.SectionID); 404 Section.StubOffset += 8; 405 Addr = GOTEntry; 406 } 407 resolveRelocation(Section, Offset, (uint64_t)Addr, 408 MachO::X86_64_RELOC_UNSIGNED, Value.Addend, true, 2); 409 } else if (Arch == Triple::arm && 410 (RelType & 0xf) == MachO::ARM_RELOC_BR24) { 411 // This is an ARM branch relocation, need to use a stub function. 412 413 // Look up for existing stub. 414 StubMap::const_iterator i = Stubs.find(Value); 415 if (i != Stubs.end()) 416 resolveRelocation(Section, Offset, 417 (uint64_t)Section.Address + i->second, 418 RelType, 0, IsPCRel, Size); 419 else { 420 // Create a new stub function. 421 Stubs[Value] = Section.StubOffset; 422 uint8_t *StubTargetAddr = createStubFunction(Section.Address + 423 Section.StubOffset); 424 RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, 425 MachO::GENERIC_RELOC_VANILLA, Value.Addend); 426 if (Value.SymbolName) 427 addRelocationForSymbol(RE, Value.SymbolName); 428 else 429 addRelocationForSection(RE, Value.SectionID); 430 resolveRelocation(Section, Offset, 431 (uint64_t)Section.Address + Section.StubOffset, 432 RelType, 0, IsPCRel, Size); 433 Section.StubOffset += getMaxStubSize(); 434 } 435 } else { 436 RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, 437 IsPCRel, Size); 438 if (Value.SymbolName) 439 addRelocationForSymbol(RE, Value.SymbolName); 440 else 441 addRelocationForSection(RE, Value.SectionID); 442 } 443} 444 445 446bool RuntimeDyldMachO::isCompatibleFormat( 447 const ObjectBuffer *InputBuffer) const { 448 if (InputBuffer->getBufferSize() < 4) 449 return false; 450 StringRef Magic(InputBuffer->getBufferStart(), 4); 451 if (Magic == "\xFE\xED\xFA\xCE") return true; 452 if (Magic == "\xCE\xFA\xED\xFE") return true; 453 if (Magic == "\xFE\xED\xFA\xCF") return true; 454 if (Magic == "\xCF\xFA\xED\xFE") return true; 455 return false; 456} 457 458} // end namespace llvm 459