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