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