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