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