1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- 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 // This file defines the MachOObjectFile class, which binds the MachOObject 11 // class to the generic ObjectFile wrapper. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Object/MachO.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/Triple.h" 18 #include "llvm/Support/DataExtractor.h" 19 #include "llvm/Support/Format.h" 20 #include "llvm/Support/Host.h" 21 #include "llvm/Support/MemoryBuffer.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <cctype> 24 #include <cstring> 25 #include <limits> 26 27 using namespace llvm; 28 using namespace object; 29 30 namespace llvm { 31 32 namespace object { 33 34 struct nlist_base { 35 uint32_t n_strx; 36 uint8_t n_type; 37 uint8_t n_sect; 38 uint16_t n_desc; 39 }; 40 41 struct section_base { 42 char sectname[16]; 43 char segname[16]; 44 }; 45 46 template<typename T> 47 static void SwapStruct(T &Value); 48 49 template<> 50 void SwapStruct(MachO::any_relocation_info &H) { 51 sys::swapByteOrder(H.r_word0); 52 sys::swapByteOrder(H.r_word1); 53 } 54 55 template<> 56 void SwapStruct(MachO::load_command &L) { 57 sys::swapByteOrder(L.cmd); 58 sys::swapByteOrder(L.cmdsize); 59 } 60 61 template<> 62 void SwapStruct(nlist_base &S) { 63 sys::swapByteOrder(S.n_strx); 64 sys::swapByteOrder(S.n_desc); 65 } 66 67 template<> 68 void SwapStruct(MachO::section &S) { 69 sys::swapByteOrder(S.addr); 70 sys::swapByteOrder(S.size); 71 sys::swapByteOrder(S.offset); 72 sys::swapByteOrder(S.align); 73 sys::swapByteOrder(S.reloff); 74 sys::swapByteOrder(S.nreloc); 75 sys::swapByteOrder(S.flags); 76 sys::swapByteOrder(S.reserved1); 77 sys::swapByteOrder(S.reserved2); 78 } 79 80 template<> 81 void SwapStruct(MachO::section_64 &S) { 82 sys::swapByteOrder(S.addr); 83 sys::swapByteOrder(S.size); 84 sys::swapByteOrder(S.offset); 85 sys::swapByteOrder(S.align); 86 sys::swapByteOrder(S.reloff); 87 sys::swapByteOrder(S.nreloc); 88 sys::swapByteOrder(S.flags); 89 sys::swapByteOrder(S.reserved1); 90 sys::swapByteOrder(S.reserved2); 91 sys::swapByteOrder(S.reserved3); 92 } 93 94 template<> 95 void SwapStruct(MachO::nlist &S) { 96 sys::swapByteOrder(S.n_strx); 97 sys::swapByteOrder(S.n_desc); 98 sys::swapByteOrder(S.n_value); 99 } 100 101 template<> 102 void SwapStruct(MachO::nlist_64 &S) { 103 sys::swapByteOrder(S.n_strx); 104 sys::swapByteOrder(S.n_desc); 105 sys::swapByteOrder(S.n_value); 106 } 107 108 template<> 109 void SwapStruct(MachO::mach_header &H) { 110 sys::swapByteOrder(H.magic); 111 sys::swapByteOrder(H.cputype); 112 sys::swapByteOrder(H.cpusubtype); 113 sys::swapByteOrder(H.filetype); 114 sys::swapByteOrder(H.ncmds); 115 sys::swapByteOrder(H.sizeofcmds); 116 sys::swapByteOrder(H.flags); 117 } 118 119 template<> 120 void SwapStruct(MachO::mach_header_64 &H) { 121 sys::swapByteOrder(H.magic); 122 sys::swapByteOrder(H.cputype); 123 sys::swapByteOrder(H.cpusubtype); 124 sys::swapByteOrder(H.filetype); 125 sys::swapByteOrder(H.ncmds); 126 sys::swapByteOrder(H.sizeofcmds); 127 sys::swapByteOrder(H.flags); 128 sys::swapByteOrder(H.reserved); 129 } 130 131 template<> 132 void SwapStruct(MachO::symtab_command &C) { 133 sys::swapByteOrder(C.cmd); 134 sys::swapByteOrder(C.cmdsize); 135 sys::swapByteOrder(C.symoff); 136 sys::swapByteOrder(C.nsyms); 137 sys::swapByteOrder(C.stroff); 138 sys::swapByteOrder(C.strsize); 139 } 140 141 template<> 142 void SwapStruct(MachO::dysymtab_command &C) { 143 sys::swapByteOrder(C.cmd); 144 sys::swapByteOrder(C.cmdsize); 145 sys::swapByteOrder(C.ilocalsym); 146 sys::swapByteOrder(C.nlocalsym); 147 sys::swapByteOrder(C.iextdefsym); 148 sys::swapByteOrder(C.nextdefsym); 149 sys::swapByteOrder(C.iundefsym); 150 sys::swapByteOrder(C.nundefsym); 151 sys::swapByteOrder(C.tocoff); 152 sys::swapByteOrder(C.ntoc); 153 sys::swapByteOrder(C.modtaboff); 154 sys::swapByteOrder(C.nmodtab); 155 sys::swapByteOrder(C.extrefsymoff); 156 sys::swapByteOrder(C.nextrefsyms); 157 sys::swapByteOrder(C.indirectsymoff); 158 sys::swapByteOrder(C.nindirectsyms); 159 sys::swapByteOrder(C.extreloff); 160 sys::swapByteOrder(C.nextrel); 161 sys::swapByteOrder(C.locreloff); 162 sys::swapByteOrder(C.nlocrel); 163 } 164 165 template<> 166 void SwapStruct(MachO::linkedit_data_command &C) { 167 sys::swapByteOrder(C.cmd); 168 sys::swapByteOrder(C.cmdsize); 169 sys::swapByteOrder(C.dataoff); 170 sys::swapByteOrder(C.datasize); 171 } 172 173 template<> 174 void SwapStruct(MachO::segment_command &C) { 175 sys::swapByteOrder(C.cmd); 176 sys::swapByteOrder(C.cmdsize); 177 sys::swapByteOrder(C.vmaddr); 178 sys::swapByteOrder(C.vmsize); 179 sys::swapByteOrder(C.fileoff); 180 sys::swapByteOrder(C.filesize); 181 sys::swapByteOrder(C.maxprot); 182 sys::swapByteOrder(C.initprot); 183 sys::swapByteOrder(C.nsects); 184 sys::swapByteOrder(C.flags); 185 } 186 187 template<> 188 void SwapStruct(MachO::segment_command_64 &C) { 189 sys::swapByteOrder(C.cmd); 190 sys::swapByteOrder(C.cmdsize); 191 sys::swapByteOrder(C.vmaddr); 192 sys::swapByteOrder(C.vmsize); 193 sys::swapByteOrder(C.fileoff); 194 sys::swapByteOrder(C.filesize); 195 sys::swapByteOrder(C.maxprot); 196 sys::swapByteOrder(C.initprot); 197 sys::swapByteOrder(C.nsects); 198 sys::swapByteOrder(C.flags); 199 } 200 201 template<> 202 void SwapStruct(uint32_t &C) { 203 sys::swapByteOrder(C); 204 } 205 206 template<> 207 void SwapStruct(MachO::linker_options_command &C) { 208 sys::swapByteOrder(C.cmd); 209 sys::swapByteOrder(C.cmdsize); 210 sys::swapByteOrder(C.count); 211 } 212 213 template<> 214 void SwapStruct(MachO::version_min_command&C) { 215 sys::swapByteOrder(C.cmd); 216 sys::swapByteOrder(C.cmdsize); 217 sys::swapByteOrder(C.version); 218 sys::swapByteOrder(C.reserved); 219 } 220 221 template<> 222 void SwapStruct(MachO::dylib_command&C) { 223 sys::swapByteOrder(C.cmd); 224 sys::swapByteOrder(C.cmdsize); 225 sys::swapByteOrder(C.dylib.name); 226 sys::swapByteOrder(C.dylib.timestamp); 227 sys::swapByteOrder(C.dylib.current_version); 228 sys::swapByteOrder(C.dylib.compatibility_version); 229 } 230 231 template<> 232 void SwapStruct(MachO::data_in_code_entry &C) { 233 sys::swapByteOrder(C.offset); 234 sys::swapByteOrder(C.length); 235 sys::swapByteOrder(C.kind); 236 } 237 238 template<typename T> 239 T getStruct(const MachOObjectFile *O, const char *P) { 240 T Cmd; 241 memcpy(&Cmd, P, sizeof(T)); 242 if (O->isLittleEndian() != sys::IsLittleEndianHost) 243 SwapStruct(Cmd); 244 return Cmd; 245 } 246 247 static uint32_t 248 getSegmentLoadCommandNumSections(const MachOObjectFile *O, 249 const MachOObjectFile::LoadCommandInfo &L) { 250 if (O->is64Bit()) { 251 MachO::segment_command_64 S = O->getSegment64LoadCommand(L); 252 return S.nsects; 253 } 254 MachO::segment_command S = O->getSegmentLoadCommand(L); 255 return S.nsects; 256 } 257 258 static const char * 259 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 260 unsigned Sec) { 261 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 262 263 bool Is64 = O->is64Bit(); 264 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 265 sizeof(MachO::segment_command); 266 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 267 sizeof(MachO::section); 268 269 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 270 return reinterpret_cast<const char*>(SectionAddr); 271 } 272 273 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 274 return O->getData().substr(Offset, 1).data(); 275 } 276 277 static nlist_base 278 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 279 const char *P = reinterpret_cast<const char *>(DRI.p); 280 return getStruct<nlist_base>(O, P); 281 } 282 283 static StringRef parseSegmentOrSectionName(const char *P) { 284 if (P[15] == 0) 285 // Null terminated. 286 return P; 287 // Not null terminated, so this is a 16 char string. 288 return StringRef(P, 16); 289 } 290 291 // Helper to advance a section or symbol iterator multiple increments at a time. 292 template<class T> 293 static void advance(T &it, size_t Val) { 294 while (Val--) 295 ++it; 296 } 297 298 static unsigned getCPUType(const MachOObjectFile *O) { 299 return O->getHeader().cputype; 300 } 301 302 static void printRelocationTargetName(const MachOObjectFile *O, 303 const MachO::any_relocation_info &RE, 304 raw_string_ostream &fmt) { 305 bool IsScattered = O->isRelocationScattered(RE); 306 307 // Target of a scattered relocation is an address. In the interest of 308 // generating pretty output, scan through the symbol table looking for a 309 // symbol that aligns with that address. If we find one, print it. 310 // Otherwise, we just print the hex address of the target. 311 if (IsScattered) { 312 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 313 314 for (const SymbolRef &Symbol : O->symbols()) { 315 std::error_code ec; 316 uint64_t Addr; 317 StringRef Name; 318 319 if ((ec = Symbol.getAddress(Addr))) 320 report_fatal_error(ec.message()); 321 if (Addr != Val) 322 continue; 323 if ((ec = Symbol.getName(Name))) 324 report_fatal_error(ec.message()); 325 fmt << Name; 326 return; 327 } 328 329 // If we couldn't find a symbol that this relocation refers to, try 330 // to find a section beginning instead. 331 for (const SectionRef &Section : O->sections()) { 332 std::error_code ec; 333 uint64_t Addr; 334 StringRef Name; 335 336 if ((ec = Section.getAddress(Addr))) 337 report_fatal_error(ec.message()); 338 if (Addr != Val) 339 continue; 340 if ((ec = Section.getName(Name))) 341 report_fatal_error(ec.message()); 342 fmt << Name; 343 return; 344 } 345 346 fmt << format("0x%x", Val); 347 return; 348 } 349 350 StringRef S; 351 bool isExtern = O->getPlainRelocationExternal(RE); 352 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 353 354 if (isExtern) { 355 symbol_iterator SI = O->symbol_begin(); 356 advance(SI, Val); 357 SI->getName(S); 358 } else { 359 section_iterator SI = O->section_begin(); 360 // Adjust for the fact that sections are 1-indexed. 361 advance(SI, Val - 1); 362 SI->getName(S); 363 } 364 365 fmt << S; 366 } 367 368 static uint32_t 369 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 370 return RE.r_word0; 371 } 372 373 static unsigned 374 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 375 return RE.r_word0 & 0xffffff; 376 } 377 378 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 379 const MachO::any_relocation_info &RE) { 380 if (O->isLittleEndian()) 381 return (RE.r_word1 >> 24) & 1; 382 return (RE.r_word1 >> 7) & 1; 383 } 384 385 static bool 386 getScatteredRelocationPCRel(const MachOObjectFile *O, 387 const MachO::any_relocation_info &RE) { 388 return (RE.r_word0 >> 30) & 1; 389 } 390 391 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 392 const MachO::any_relocation_info &RE) { 393 if (O->isLittleEndian()) 394 return (RE.r_word1 >> 25) & 3; 395 return (RE.r_word1 >> 5) & 3; 396 } 397 398 static unsigned 399 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 400 return (RE.r_word0 >> 28) & 3; 401 } 402 403 static unsigned getPlainRelocationType(const MachOObjectFile *O, 404 const MachO::any_relocation_info &RE) { 405 if (O->isLittleEndian()) 406 return RE.r_word1 >> 28; 407 return RE.r_word1 & 0xf; 408 } 409 410 static unsigned 411 getScatteredRelocationType(const MachO::any_relocation_info &RE) { 412 return (RE.r_word0 >> 24) & 0xf; 413 } 414 415 static uint32_t getSectionFlags(const MachOObjectFile *O, 416 DataRefImpl Sec) { 417 if (O->is64Bit()) { 418 MachO::section_64 Sect = O->getSection64(Sec); 419 return Sect.flags; 420 } 421 MachO::section Sect = O->getSection(Sec); 422 return Sect.flags; 423 } 424 425 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, 426 bool Is64bits, std::error_code &EC) 427 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 428 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 429 DataInCodeLoadCmd(nullptr) { 430 uint32_t LoadCommandCount = this->getHeader().ncmds; 431 MachO::LoadCommandType SegmentLoadType = is64Bit() ? 432 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; 433 434 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); 435 for (unsigned I = 0; ; ++I) { 436 if (Load.C.cmd == MachO::LC_SYMTAB) { 437 assert(!SymtabLoadCmd && "Multiple symbol tables"); 438 SymtabLoadCmd = Load.Ptr; 439 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 440 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); 441 DysymtabLoadCmd = Load.Ptr; 442 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 443 assert(!DataInCodeLoadCmd && "Multiple data in code tables"); 444 DataInCodeLoadCmd = Load.Ptr; 445 } else if (Load.C.cmd == SegmentLoadType) { 446 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); 447 for (unsigned J = 0; J < NumSections; ++J) { 448 const char *Sec = getSectionPtr(this, Load, J); 449 Sections.push_back(Sec); 450 } 451 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || 452 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 453 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 454 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 455 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 456 Libraries.push_back(Load.Ptr); 457 } 458 459 if (I == LoadCommandCount - 1) 460 break; 461 else 462 Load = getNextLoadCommandInfo(Load); 463 } 464 } 465 466 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 467 unsigned SymbolTableEntrySize = is64Bit() ? 468 sizeof(MachO::nlist_64) : 469 sizeof(MachO::nlist); 470 Symb.p += SymbolTableEntrySize; 471 } 472 473 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 474 StringRef &Res) const { 475 StringRef StringTable = getStringTableData(); 476 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 477 const char *Start = &StringTable.data()[Entry.n_strx]; 478 Res = StringRef(Start); 479 return object_error::success; 480 } 481 482 // getIndirectName() returns the name of the alias'ed symbol who's string table 483 // index is in the n_value field. 484 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 485 StringRef &Res) const { 486 StringRef StringTable = getStringTableData(); 487 uint64_t NValue; 488 if (is64Bit()) { 489 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 490 NValue = Entry.n_value; 491 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 492 return object_error::parse_failed; 493 } else { 494 MachO::nlist Entry = getSymbolTableEntry(Symb); 495 NValue = Entry.n_value; 496 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 497 return object_error::parse_failed; 498 } 499 if (NValue >= StringTable.size()) 500 return object_error::parse_failed; 501 const char *Start = &StringTable.data()[NValue]; 502 Res = StringRef(Start); 503 return object_error::success; 504 } 505 506 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 507 uint64_t &Res) const { 508 if (is64Bit()) { 509 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 510 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 511 Entry.n_value == 0) 512 Res = UnknownAddressOrSize; 513 else 514 Res = Entry.n_value; 515 } else { 516 MachO::nlist Entry = getSymbolTableEntry(Symb); 517 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 518 Entry.n_value == 0) 519 Res = UnknownAddressOrSize; 520 else 521 Res = Entry.n_value; 522 } 523 return object_error::success; 524 } 525 526 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, 527 uint32_t &Result) const { 528 uint32_t flags = getSymbolFlags(DRI); 529 if (flags & SymbolRef::SF_Common) { 530 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 531 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 532 } else { 533 Result = 0; 534 } 535 return object_error::success; 536 } 537 538 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 539 uint64_t &Result) const { 540 uint64_t BeginOffset; 541 uint64_t EndOffset = 0; 542 uint8_t SectionIndex; 543 544 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 545 uint64_t Value; 546 getSymbolAddress(DRI, Value); 547 if (Value == UnknownAddressOrSize) { 548 Result = UnknownAddressOrSize; 549 return object_error::success; 550 } 551 552 BeginOffset = Value; 553 554 SectionIndex = Entry.n_sect; 555 if (!SectionIndex) { 556 uint32_t flags = getSymbolFlags(DRI); 557 if (flags & SymbolRef::SF_Common) 558 Result = Value; 559 else 560 Result = UnknownAddressOrSize; 561 return object_error::success; 562 } 563 // Unfortunately symbols are unsorted so we need to touch all 564 // symbols from load command 565 for (const SymbolRef &Symbol : symbols()) { 566 DataRefImpl DRI = Symbol.getRawDataRefImpl(); 567 Entry = getSymbolTableEntryBase(this, DRI); 568 getSymbolAddress(DRI, Value); 569 if (Value == UnknownAddressOrSize) 570 continue; 571 if (Entry.n_sect == SectionIndex && Value > BeginOffset) 572 if (!EndOffset || Value < EndOffset) 573 EndOffset = Value; 574 } 575 if (!EndOffset) { 576 uint64_t Size; 577 DataRefImpl Sec; 578 Sec.d.a = SectionIndex-1; 579 getSectionSize(Sec, Size); 580 getSectionAddress(Sec, EndOffset); 581 EndOffset += Size; 582 } 583 Result = EndOffset - BeginOffset; 584 return object_error::success; 585 } 586 587 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 588 SymbolRef::Type &Res) const { 589 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 590 uint8_t n_type = Entry.n_type; 591 592 Res = SymbolRef::ST_Other; 593 594 // If this is a STAB debugging symbol, we can do nothing more. 595 if (n_type & MachO::N_STAB) { 596 Res = SymbolRef::ST_Debug; 597 return object_error::success; 598 } 599 600 switch (n_type & MachO::N_TYPE) { 601 case MachO::N_UNDF : 602 Res = SymbolRef::ST_Unknown; 603 break; 604 case MachO::N_SECT : 605 Res = SymbolRef::ST_Function; 606 break; 607 } 608 return object_error::success; 609 } 610 611 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 612 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 613 614 uint8_t MachOType = Entry.n_type; 615 uint16_t MachOFlags = Entry.n_desc; 616 617 uint32_t Result = SymbolRef::SF_None; 618 619 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) 620 Result |= SymbolRef::SF_Undefined; 621 622 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 623 Result |= SymbolRef::SF_Indirect; 624 625 if (MachOType & MachO::N_STAB) 626 Result |= SymbolRef::SF_FormatSpecific; 627 628 if (MachOType & MachO::N_EXT) { 629 Result |= SymbolRef::SF_Global; 630 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 631 uint64_t Value; 632 getSymbolAddress(DRI, Value); 633 if (Value && Value != UnknownAddressOrSize) 634 Result |= SymbolRef::SF_Common; 635 } 636 } 637 638 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 639 Result |= SymbolRef::SF_Weak; 640 641 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 642 Result |= SymbolRef::SF_Absolute; 643 644 return Result; 645 } 646 647 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 648 section_iterator &Res) const { 649 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 650 uint8_t index = Entry.n_sect; 651 652 if (index == 0) { 653 Res = section_end(); 654 } else { 655 DataRefImpl DRI; 656 DRI.d.a = index - 1; 657 Res = section_iterator(SectionRef(DRI, this)); 658 } 659 660 return object_error::success; 661 } 662 663 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 664 Sec.d.a++; 665 } 666 667 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 668 StringRef &Result) const { 669 ArrayRef<char> Raw = getSectionRawName(Sec); 670 Result = parseSegmentOrSectionName(Raw.data()); 671 return object_error::success; 672 } 673 674 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, 675 uint64_t &Res) const { 676 if (is64Bit()) { 677 MachO::section_64 Sect = getSection64(Sec); 678 Res = Sect.addr; 679 } else { 680 MachO::section Sect = getSection(Sec); 681 Res = Sect.addr; 682 } 683 return object_error::success; 684 } 685 686 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, 687 uint64_t &Res) const { 688 if (is64Bit()) { 689 MachO::section_64 Sect = getSection64(Sec); 690 Res = Sect.size; 691 } else { 692 MachO::section Sect = getSection(Sec); 693 Res = Sect.size; 694 } 695 696 return object_error::success; 697 } 698 699 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 700 StringRef &Res) const { 701 uint32_t Offset; 702 uint64_t Size; 703 704 if (is64Bit()) { 705 MachO::section_64 Sect = getSection64(Sec); 706 Offset = Sect.offset; 707 Size = Sect.size; 708 } else { 709 MachO::section Sect = getSection(Sec); 710 Offset = Sect.offset; 711 Size = Sect.size; 712 } 713 714 Res = this->getData().substr(Offset, Size); 715 return object_error::success; 716 } 717 718 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, 719 uint64_t &Res) const { 720 uint32_t Align; 721 if (is64Bit()) { 722 MachO::section_64 Sect = getSection64(Sec); 723 Align = Sect.align; 724 } else { 725 MachO::section Sect = getSection(Sec); 726 Align = Sect.align; 727 } 728 729 Res = uint64_t(1) << Align; 730 return object_error::success; 731 } 732 733 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, 734 bool &Res) const { 735 uint32_t Flags = getSectionFlags(this, Sec); 736 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 737 return object_error::success; 738 } 739 740 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, 741 bool &Result) const { 742 uint32_t Flags = getSectionFlags(this, Sec); 743 unsigned SectionType = Flags & MachO::SECTION_TYPE; 744 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 745 !(SectionType == MachO::S_ZEROFILL || 746 SectionType == MachO::S_GB_ZEROFILL); 747 return object_error::success; 748 } 749 750 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, 751 bool &Result) const { 752 uint32_t Flags = getSectionFlags(this, Sec); 753 unsigned SectionType = Flags & MachO::SECTION_TYPE; 754 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 755 (SectionType == MachO::S_ZEROFILL || 756 SectionType == MachO::S_GB_ZEROFILL); 757 return object_error::success; 758 } 759 760 std::error_code 761 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 762 bool &Result) const { 763 // FIXME: Unimplemented. 764 Result = true; 765 return object_error::success; 766 } 767 768 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 769 bool &Result) const { 770 // FIXME: Unimplemented. 771 Result = false; 772 return object_error::success; 773 } 774 775 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, 776 bool &Res) const { 777 uint32_t Flags = getSectionFlags(this, Sec); 778 unsigned SectionType = Flags & MachO::SECTION_TYPE; 779 Res = SectionType == MachO::S_ZEROFILL || 780 SectionType == MachO::S_GB_ZEROFILL; 781 return object_error::success; 782 } 783 784 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 785 bool &Result) const { 786 // Consider using the code from isSectionText to look for __const sections. 787 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 788 // to use section attributes to distinguish code from data. 789 790 // FIXME: Unimplemented. 791 Result = false; 792 return object_error::success; 793 } 794 795 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 796 DataRefImpl Symb, 797 bool &Result) const { 798 SymbolRef::Type ST; 799 this->getSymbolType(Symb, ST); 800 if (ST == SymbolRef::ST_Unknown) { 801 Result = false; 802 return object_error::success; 803 } 804 805 uint64_t SectBegin, SectEnd; 806 getSectionAddress(Sec, SectBegin); 807 getSectionSize(Sec, SectEnd); 808 SectEnd += SectBegin; 809 810 uint64_t SymAddr; 811 getSymbolAddress(Symb, SymAddr); 812 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 813 814 return object_error::success; 815 } 816 817 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 818 DataRefImpl Ret; 819 Ret.d.a = Sec.d.a; 820 Ret.d.b = 0; 821 return relocation_iterator(RelocationRef(Ret, this)); 822 } 823 824 relocation_iterator 825 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 826 uint32_t Num; 827 if (is64Bit()) { 828 MachO::section_64 Sect = getSection64(Sec); 829 Num = Sect.nreloc; 830 } else { 831 MachO::section Sect = getSection(Sec); 832 Num = Sect.nreloc; 833 } 834 835 DataRefImpl Ret; 836 Ret.d.a = Sec.d.a; 837 Ret.d.b = Num; 838 return relocation_iterator(RelocationRef(Ret, this)); 839 } 840 841 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 842 ++Rel.d.b; 843 } 844 845 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 846 uint64_t &Res) const { 847 uint64_t Offset; 848 getRelocationOffset(Rel, Offset); 849 850 DataRefImpl Sec; 851 Sec.d.a = Rel.d.a; 852 uint64_t SecAddress; 853 getSectionAddress(Sec, SecAddress); 854 Res = SecAddress + Offset; 855 return object_error::success; 856 } 857 858 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 859 uint64_t &Res) const { 860 assert(getHeader().filetype == MachO::MH_OBJECT && 861 "Only implemented for MH_OBJECT"); 862 MachO::any_relocation_info RE = getRelocation(Rel); 863 Res = getAnyRelocationAddress(RE); 864 return object_error::success; 865 } 866 867 symbol_iterator 868 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 869 MachO::any_relocation_info RE = getRelocation(Rel); 870 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 871 bool isExtern = getPlainRelocationExternal(RE); 872 if (!isExtern) 873 return symbol_end(); 874 875 MachO::symtab_command S = getSymtabLoadCommand(); 876 unsigned SymbolTableEntrySize = is64Bit() ? 877 sizeof(MachO::nlist_64) : 878 sizeof(MachO::nlist); 879 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 880 DataRefImpl Sym; 881 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 882 return symbol_iterator(SymbolRef(Sym, this)); 883 } 884 885 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 886 uint64_t &Res) const { 887 MachO::any_relocation_info RE = getRelocation(Rel); 888 Res = getAnyRelocationType(RE); 889 return object_error::success; 890 } 891 892 std::error_code 893 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 894 SmallVectorImpl<char> &Result) const { 895 StringRef res; 896 uint64_t RType; 897 getRelocationType(Rel, RType); 898 899 unsigned Arch = this->getArch(); 900 901 switch (Arch) { 902 case Triple::x86: { 903 static const char *const Table[] = { 904 "GENERIC_RELOC_VANILLA", 905 "GENERIC_RELOC_PAIR", 906 "GENERIC_RELOC_SECTDIFF", 907 "GENERIC_RELOC_PB_LA_PTR", 908 "GENERIC_RELOC_LOCAL_SECTDIFF", 909 "GENERIC_RELOC_TLV" }; 910 911 if (RType > 5) 912 res = "Unknown"; 913 else 914 res = Table[RType]; 915 break; 916 } 917 case Triple::x86_64: { 918 static const char *const Table[] = { 919 "X86_64_RELOC_UNSIGNED", 920 "X86_64_RELOC_SIGNED", 921 "X86_64_RELOC_BRANCH", 922 "X86_64_RELOC_GOT_LOAD", 923 "X86_64_RELOC_GOT", 924 "X86_64_RELOC_SUBTRACTOR", 925 "X86_64_RELOC_SIGNED_1", 926 "X86_64_RELOC_SIGNED_2", 927 "X86_64_RELOC_SIGNED_4", 928 "X86_64_RELOC_TLV" }; 929 930 if (RType > 9) 931 res = "Unknown"; 932 else 933 res = Table[RType]; 934 break; 935 } 936 case Triple::arm: { 937 static const char *const Table[] = { 938 "ARM_RELOC_VANILLA", 939 "ARM_RELOC_PAIR", 940 "ARM_RELOC_SECTDIFF", 941 "ARM_RELOC_LOCAL_SECTDIFF", 942 "ARM_RELOC_PB_LA_PTR", 943 "ARM_RELOC_BR24", 944 "ARM_THUMB_RELOC_BR22", 945 "ARM_THUMB_32BIT_BRANCH", 946 "ARM_RELOC_HALF", 947 "ARM_RELOC_HALF_SECTDIFF" }; 948 949 if (RType > 9) 950 res = "Unknown"; 951 else 952 res = Table[RType]; 953 break; 954 } 955 case Triple::arm64: 956 case Triple::aarch64: { 957 static const char *const Table[] = { 958 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 959 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 960 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 961 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 962 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 963 "ARM64_RELOC_ADDEND" 964 }; 965 966 if (RType >= array_lengthof(Table)) 967 res = "Unknown"; 968 else 969 res = Table[RType]; 970 break; 971 } 972 case Triple::ppc: { 973 static const char *const Table[] = { 974 "PPC_RELOC_VANILLA", 975 "PPC_RELOC_PAIR", 976 "PPC_RELOC_BR14", 977 "PPC_RELOC_BR24", 978 "PPC_RELOC_HI16", 979 "PPC_RELOC_LO16", 980 "PPC_RELOC_HA16", 981 "PPC_RELOC_LO14", 982 "PPC_RELOC_SECTDIFF", 983 "PPC_RELOC_PB_LA_PTR", 984 "PPC_RELOC_HI16_SECTDIFF", 985 "PPC_RELOC_LO16_SECTDIFF", 986 "PPC_RELOC_HA16_SECTDIFF", 987 "PPC_RELOC_JBSR", 988 "PPC_RELOC_LO14_SECTDIFF", 989 "PPC_RELOC_LOCAL_SECTDIFF" }; 990 991 if (RType > 15) 992 res = "Unknown"; 993 else 994 res = Table[RType]; 995 break; 996 } 997 case Triple::UnknownArch: 998 res = "Unknown"; 999 break; 1000 } 1001 Result.append(res.begin(), res.end()); 1002 return object_error::success; 1003 } 1004 1005 std::error_code 1006 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 1007 SmallVectorImpl<char> &Result) const { 1008 MachO::any_relocation_info RE = getRelocation(Rel); 1009 1010 unsigned Arch = this->getArch(); 1011 1012 std::string fmtbuf; 1013 raw_string_ostream fmt(fmtbuf); 1014 unsigned Type = this->getAnyRelocationType(RE); 1015 bool IsPCRel = this->getAnyRelocationPCRel(RE); 1016 1017 // Determine any addends that should be displayed with the relocation. 1018 // These require decoding the relocation type, which is triple-specific. 1019 1020 // X86_64 has entirely custom relocation types. 1021 if (Arch == Triple::x86_64) { 1022 bool isPCRel = getAnyRelocationPCRel(RE); 1023 1024 switch (Type) { 1025 case MachO::X86_64_RELOC_GOT_LOAD: 1026 case MachO::X86_64_RELOC_GOT: { 1027 printRelocationTargetName(this, RE, fmt); 1028 fmt << "@GOT"; 1029 if (isPCRel) fmt << "PCREL"; 1030 break; 1031 } 1032 case MachO::X86_64_RELOC_SUBTRACTOR: { 1033 DataRefImpl RelNext = Rel; 1034 moveRelocationNext(RelNext); 1035 MachO::any_relocation_info RENext = getRelocation(RelNext); 1036 1037 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 1038 // X86_64_RELOC_UNSIGNED. 1039 // NOTE: Scattered relocations don't exist on x86_64. 1040 unsigned RType = getAnyRelocationType(RENext); 1041 if (RType != MachO::X86_64_RELOC_UNSIGNED) 1042 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 1043 "X86_64_RELOC_SUBTRACTOR."); 1044 1045 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 1046 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 1047 printRelocationTargetName(this, RENext, fmt); 1048 fmt << "-"; 1049 printRelocationTargetName(this, RE, fmt); 1050 break; 1051 } 1052 case MachO::X86_64_RELOC_TLV: 1053 printRelocationTargetName(this, RE, fmt); 1054 fmt << "@TLV"; 1055 if (isPCRel) fmt << "P"; 1056 break; 1057 case MachO::X86_64_RELOC_SIGNED_1: 1058 printRelocationTargetName(this, RE, fmt); 1059 fmt << "-1"; 1060 break; 1061 case MachO::X86_64_RELOC_SIGNED_2: 1062 printRelocationTargetName(this, RE, fmt); 1063 fmt << "-2"; 1064 break; 1065 case MachO::X86_64_RELOC_SIGNED_4: 1066 printRelocationTargetName(this, RE, fmt); 1067 fmt << "-4"; 1068 break; 1069 default: 1070 printRelocationTargetName(this, RE, fmt); 1071 break; 1072 } 1073 // X86 and ARM share some relocation types in common. 1074 } else if (Arch == Triple::x86 || Arch == Triple::arm || 1075 Arch == Triple::ppc) { 1076 // Generic relocation types... 1077 switch (Type) { 1078 case MachO::GENERIC_RELOC_PAIR: // prints no info 1079 return object_error::success; 1080 case MachO::GENERIC_RELOC_SECTDIFF: { 1081 DataRefImpl RelNext = Rel; 1082 moveRelocationNext(RelNext); 1083 MachO::any_relocation_info RENext = getRelocation(RelNext); 1084 1085 // X86 sect diff's must be followed by a relocation of type 1086 // GENERIC_RELOC_PAIR. 1087 unsigned RType = getAnyRelocationType(RENext); 1088 1089 if (RType != MachO::GENERIC_RELOC_PAIR) 1090 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1091 "GENERIC_RELOC_SECTDIFF."); 1092 1093 printRelocationTargetName(this, RE, fmt); 1094 fmt << "-"; 1095 printRelocationTargetName(this, RENext, fmt); 1096 break; 1097 } 1098 } 1099 1100 if (Arch == Triple::x86 || Arch == Triple::ppc) { 1101 switch (Type) { 1102 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 1103 DataRefImpl RelNext = Rel; 1104 moveRelocationNext(RelNext); 1105 MachO::any_relocation_info RENext = getRelocation(RelNext); 1106 1107 // X86 sect diff's must be followed by a relocation of type 1108 // GENERIC_RELOC_PAIR. 1109 unsigned RType = getAnyRelocationType(RENext); 1110 if (RType != MachO::GENERIC_RELOC_PAIR) 1111 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1112 "GENERIC_RELOC_LOCAL_SECTDIFF."); 1113 1114 printRelocationTargetName(this, RE, fmt); 1115 fmt << "-"; 1116 printRelocationTargetName(this, RENext, fmt); 1117 break; 1118 } 1119 case MachO::GENERIC_RELOC_TLV: { 1120 printRelocationTargetName(this, RE, fmt); 1121 fmt << "@TLV"; 1122 if (IsPCRel) fmt << "P"; 1123 break; 1124 } 1125 default: 1126 printRelocationTargetName(this, RE, fmt); 1127 } 1128 } else { // ARM-specific relocations 1129 switch (Type) { 1130 case MachO::ARM_RELOC_HALF: 1131 case MachO::ARM_RELOC_HALF_SECTDIFF: { 1132 // Half relocations steal a bit from the length field to encode 1133 // whether this is an upper16 or a lower16 relocation. 1134 bool isUpper = getAnyRelocationLength(RE) >> 1; 1135 1136 if (isUpper) 1137 fmt << ":upper16:("; 1138 else 1139 fmt << ":lower16:("; 1140 printRelocationTargetName(this, RE, fmt); 1141 1142 DataRefImpl RelNext = Rel; 1143 moveRelocationNext(RelNext); 1144 MachO::any_relocation_info RENext = getRelocation(RelNext); 1145 1146 // ARM half relocs must be followed by a relocation of type 1147 // ARM_RELOC_PAIR. 1148 unsigned RType = getAnyRelocationType(RENext); 1149 if (RType != MachO::ARM_RELOC_PAIR) 1150 report_fatal_error("Expected ARM_RELOC_PAIR after " 1151 "ARM_RELOC_HALF"); 1152 1153 // NOTE: The half of the target virtual address is stashed in the 1154 // address field of the secondary relocation, but we can't reverse 1155 // engineer the constant offset from it without decoding the movw/movt 1156 // instruction to find the other half in its immediate field. 1157 1158 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1159 // symbol/section pointer of the follow-on relocation. 1160 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 1161 fmt << "-"; 1162 printRelocationTargetName(this, RENext, fmt); 1163 } 1164 1165 fmt << ")"; 1166 break; 1167 } 1168 default: { 1169 printRelocationTargetName(this, RE, fmt); 1170 } 1171 } 1172 } 1173 } else 1174 printRelocationTargetName(this, RE, fmt); 1175 1176 fmt.flush(); 1177 Result.append(fmtbuf.begin(), fmtbuf.end()); 1178 return object_error::success; 1179 } 1180 1181 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 1182 bool &Result) const { 1183 unsigned Arch = getArch(); 1184 uint64_t Type; 1185 getRelocationType(Rel, Type); 1186 1187 Result = false; 1188 1189 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1190 // is always hidden. 1191 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { 1192 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; 1193 } else if (Arch == Triple::x86_64) { 1194 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1195 // an X86_64_RELOC_SUBTRACTOR. 1196 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { 1197 DataRefImpl RelPrev = Rel; 1198 RelPrev.d.a--; 1199 uint64_t PrevType; 1200 getRelocationType(RelPrev, PrevType); 1201 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) 1202 Result = true; 1203 } 1204 } 1205 1206 return object_error::success; 1207 } 1208 1209 std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1210 LibraryRef &Res) const { 1211 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1212 } 1213 1214 std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1215 StringRef &Res) const { 1216 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1217 } 1218 1219 // 1220 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1221 // guess on what the short name is. Then name is returned as a substring of the 1222 // StringRef Name passed in. The name of the dynamic library is recognized as 1223 // a framework if it has one of the two following forms: 1224 // Foo.framework/Versions/A/Foo 1225 // Foo.framework/Foo 1226 // Where A and Foo can be any string. And may contain a trailing suffix 1227 // starting with an underbar. If the Name is recognized as a framework then 1228 // isFramework is set to true else it is set to false. If the Name has a 1229 // suffix then Suffix is set to the substring in Name that contains the suffix 1230 // else it is set to a NULL StringRef. 1231 // 1232 // The Name of the dynamic library is recognized as a library name if it has 1233 // one of the two following forms: 1234 // libFoo.A.dylib 1235 // libFoo.dylib 1236 // The library may have a suffix trailing the name Foo of the form: 1237 // libFoo_profile.A.dylib 1238 // libFoo_profile.dylib 1239 // 1240 // The Name of the dynamic library is also recognized as a library name if it 1241 // has the following form: 1242 // Foo.qtx 1243 // 1244 // If the Name of the dynamic library is none of the forms above then a NULL 1245 // StringRef is returned. 1246 // 1247 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1248 bool &isFramework, 1249 StringRef &Suffix) { 1250 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1251 size_t a, b, c, d, Idx; 1252 1253 isFramework = false; 1254 Suffix = StringRef(); 1255 1256 // Pull off the last component and make Foo point to it 1257 a = Name.rfind('/'); 1258 if (a == Name.npos || a == 0) 1259 goto guess_library; 1260 Foo = Name.slice(a+1, Name.npos); 1261 1262 // Look for a suffix starting with a '_' 1263 Idx = Foo.rfind('_'); 1264 if (Idx != Foo.npos && Foo.size() >= 2) { 1265 Suffix = Foo.slice(Idx, Foo.npos); 1266 Foo = Foo.slice(0, Idx); 1267 } 1268 1269 // First look for the form Foo.framework/Foo 1270 b = Name.rfind('/', a); 1271 if (b == Name.npos) 1272 Idx = 0; 1273 else 1274 Idx = b+1; 1275 F = Name.slice(Idx, Idx + Foo.size()); 1276 DotFramework = Name.slice(Idx + Foo.size(), 1277 Idx + Foo.size() + sizeof(".framework/")-1); 1278 if (F == Foo && DotFramework == ".framework/") { 1279 isFramework = true; 1280 return Foo; 1281 } 1282 1283 // Next look for the form Foo.framework/Versions/A/Foo 1284 if (b == Name.npos) 1285 goto guess_library; 1286 c = Name.rfind('/', b); 1287 if (c == Name.npos || c == 0) 1288 goto guess_library; 1289 V = Name.slice(c+1, Name.npos); 1290 if (!V.startswith("Versions/")) 1291 goto guess_library; 1292 d = Name.rfind('/', c); 1293 if (d == Name.npos) 1294 Idx = 0; 1295 else 1296 Idx = d+1; 1297 F = Name.slice(Idx, Idx + Foo.size()); 1298 DotFramework = Name.slice(Idx + Foo.size(), 1299 Idx + Foo.size() + sizeof(".framework/")-1); 1300 if (F == Foo && DotFramework == ".framework/") { 1301 isFramework = true; 1302 return Foo; 1303 } 1304 1305 guess_library: 1306 // pull off the suffix after the "." and make a point to it 1307 a = Name.rfind('.'); 1308 if (a == Name.npos || a == 0) 1309 return StringRef(); 1310 Dylib = Name.slice(a, Name.npos); 1311 if (Dylib != ".dylib") 1312 goto guess_qtx; 1313 1314 // First pull off the version letter for the form Foo.A.dylib if any. 1315 if (a >= 3) { 1316 Dot = Name.slice(a-2, a-1); 1317 if (Dot == ".") 1318 a = a - 2; 1319 } 1320 1321 b = Name.rfind('/', a); 1322 if (b == Name.npos) 1323 b = 0; 1324 else 1325 b = b+1; 1326 // ignore any suffix after an underbar like Foo_profile.A.dylib 1327 Idx = Name.find('_', b); 1328 if (Idx != Name.npos && Idx != b) { 1329 Lib = Name.slice(b, Idx); 1330 Suffix = Name.slice(Idx, a); 1331 } 1332 else 1333 Lib = Name.slice(b, a); 1334 // There are incorrect library names of the form: 1335 // libATS.A_profile.dylib so check for these. 1336 if (Lib.size() >= 3) { 1337 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1338 if (Dot == ".") 1339 Lib = Lib.slice(0, Lib.size()-2); 1340 } 1341 return Lib; 1342 1343 guess_qtx: 1344 Qtx = Name.slice(a, Name.npos); 1345 if (Qtx != ".qtx") 1346 return StringRef(); 1347 b = Name.rfind('/', a); 1348 if (b == Name.npos) 1349 Lib = Name.slice(0, a); 1350 else 1351 Lib = Name.slice(b+1, a); 1352 // There are library names of the form: QT.A.qtx so check for these. 1353 if (Lib.size() >= 3) { 1354 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1355 if (Dot == ".") 1356 Lib = Lib.slice(0, Lib.size()-2); 1357 } 1358 return Lib; 1359 } 1360 1361 // getLibraryShortNameByIndex() is used to get the short name of the library 1362 // for an undefined symbol in a linked Mach-O binary that was linked with the 1363 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 1364 // It is passed the index (0 - based) of the library as translated from 1365 // GET_LIBRARY_ORDINAL (1 - based). 1366 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 1367 StringRef &Res) { 1368 if (Index >= Libraries.size()) 1369 return object_error::parse_failed; 1370 1371 MachO::dylib_command D = 1372 getStruct<MachO::dylib_command>(this, Libraries[Index]); 1373 if (D.dylib.name >= D.cmdsize) 1374 return object_error::parse_failed; 1375 1376 // If the cache of LibrariesShortNames is not built up do that first for 1377 // all the Libraries. 1378 if (LibrariesShortNames.size() == 0) { 1379 for (unsigned i = 0; i < Libraries.size(); i++) { 1380 MachO::dylib_command D = 1381 getStruct<MachO::dylib_command>(this, Libraries[i]); 1382 if (D.dylib.name >= D.cmdsize) { 1383 LibrariesShortNames.push_back(StringRef()); 1384 continue; 1385 } 1386 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 1387 StringRef Name = StringRef(P); 1388 StringRef Suffix; 1389 bool isFramework; 1390 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 1391 if (shortName == StringRef()) 1392 LibrariesShortNames.push_back(Name); 1393 else 1394 LibrariesShortNames.push_back(shortName); 1395 } 1396 } 1397 1398 Res = LibrariesShortNames[Index]; 1399 return object_error::success; 1400 } 1401 1402 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1403 return getSymbolByIndex(0); 1404 } 1405 1406 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1407 DataRefImpl DRI; 1408 if (!SymtabLoadCmd) 1409 return basic_symbol_iterator(SymbolRef(DRI, this)); 1410 1411 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1412 unsigned SymbolTableEntrySize = is64Bit() ? 1413 sizeof(MachO::nlist_64) : 1414 sizeof(MachO::nlist); 1415 unsigned Offset = Symtab.symoff + 1416 Symtab.nsyms * SymbolTableEntrySize; 1417 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1418 return basic_symbol_iterator(SymbolRef(DRI, this)); 1419 } 1420 1421 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 1422 DataRefImpl DRI; 1423 if (!SymtabLoadCmd) 1424 return basic_symbol_iterator(SymbolRef(DRI, this)); 1425 1426 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1427 assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); 1428 unsigned SymbolTableEntrySize = 1429 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1430 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1431 DRI.p += Index * SymbolTableEntrySize; 1432 return basic_symbol_iterator(SymbolRef(DRI, this)); 1433 } 1434 1435 section_iterator MachOObjectFile::section_begin() const { 1436 DataRefImpl DRI; 1437 return section_iterator(SectionRef(DRI, this)); 1438 } 1439 1440 section_iterator MachOObjectFile::section_end() const { 1441 DataRefImpl DRI; 1442 DRI.d.a = Sections.size(); 1443 return section_iterator(SectionRef(DRI, this)); 1444 } 1445 1446 library_iterator MachOObjectFile::needed_library_begin() const { 1447 // TODO: implement 1448 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1449 } 1450 1451 library_iterator MachOObjectFile::needed_library_end() const { 1452 // TODO: implement 1453 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1454 } 1455 1456 uint8_t MachOObjectFile::getBytesInAddress() const { 1457 return is64Bit() ? 8 : 4; 1458 } 1459 1460 StringRef MachOObjectFile::getFileFormatName() const { 1461 unsigned CPUType = getCPUType(this); 1462 if (!is64Bit()) { 1463 switch (CPUType) { 1464 case llvm::MachO::CPU_TYPE_I386: 1465 return "Mach-O 32-bit i386"; 1466 case llvm::MachO::CPU_TYPE_ARM: 1467 return "Mach-O arm"; 1468 case llvm::MachO::CPU_TYPE_POWERPC: 1469 return "Mach-O 32-bit ppc"; 1470 default: 1471 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 1472 "64-bit object file when we're not 64-bit?"); 1473 return "Mach-O 32-bit unknown"; 1474 } 1475 } 1476 1477 // Make sure the cpu type has the correct mask. 1478 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 1479 == llvm::MachO::CPU_ARCH_ABI64 && 1480 "32-bit object file when we're 64-bit?"); 1481 1482 switch (CPUType) { 1483 case llvm::MachO::CPU_TYPE_X86_64: 1484 return "Mach-O 64-bit x86-64"; 1485 case llvm::MachO::CPU_TYPE_ARM64: 1486 return "Mach-O arm64"; 1487 case llvm::MachO::CPU_TYPE_POWERPC64: 1488 return "Mach-O 64-bit ppc64"; 1489 default: 1490 return "Mach-O 64-bit unknown"; 1491 } 1492 } 1493 1494 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1495 switch (CPUType) { 1496 case llvm::MachO::CPU_TYPE_I386: 1497 return Triple::x86; 1498 case llvm::MachO::CPU_TYPE_X86_64: 1499 return Triple::x86_64; 1500 case llvm::MachO::CPU_TYPE_ARM: 1501 return Triple::arm; 1502 case llvm::MachO::CPU_TYPE_ARM64: 1503 return Triple::arm64; 1504 case llvm::MachO::CPU_TYPE_POWERPC: 1505 return Triple::ppc; 1506 case llvm::MachO::CPU_TYPE_POWERPC64: 1507 return Triple::ppc64; 1508 default: 1509 return Triple::UnknownArch; 1510 } 1511 } 1512 1513 unsigned MachOObjectFile::getArch() const { 1514 return getArch(getCPUType(this)); 1515 } 1516 1517 StringRef MachOObjectFile::getLoadName() const { 1518 // TODO: Implement 1519 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 1520 } 1521 1522 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1523 DataRefImpl DRI; 1524 DRI.d.a = Index; 1525 return section_rel_begin(DRI); 1526 } 1527 1528 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1529 DataRefImpl DRI; 1530 DRI.d.a = Index; 1531 return section_rel_end(DRI); 1532 } 1533 1534 dice_iterator MachOObjectFile::begin_dices() const { 1535 DataRefImpl DRI; 1536 if (!DataInCodeLoadCmd) 1537 return dice_iterator(DiceRef(DRI, this)); 1538 1539 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1540 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1541 return dice_iterator(DiceRef(DRI, this)); 1542 } 1543 1544 dice_iterator MachOObjectFile::end_dices() const { 1545 DataRefImpl DRI; 1546 if (!DataInCodeLoadCmd) 1547 return dice_iterator(DiceRef(DRI, this)); 1548 1549 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1550 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1551 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1552 return dice_iterator(DiceRef(DRI, this)); 1553 } 1554 1555 StringRef 1556 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1557 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1558 return parseSegmentOrSectionName(Raw.data()); 1559 } 1560 1561 ArrayRef<char> 1562 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1563 const section_base *Base = 1564 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1565 return ArrayRef<char>(Base->sectname); 1566 } 1567 1568 ArrayRef<char> 1569 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1570 const section_base *Base = 1571 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1572 return ArrayRef<char>(Base->segname); 1573 } 1574 1575 bool 1576 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1577 const { 1578 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1579 return false; 1580 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1581 } 1582 1583 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1584 const MachO::any_relocation_info &RE) const { 1585 if (isLittleEndian()) 1586 return RE.r_word1 & 0xffffff; 1587 return RE.r_word1 >> 8; 1588 } 1589 1590 bool MachOObjectFile::getPlainRelocationExternal( 1591 const MachO::any_relocation_info &RE) const { 1592 if (isLittleEndian()) 1593 return (RE.r_word1 >> 27) & 1; 1594 return (RE.r_word1 >> 4) & 1; 1595 } 1596 1597 bool MachOObjectFile::getScatteredRelocationScattered( 1598 const MachO::any_relocation_info &RE) const { 1599 return RE.r_word0 >> 31; 1600 } 1601 1602 uint32_t MachOObjectFile::getScatteredRelocationValue( 1603 const MachO::any_relocation_info &RE) const { 1604 return RE.r_word1; 1605 } 1606 1607 unsigned MachOObjectFile::getAnyRelocationAddress( 1608 const MachO::any_relocation_info &RE) const { 1609 if (isRelocationScattered(RE)) 1610 return getScatteredRelocationAddress(RE); 1611 return getPlainRelocationAddress(RE); 1612 } 1613 1614 unsigned MachOObjectFile::getAnyRelocationPCRel( 1615 const MachO::any_relocation_info &RE) const { 1616 if (isRelocationScattered(RE)) 1617 return getScatteredRelocationPCRel(this, RE); 1618 return getPlainRelocationPCRel(this, RE); 1619 } 1620 1621 unsigned MachOObjectFile::getAnyRelocationLength( 1622 const MachO::any_relocation_info &RE) const { 1623 if (isRelocationScattered(RE)) 1624 return getScatteredRelocationLength(RE); 1625 return getPlainRelocationLength(this, RE); 1626 } 1627 1628 unsigned 1629 MachOObjectFile::getAnyRelocationType( 1630 const MachO::any_relocation_info &RE) const { 1631 if (isRelocationScattered(RE)) 1632 return getScatteredRelocationType(RE); 1633 return getPlainRelocationType(this, RE); 1634 } 1635 1636 SectionRef 1637 MachOObjectFile::getRelocationSection( 1638 const MachO::any_relocation_info &RE) const { 1639 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1640 return *section_end(); 1641 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 1642 DataRefImpl DRI; 1643 DRI.d.a = SecNum; 1644 return SectionRef(DRI, this); 1645 } 1646 1647 MachOObjectFile::LoadCommandInfo 1648 MachOObjectFile::getFirstLoadCommandInfo() const { 1649 MachOObjectFile::LoadCommandInfo Load; 1650 1651 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 1652 sizeof(MachO::mach_header); 1653 Load.Ptr = getPtr(this, HeaderSize); 1654 Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 1655 return Load; 1656 } 1657 1658 MachOObjectFile::LoadCommandInfo 1659 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1660 MachOObjectFile::LoadCommandInfo Next; 1661 Next.Ptr = L.Ptr + L.C.cmdsize; 1662 Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 1663 return Next; 1664 } 1665 1666 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1667 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1668 } 1669 1670 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1671 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1672 } 1673 1674 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1675 unsigned Index) const { 1676 const char *Sec = getSectionPtr(this, L, Index); 1677 return getStruct<MachO::section>(this, Sec); 1678 } 1679 1680 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1681 unsigned Index) const { 1682 const char *Sec = getSectionPtr(this, L, Index); 1683 return getStruct<MachO::section_64>(this, Sec); 1684 } 1685 1686 MachO::nlist 1687 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1688 const char *P = reinterpret_cast<const char *>(DRI.p); 1689 return getStruct<MachO::nlist>(this, P); 1690 } 1691 1692 MachO::nlist_64 1693 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1694 const char *P = reinterpret_cast<const char *>(DRI.p); 1695 return getStruct<MachO::nlist_64>(this, P); 1696 } 1697 1698 MachO::linkedit_data_command 1699 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1700 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1701 } 1702 1703 MachO::segment_command 1704 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1705 return getStruct<MachO::segment_command>(this, L.Ptr); 1706 } 1707 1708 MachO::segment_command_64 1709 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1710 return getStruct<MachO::segment_command_64>(this, L.Ptr); 1711 } 1712 1713 MachO::linker_options_command 1714 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 1715 return getStruct<MachO::linker_options_command>(this, L.Ptr); 1716 } 1717 1718 MachO::version_min_command 1719 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 1720 return getStruct<MachO::version_min_command>(this, L.Ptr); 1721 } 1722 1723 MachO::any_relocation_info 1724 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 1725 DataRefImpl Sec; 1726 Sec.d.a = Rel.d.a; 1727 uint32_t Offset; 1728 if (is64Bit()) { 1729 MachO::section_64 Sect = getSection64(Sec); 1730 Offset = Sect.reloff; 1731 } else { 1732 MachO::section Sect = getSection(Sec); 1733 Offset = Sect.reloff; 1734 } 1735 1736 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 1737 getPtr(this, Offset)) + Rel.d.b; 1738 return getStruct<MachO::any_relocation_info>( 1739 this, reinterpret_cast<const char *>(P)); 1740 } 1741 1742 MachO::data_in_code_entry 1743 MachOObjectFile::getDice(DataRefImpl Rel) const { 1744 const char *P = reinterpret_cast<const char *>(Rel.p); 1745 return getStruct<MachO::data_in_code_entry>(this, P); 1746 } 1747 1748 MachO::mach_header MachOObjectFile::getHeader() const { 1749 return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 1750 } 1751 1752 MachO::mach_header_64 MachOObjectFile::getHeader64() const { 1753 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 1754 } 1755 1756 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 1757 const MachO::dysymtab_command &DLC, 1758 unsigned Index) const { 1759 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 1760 return getStruct<uint32_t>(this, getPtr(this, Offset)); 1761 } 1762 1763 MachO::data_in_code_entry 1764 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 1765 unsigned Index) const { 1766 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 1767 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 1768 } 1769 1770 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 1771 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1772 } 1773 1774 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 1775 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1776 } 1777 1778 MachO::linkedit_data_command 1779 MachOObjectFile::getDataInCodeLoadCommand() const { 1780 if (DataInCodeLoadCmd) 1781 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 1782 1783 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 1784 MachO::linkedit_data_command Cmd; 1785 Cmd.cmd = MachO::LC_DATA_IN_CODE; 1786 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 1787 Cmd.dataoff = 0; 1788 Cmd.datasize = 0; 1789 return Cmd; 1790 } 1791 1792 StringRef MachOObjectFile::getStringTableData() const { 1793 MachO::symtab_command S = getSymtabLoadCommand(); 1794 return getData().substr(S.stroff, S.strsize); 1795 } 1796 1797 bool MachOObjectFile::is64Bit() const { 1798 return getType() == getMachOType(false, true) || 1799 getType() == getMachOType(true, true); 1800 } 1801 1802 void MachOObjectFile::ReadULEB128s(uint64_t Index, 1803 SmallVectorImpl<uint64_t> &Out) const { 1804 DataExtractor extractor(ObjectFile::getData(), true, 0); 1805 1806 uint32_t offset = Index; 1807 uint64_t data = 0; 1808 while (uint64_t delta = extractor.getULEB128(&offset)) { 1809 data += delta; 1810 Out.push_back(data); 1811 } 1812 } 1813 1814 ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 1815 StringRef Magic = Buffer->getBuffer().slice(0, 4); 1816 std::error_code EC; 1817 std::unique_ptr<MachOObjectFile> Ret; 1818 if (Magic == "\xFE\xED\xFA\xCE") 1819 Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); 1820 else if (Magic == "\xCE\xFA\xED\xFE") 1821 Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); 1822 else if (Magic == "\xFE\xED\xFA\xCF") 1823 Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); 1824 else if (Magic == "\xCF\xFA\xED\xFE") 1825 Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); 1826 else { 1827 delete Buffer; 1828 return object_error::parse_failed; 1829 } 1830 1831 if (EC) 1832 return EC; 1833 return Ret.release(); 1834 } 1835 1836 } // end namespace object 1837 } // end namespace llvm 1838