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, 631 StringRef &Result) const { 632 ArrayRef<char> Raw = getSectionRawName(Sec); 633 Result = parseSegmentOrSectionName(Raw.data()); 634 return object_error::success; 635 } 636 637 error_code 638 MachOObjectFile::getSectionAddress(DataRefImpl Sec, 639 uint64_t &Res) const { 640 if (is64Bit()) { 641 macho::Section64 Sect = getSection64(Sec); 642 Res = Sect.Address; 643 } else { 644 macho::Section Sect = getSection(Sec); 645 Res = Sect.Address; 646 } 647 return object_error::success; 648 } 649 650 error_code 651 MachOObjectFile::getSectionSize(DataRefImpl Sec, 652 uint64_t &Res) const { 653 if (is64Bit()) { 654 macho::Section64 Sect = getSection64(Sec); 655 Res = Sect.Size; 656 } else { 657 macho::Section Sect = getSection(Sec); 658 Res = Sect.Size; 659 } 660 661 return object_error::success; 662 } 663 664 error_code 665 MachOObjectFile::getSectionContents(DataRefImpl Sec, 666 StringRef &Res) const { 667 uint32_t Offset; 668 uint64_t Size; 669 670 if (is64Bit()) { 671 macho::Section64 Sect = getSection64(Sec); 672 Offset = Sect.Offset; 673 Size = Sect.Size; 674 } else { 675 macho::Section Sect =getSection(Sec); 676 Offset = Sect.Offset; 677 Size = Sect.Size; 678 } 679 680 Res = this->getData().substr(Offset, Size); 681 return object_error::success; 682 } 683 684 error_code 685 MachOObjectFile::getSectionAlignment(DataRefImpl Sec, 686 uint64_t &Res) const { 687 uint32_t Align; 688 if (is64Bit()) { 689 macho::Section64 Sect = getSection64(Sec); 690 Align = Sect.Align; 691 } else { 692 macho::Section Sect = getSection(Sec); 693 Align = Sect.Align; 694 } 695 696 Res = uint64_t(1) << Align; 697 return object_error::success; 698 } 699 700 error_code 701 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { 702 uint32_t Flags = getSectionFlags(this, Sec); 703 Res = Flags & macho::SF_PureInstructions; 704 return object_error::success; 705 } 706 707 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, 708 bool &Result) const { 709 // FIXME: Unimplemented. 710 Result = false; 711 return object_error::success; 712 } 713 714 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, 715 bool &Result) const { 716 // FIXME: Unimplemented. 717 Result = false; 718 return object_error::success; 719 } 720 721 error_code 722 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 723 bool &Result) const { 724 // FIXME: Unimplemented. 725 Result = true; 726 return object_error::success; 727 } 728 729 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 730 bool &Result) const { 731 // FIXME: Unimplemented. 732 Result = false; 733 return object_error::success; 734 } 735 736 error_code 737 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { 738 uint32_t Flags = getSectionFlags(this, Sec); 739 unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType; 740 Res = SectionType == MachO::SectionTypeZeroFill || 741 SectionType == MachO::SectionTypeZeroFillLarge; 742 return object_error::success; 743 } 744 745 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 746 bool &Result) const { 747 // Consider using the code from isSectionText to look for __const sections. 748 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 749 // to use section attributes to distinguish code from data. 750 751 // FIXME: Unimplemented. 752 Result = false; 753 return object_error::success; 754 } 755 756 error_code 757 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 758 DataRefImpl Symb, 759 bool &Result) const { 760 SymbolRef::Type ST; 761 this->getSymbolType(Symb, ST); 762 if (ST == SymbolRef::ST_Unknown) { 763 Result = false; 764 return object_error::success; 765 } 766 767 uint64_t SectBegin, SectEnd; 768 getSectionAddress(Sec, SectBegin); 769 getSectionSize(Sec, SectEnd); 770 SectEnd += SectBegin; 771 772 uint64_t SymAddr; 773 getSymbolAddress(Symb, SymAddr); 774 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 775 776 return object_error::success; 777 } 778 779 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 780 DataRefImpl ret; 781 ret.d.b = Sec.d.a; 782 return relocation_iterator(RelocationRef(ret, this)); 783 } 784 785 relocation_iterator 786 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 787 uint32_t LastReloc; 788 if (is64Bit()) { 789 macho::Section64 Sect = getSection64(Sec); 790 LastReloc = Sect.NumRelocationTableEntries; 791 } else { 792 macho::Section Sect = getSection(Sec); 793 LastReloc = Sect.NumRelocationTableEntries; 794 } 795 796 DataRefImpl Ret; 797 Ret.d.a = LastReloc; 798 Ret.d.b = Sec.d.a; 799 return relocation_iterator(RelocationRef(Ret, this)); 800 } 801 802 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 803 RelocationRef &Res) const { 804 ++Rel.d.a; 805 Res = RelocationRef(Rel, this); 806 return object_error::success; 807 } 808 809 error_code 810 MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 811 uint64_t &Res) const { 812 uint64_t SectAddress; 813 DataRefImpl Sec; 814 Sec.d.a = Rel.d.b; 815 if (is64Bit()) { 816 macho::Section64 Sect = getSection64(Sec); 817 SectAddress = Sect.Address; 818 } else { 819 macho::Section Sect = getSection(Sec); 820 SectAddress = Sect.Address; 821 } 822 823 macho::RelocationEntry RE = getRelocation(Rel); 824 uint64_t RelAddr = getAnyRelocationAddress(RE); 825 Res = SectAddress + RelAddr; 826 return object_error::success; 827 } 828 829 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 830 uint64_t &Res) const { 831 macho::RelocationEntry RE = getRelocation(Rel); 832 Res = getAnyRelocationAddress(RE); 833 return object_error::success; 834 } 835 836 error_code 837 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, 838 SymbolRef &Res) const { 839 macho::RelocationEntry RE = getRelocation(Rel); 840 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 841 bool isExtern = getPlainRelocationExternal(RE); 842 843 DataRefImpl Sym; 844 if (isExtern) { 845 Sym.d.b = SymbolIdx; 846 } 847 Res = SymbolRef(Sym, this); 848 return object_error::success; 849 } 850 851 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 852 uint64_t &Res) const { 853 macho::RelocationEntry RE = getRelocation(Rel); 854 Res = getAnyRelocationType(RE); 855 return object_error::success; 856 } 857 858 error_code 859 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 860 SmallVectorImpl<char> &Result) const { 861 StringRef res; 862 uint64_t RType; 863 getRelocationType(Rel, RType); 864 865 unsigned Arch = this->getArch(); 866 867 switch (Arch) { 868 case Triple::x86: { 869 static const char *const Table[] = { 870 "GENERIC_RELOC_VANILLA", 871 "GENERIC_RELOC_PAIR", 872 "GENERIC_RELOC_SECTDIFF", 873 "GENERIC_RELOC_PB_LA_PTR", 874 "GENERIC_RELOC_LOCAL_SECTDIFF", 875 "GENERIC_RELOC_TLV" }; 876 877 if (RType > 6) 878 res = "Unknown"; 879 else 880 res = Table[RType]; 881 break; 882 } 883 case Triple::x86_64: { 884 static const char *const Table[] = { 885 "X86_64_RELOC_UNSIGNED", 886 "X86_64_RELOC_SIGNED", 887 "X86_64_RELOC_BRANCH", 888 "X86_64_RELOC_GOT_LOAD", 889 "X86_64_RELOC_GOT", 890 "X86_64_RELOC_SUBTRACTOR", 891 "X86_64_RELOC_SIGNED_1", 892 "X86_64_RELOC_SIGNED_2", 893 "X86_64_RELOC_SIGNED_4", 894 "X86_64_RELOC_TLV" }; 895 896 if (RType > 9) 897 res = "Unknown"; 898 else 899 res = Table[RType]; 900 break; 901 } 902 case Triple::arm: { 903 static const char *const Table[] = { 904 "ARM_RELOC_VANILLA", 905 "ARM_RELOC_PAIR", 906 "ARM_RELOC_SECTDIFF", 907 "ARM_RELOC_LOCAL_SECTDIFF", 908 "ARM_RELOC_PB_LA_PTR", 909 "ARM_RELOC_BR24", 910 "ARM_THUMB_RELOC_BR22", 911 "ARM_THUMB_32BIT_BRANCH", 912 "ARM_RELOC_HALF", 913 "ARM_RELOC_HALF_SECTDIFF" }; 914 915 if (RType > 9) 916 res = "Unknown"; 917 else 918 res = Table[RType]; 919 break; 920 } 921 case Triple::ppc: { 922 static const char *const Table[] = { 923 "PPC_RELOC_VANILLA", 924 "PPC_RELOC_PAIR", 925 "PPC_RELOC_BR14", 926 "PPC_RELOC_BR24", 927 "PPC_RELOC_HI16", 928 "PPC_RELOC_LO16", 929 "PPC_RELOC_HA16", 930 "PPC_RELOC_LO14", 931 "PPC_RELOC_SECTDIFF", 932 "PPC_RELOC_PB_LA_PTR", 933 "PPC_RELOC_HI16_SECTDIFF", 934 "PPC_RELOC_LO16_SECTDIFF", 935 "PPC_RELOC_HA16_SECTDIFF", 936 "PPC_RELOC_JBSR", 937 "PPC_RELOC_LO14_SECTDIFF", 938 "PPC_RELOC_LOCAL_SECTDIFF" }; 939 940 res = Table[RType]; 941 break; 942 } 943 case Triple::UnknownArch: 944 res = "Unknown"; 945 break; 946 } 947 Result.append(res.begin(), res.end()); 948 return object_error::success; 949 } 950 951 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 952 int64_t &Res) const { 953 Res = 0; 954 return object_error::success; 955 } 956 957 error_code 958 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 959 SmallVectorImpl<char> &Result) const { 960 macho::RelocationEntry RE = getRelocation(Rel); 961 962 unsigned Arch = this->getArch(); 963 964 std::string fmtbuf; 965 raw_string_ostream fmt(fmtbuf); 966 unsigned Type = this->getAnyRelocationType(RE); 967 bool IsPCRel = this->getAnyRelocationPCRel(RE); 968 969 // Determine any addends that should be displayed with the relocation. 970 // These require decoding the relocation type, which is triple-specific. 971 972 // X86_64 has entirely custom relocation types. 973 if (Arch == Triple::x86_64) { 974 bool isPCRel = getAnyRelocationPCRel(RE); 975 976 switch (Type) { 977 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD 978 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT 979 printRelocationTargetName(this, RE, fmt); 980 fmt << "@GOT"; 981 if (isPCRel) fmt << "PCREL"; 982 break; 983 } 984 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR 985 DataRefImpl RelNext = Rel; 986 RelNext.d.a++; 987 macho::RelocationEntry RENext = getRelocation(RelNext); 988 989 // X86_64_SUBTRACTOR must be followed by a relocation of type 990 // X86_64_RELOC_UNSIGNED. 991 // NOTE: Scattered relocations don't exist on x86_64. 992 unsigned RType = getAnyRelocationType(RENext); 993 if (RType != 0) 994 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 995 "X86_64_RELOC_SUBTRACTOR."); 996 997 // The X86_64_RELOC_UNSIGNED contains the minuend symbol, 998 // X86_64_SUBTRACTOR contains to the subtrahend. 999 printRelocationTargetName(this, RENext, fmt); 1000 fmt << "-"; 1001 printRelocationTargetName(this, RE, fmt); 1002 break; 1003 } 1004 case macho::RIT_X86_64_TLV: 1005 printRelocationTargetName(this, RE, fmt); 1006 fmt << "@TLV"; 1007 if (isPCRel) fmt << "P"; 1008 break; 1009 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 1010 printRelocationTargetName(this, RE, fmt); 1011 fmt << "-1"; 1012 break; 1013 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 1014 printRelocationTargetName(this, RE, fmt); 1015 fmt << "-2"; 1016 break; 1017 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 1018 printRelocationTargetName(this, RE, fmt); 1019 fmt << "-4"; 1020 break; 1021 default: 1022 printRelocationTargetName(this, RE, fmt); 1023 break; 1024 } 1025 // X86 and ARM share some relocation types in common. 1026 } else if (Arch == Triple::x86 || Arch == Triple::arm) { 1027 // Generic relocation types... 1028 switch (Type) { 1029 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info 1030 return object_error::success; 1031 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF 1032 DataRefImpl RelNext = Rel; 1033 RelNext.d.a++; 1034 macho::RelocationEntry 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 != 1) 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) { 1052 // All X86 relocations that need special printing were already 1053 // handled in the generic code. 1054 switch (Type) { 1055 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF 1056 DataRefImpl RelNext = Rel; 1057 RelNext.d.a++; 1058 macho::RelocationEntry RENext = getRelocation(RelNext); 1059 1060 // X86 sect diff's must be followed by a relocation of type 1061 // GENERIC_RELOC_PAIR. 1062 unsigned RType = getAnyRelocationType(RENext); 1063 if (RType != 1) 1064 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1065 "GENERIC_RELOC_LOCAL_SECTDIFF."); 1066 1067 printRelocationTargetName(this, RE, fmt); 1068 fmt << "-"; 1069 printRelocationTargetName(this, RENext, fmt); 1070 break; 1071 } 1072 case macho::RIT_Generic_TLV: { 1073 printRelocationTargetName(this, RE, fmt); 1074 fmt << "@TLV"; 1075 if (IsPCRel) fmt << "P"; 1076 break; 1077 } 1078 default: 1079 printRelocationTargetName(this, RE, fmt); 1080 } 1081 } else { // ARM-specific relocations 1082 switch (Type) { 1083 case macho::RIT_ARM_Half: // ARM_RELOC_HALF 1084 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF 1085 // Half relocations steal a bit from the length field to encode 1086 // whether this is an upper16 or a lower16 relocation. 1087 bool isUpper = getAnyRelocationLength(RE) >> 1; 1088 1089 if (isUpper) 1090 fmt << ":upper16:("; 1091 else 1092 fmt << ":lower16:("; 1093 printRelocationTargetName(this, RE, fmt); 1094 1095 DataRefImpl RelNext = Rel; 1096 RelNext.d.a++; 1097 macho::RelocationEntry RENext = getRelocation(RelNext); 1098 1099 // ARM half relocs must be followed by a relocation of type 1100 // ARM_RELOC_PAIR. 1101 unsigned RType = getAnyRelocationType(RENext); 1102 if (RType != 1) 1103 report_fatal_error("Expected ARM_RELOC_PAIR after " 1104 "GENERIC_RELOC_HALF"); 1105 1106 // NOTE: The half of the target virtual address is stashed in the 1107 // address field of the secondary relocation, but we can't reverse 1108 // engineer the constant offset from it without decoding the movw/movt 1109 // instruction to find the other half in its immediate field. 1110 1111 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1112 // symbol/section pointer of the follow-on relocation. 1113 if (Type == macho::RIT_ARM_HalfDifference) { 1114 fmt << "-"; 1115 printRelocationTargetName(this, RENext, fmt); 1116 } 1117 1118 fmt << ")"; 1119 break; 1120 } 1121 default: { 1122 printRelocationTargetName(this, RE, fmt); 1123 } 1124 } 1125 } 1126 } else 1127 printRelocationTargetName(this, RE, fmt); 1128 1129 fmt.flush(); 1130 Result.append(fmtbuf.begin(), fmtbuf.end()); 1131 return object_error::success; 1132 } 1133 1134 error_code 1135 MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 1136 bool &Result) const { 1137 unsigned Arch = getArch(); 1138 uint64_t Type; 1139 getRelocationType(Rel, Type); 1140 1141 Result = false; 1142 1143 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1144 // is always hidden. 1145 if (Arch == Triple::x86 || Arch == Triple::arm) { 1146 if (Type == macho::RIT_Pair) Result = true; 1147 } else if (Arch == Triple::x86_64) { 1148 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1149 // an X864_64_RELOC_SUBTRACTOR. 1150 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { 1151 DataRefImpl RelPrev = Rel; 1152 RelPrev.d.a--; 1153 uint64_t PrevType; 1154 getRelocationType(RelPrev, PrevType); 1155 if (PrevType == macho::RIT_X86_64_Subtractor) 1156 Result = true; 1157 } 1158 } 1159 1160 return object_error::success; 1161 } 1162 1163 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1164 LibraryRef &Res) const { 1165 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1166 } 1167 1168 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1169 StringRef &Res) const { 1170 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1171 } 1172 1173 symbol_iterator MachOObjectFile::begin_symbols() const { 1174 // DRI.d.a = segment number; DRI.d.b = symbol index. 1175 DataRefImpl DRI; 1176 return symbol_iterator(SymbolRef(DRI, this)); 1177 } 1178 1179 symbol_iterator MachOObjectFile::end_symbols() const { 1180 DataRefImpl DRI; 1181 if (SymtabLoadCmd) { 1182 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); 1183 DRI.d.b = Symtab.NumSymbolTableEntries; 1184 } 1185 return symbol_iterator(SymbolRef(DRI, this)); 1186 } 1187 1188 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { 1189 // TODO: implement 1190 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 1191 } 1192 1193 symbol_iterator MachOObjectFile::end_dynamic_symbols() const { 1194 // TODO: implement 1195 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 1196 } 1197 1198 section_iterator MachOObjectFile::begin_sections() const { 1199 DataRefImpl DRI; 1200 return section_iterator(SectionRef(DRI, this)); 1201 } 1202 1203 section_iterator MachOObjectFile::end_sections() const { 1204 DataRefImpl DRI; 1205 DRI.d.a = Sections.size(); 1206 return section_iterator(SectionRef(DRI, this)); 1207 } 1208 1209 library_iterator MachOObjectFile::begin_libraries_needed() const { 1210 // TODO: implement 1211 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1212 } 1213 1214 library_iterator MachOObjectFile::end_libraries_needed() const { 1215 // TODO: implement 1216 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1217 } 1218 1219 uint8_t MachOObjectFile::getBytesInAddress() const { 1220 return is64Bit() ? 8 : 4; 1221 } 1222 1223 StringRef MachOObjectFile::getFileFormatName() const { 1224 unsigned CPUType = getCPUType(this); 1225 if (!is64Bit()) { 1226 switch (CPUType) { 1227 case llvm::MachO::CPUTypeI386: 1228 return "Mach-O 32-bit i386"; 1229 case llvm::MachO::CPUTypeARM: 1230 return "Mach-O arm"; 1231 case llvm::MachO::CPUTypePowerPC: 1232 return "Mach-O 32-bit ppc"; 1233 default: 1234 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 && 1235 "64-bit object file when we're not 64-bit?"); 1236 return "Mach-O 32-bit unknown"; 1237 } 1238 } 1239 1240 // Make sure the cpu type has the correct mask. 1241 assert((CPUType & llvm::MachO::CPUArchABI64) 1242 == llvm::MachO::CPUArchABI64 && 1243 "32-bit object file when we're 64-bit?"); 1244 1245 switch (CPUType) { 1246 case llvm::MachO::CPUTypeX86_64: 1247 return "Mach-O 64-bit x86-64"; 1248 case llvm::MachO::CPUTypePowerPC64: 1249 return "Mach-O 64-bit ppc64"; 1250 default: 1251 return "Mach-O 64-bit unknown"; 1252 } 1253 } 1254 1255 unsigned MachOObjectFile::getArch() const { 1256 switch (getCPUType(this)) { 1257 case llvm::MachO::CPUTypeI386: 1258 return Triple::x86; 1259 case llvm::MachO::CPUTypeX86_64: 1260 return Triple::x86_64; 1261 case llvm::MachO::CPUTypeARM: 1262 return Triple::arm; 1263 case llvm::MachO::CPUTypePowerPC: 1264 return Triple::ppc; 1265 case llvm::MachO::CPUTypePowerPC64: 1266 return Triple::ppc64; 1267 default: 1268 return Triple::UnknownArch; 1269 } 1270 } 1271 1272 StringRef MachOObjectFile::getLoadName() const { 1273 // TODO: Implement 1274 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 1275 } 1276 1277 StringRef 1278 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1279 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1280 return parseSegmentOrSectionName(Raw.data()); 1281 } 1282 1283 ArrayRef<char> 1284 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1285 const SectionBase *Base = 1286 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]); 1287 return ArrayRef<char>(Base->Name); 1288 } 1289 1290 ArrayRef<char> 1291 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1292 const SectionBase *Base = 1293 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]); 1294 return ArrayRef<char>(Base->SegmentName); 1295 } 1296 1297 bool 1298 MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE) 1299 const { 1300 if (getCPUType(this) == llvm::MachO::CPUTypeX86_64) 1301 return false; 1302 return getPlainRelocationAddress(RE) & macho::RF_Scattered; 1303 } 1304 1305 unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const { 1306 if (isLittleEndian()) 1307 return RE.Word1 & 0xffffff; 1308 return RE.Word1 >> 8; 1309 } 1310 1311 bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const { 1312 if (isLittleEndian()) 1313 return (RE.Word1 >> 27) & 1; 1314 return (RE.Word1 >> 4) & 1; 1315 } 1316 1317 bool 1318 MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const { 1319 return RE.Word0 >> 31; 1320 } 1321 1322 uint32_t 1323 MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const { 1324 return RE.Word1; 1325 } 1326 1327 unsigned 1328 MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const { 1329 if (isRelocationScattered(RE)) 1330 return getScatteredRelocationAddress(RE); 1331 return getPlainRelocationAddress(RE); 1332 } 1333 1334 unsigned 1335 MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const { 1336 if (isRelocationScattered(RE)) 1337 return getScatteredRelocationPCRel(this, RE); 1338 return getPlainRelocationPCRel(this, RE); 1339 } 1340 1341 unsigned 1342 MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const { 1343 if (isRelocationScattered(RE)) 1344 return getScatteredRelocationLength(RE); 1345 return getPlainRelocationLength(this, RE); 1346 } 1347 1348 unsigned 1349 MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const { 1350 if (isRelocationScattered(RE)) 1351 return getScatteredRelocationType(RE); 1352 return getPlainRelocationType(this, RE); 1353 } 1354 1355 MachOObjectFile::LoadCommandInfo 1356 MachOObjectFile::getFirstLoadCommandInfo() const { 1357 MachOObjectFile::LoadCommandInfo Load; 1358 1359 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size; 1360 Load.Ptr = getPtr(this, HeaderSize); 1361 Load.C = getStruct<macho::LoadCommand>(this, Load.Ptr); 1362 return Load; 1363 } 1364 1365 MachOObjectFile::LoadCommandInfo 1366 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1367 MachOObjectFile::LoadCommandInfo Next; 1368 Next.Ptr = L.Ptr + L.C.Size; 1369 Next.C = getStruct<macho::LoadCommand>(this, Next.Ptr); 1370 return Next; 1371 } 1372 1373 macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const { 1374 return getStruct<macho::Section>(this, Sections[DRI.d.a]); 1375 } 1376 1377 macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1378 return getStruct<macho::Section64>(this, Sections[DRI.d.a]); 1379 } 1380 1381 macho::SymbolTableEntry 1382 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1383 const char *P = getSymbolTableEntryPtr(this, DRI); 1384 return getStruct<macho::SymbolTableEntry>(this, P); 1385 } 1386 1387 macho::Symbol64TableEntry 1388 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1389 const char *P = getSymbolTableEntryPtr(this, DRI); 1390 return getStruct<macho::Symbol64TableEntry>(this, P); 1391 } 1392 1393 macho::LinkeditDataLoadCommand 1394 MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const { 1395 return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr); 1396 } 1397 1398 macho::RelocationEntry 1399 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 1400 uint32_t RelOffset; 1401 DataRefImpl Sec; 1402 Sec.d.a = Rel.d.b; 1403 if (is64Bit()) { 1404 macho::Section64 Sect = getSection64(Sec); 1405 RelOffset = Sect.RelocationTableOffset; 1406 } else { 1407 macho::Section Sect = getSection(Sec); 1408 RelOffset = Sect.RelocationTableOffset; 1409 } 1410 1411 uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry); 1412 return getStruct<macho::RelocationEntry>(this, getPtr(this, Offset)); 1413 } 1414 1415 macho::Header MachOObjectFile::getHeader() const { 1416 return getStruct<macho::Header>(this, getPtr(this, 0)); 1417 } 1418 1419 macho::SymtabLoadCommand 1420 MachOObjectFile::getSymtabLoadCommand() const { 1421 return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd); 1422 } 1423 1424 bool MachOObjectFile::is64Bit() const { 1425 return getType() == getMachOType(false, true) || 1426 getType() == getMachOType(true, true); 1427 } 1428 1429 void MachOObjectFile::ReadULEB128s(uint64_t Index, 1430 SmallVectorImpl<uint64_t> &Out) const { 1431 DataExtractor extractor(ObjectFile::getData(), true, 0); 1432 1433 uint32_t offset = Index; 1434 uint64_t data = 0; 1435 while (uint64_t delta = extractor.getULEB128(&offset)) { 1436 data += delta; 1437 Out.push_back(data); 1438 } 1439 } 1440 1441 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 1442 StringRef Magic = Buffer->getBuffer().slice(0, 4); 1443 error_code ec; 1444 ObjectFile *Ret; 1445 if (Magic == "\xFE\xED\xFA\xCE") 1446 Ret = new MachOObjectFile(Buffer, false, false, ec); 1447 else if (Magic == "\xCE\xFA\xED\xFE") 1448 Ret = new MachOObjectFile(Buffer, true, false, ec); 1449 else if (Magic == "\xFE\xED\xFA\xCF") 1450 Ret = new MachOObjectFile(Buffer, false, true, ec); 1451 else if (Magic == "\xCF\xFA\xED\xFE") 1452 Ret = new MachOObjectFile(Buffer, true, true, ec); 1453 else 1454 return NULL; 1455 1456 if (ec) 1457 return NULL; 1458 return Ret; 1459 } 1460 1461 } // end namespace object 1462 } // end namespace llvm 1463