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