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