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