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