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