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 uint8_t MachOSectionIndex; 279 if (MachOObj->is64Bit()) { 280 InMemoryStruct<macho::Symbol64TableEntry> Entry; 281 getSymbol64TableEntry(DRI, Entry); 282 MachOFlags = Entry->Flags; 283 MachOType = Entry->Type; 284 MachOSectionIndex = Entry->SectionIndex; 285 } else { 286 InMemoryStruct<macho::SymbolTableEntry> Entry; 287 getSymbolTableEntry(DRI, Entry); 288 MachOFlags = Entry->Flags; 289 MachOType = Entry->Type; 290 MachOSectionIndex = Entry->SectionIndex; 291 } 292 293 // TODO: Correctly set SF_ThreadLocal 294 Result = SymbolRef::SF_None; 295 296 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) 297 Result |= SymbolRef::SF_Undefined; 298 299 if (MachOFlags & macho::STF_StabsEntryMask) 300 Result |= SymbolRef::SF_FormatSpecific; 301 302 if (MachOType & MachO::NlistMaskExternal) { 303 Result |= SymbolRef::SF_Global; 304 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) 305 Result |= SymbolRef::SF_Common; 306 } 307 308 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) 309 Result |= SymbolRef::SF_Weak; 310 311 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) 312 Result |= SymbolRef::SF_Absolute; 313 314 return object_error::success; 315 } 316 317 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 318 section_iterator &Res) const { 319 uint8_t index; 320 if (MachOObj->is64Bit()) { 321 InMemoryStruct<macho::Symbol64TableEntry> Entry; 322 getSymbol64TableEntry(Symb, Entry); 323 index = Entry->SectionIndex; 324 } else { 325 InMemoryStruct<macho::SymbolTableEntry> Entry; 326 getSymbolTableEntry(Symb, Entry); 327 index = Entry->SectionIndex; 328 } 329 330 if (index == 0) 331 Res = end_sections(); 332 else 333 Res = section_iterator(SectionRef(Sections[index-1], this)); 334 335 return object_error::success; 336 } 337 338 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 339 SymbolRef::Type &Res) const { 340 uint8_t n_type; 341 if (MachOObj->is64Bit()) { 342 InMemoryStruct<macho::Symbol64TableEntry> Entry; 343 getSymbol64TableEntry(Symb, Entry); 344 n_type = Entry->Type; 345 } else { 346 InMemoryStruct<macho::SymbolTableEntry> Entry; 347 getSymbolTableEntry(Symb, Entry); 348 n_type = Entry->Type; 349 } 350 Res = SymbolRef::ST_Other; 351 352 // If this is a STAB debugging symbol, we can do nothing more. 353 if (n_type & MachO::NlistMaskStab) { 354 Res = SymbolRef::ST_Debug; 355 return object_error::success; 356 } 357 358 switch (n_type & MachO::NlistMaskType) { 359 case MachO::NListTypeUndefined : 360 Res = SymbolRef::ST_Unknown; 361 break; 362 case MachO::NListTypeSection : 363 Res = SymbolRef::ST_Function; 364 break; 365 } 366 return object_error::success; 367 } 368 369 370 symbol_iterator MachOObjectFile::begin_symbols() const { 371 // DRI.d.a = segment number; DRI.d.b = symbol index. 372 DataRefImpl DRI; 373 moveToNextSymbol(DRI); 374 return symbol_iterator(SymbolRef(DRI, this)); 375 } 376 377 symbol_iterator MachOObjectFile::end_symbols() const { 378 DataRefImpl DRI; 379 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 380 return symbol_iterator(SymbolRef(DRI, this)); 381 } 382 383 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { 384 // TODO: implement 385 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 386 } 387 388 symbol_iterator MachOObjectFile::end_dynamic_symbols() const { 389 // TODO: implement 390 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 391 } 392 393 library_iterator MachOObjectFile::begin_libraries_needed() const { 394 // TODO: implement 395 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 396 } 397 398 library_iterator MachOObjectFile::end_libraries_needed() const { 399 // TODO: implement 400 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 401 } 402 403 StringRef MachOObjectFile::getLoadName() const { 404 // TODO: Implement 405 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 406 } 407 408 /*===-- Sections ----------------------------------------------------------===*/ 409 410 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { 411 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 412 while (DRI.d.a < LoadCommandCount) { 413 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 414 if (LCI.Command.Type == macho::LCT_Segment) { 415 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd; 416 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); 417 if (DRI.d.b < SegmentLoadCmd->NumSections) 418 return; 419 } else if (LCI.Command.Type == macho::LCT_Segment64) { 420 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd; 421 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); 422 if (DRI.d.b < Segment64LoadCmd->NumSections) 423 return; 424 } 425 426 DRI.d.a++; 427 DRI.d.b = 0; 428 } 429 } 430 431 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, 432 SectionRef &Result) const { 433 DRI.d.b++; 434 moveToNextSection(DRI); 435 Result = SectionRef(DRI, this); 436 return object_error::success; 437 } 438 439 void 440 MachOObjectFile::getSection(DataRefImpl DRI, 441 InMemoryStruct<macho::Section> &Res) const { 442 InMemoryStruct<macho::SegmentLoadCommand> SLC; 443 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 444 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 445 MachOObj->ReadSection(LCI, DRI.d.b, Res); 446 } 447 448 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { 449 SectionList::const_iterator loc = 450 std::find(Sections.begin(), Sections.end(), Sec); 451 assert(loc != Sections.end() && "Sec is not a valid section!"); 452 return std::distance(Sections.begin(), loc); 453 } 454 455 void 456 MachOObjectFile::getSection64(DataRefImpl DRI, 457 InMemoryStruct<macho::Section64> &Res) const { 458 InMemoryStruct<macho::Segment64LoadCommand> SLC; 459 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 460 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 461 MachOObj->ReadSection64(LCI, DRI.d.b, Res); 462 } 463 464 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { 465 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 466 if (LCI.Command.Type == macho::LCT_Segment64) 467 return true; 468 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); 469 return false; 470 } 471 472 error_code MachOObjectFile::getSectionName(DataRefImpl DRI, 473 StringRef &Result) const { 474 // FIXME: thread safety. 475 static char result[34]; 476 if (is64BitLoadCommand(MachOObj, DRI)) { 477 InMemoryStruct<macho::Segment64LoadCommand> SLC; 478 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 479 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 480 InMemoryStruct<macho::Section64> Sect; 481 MachOObj->ReadSection64(LCI, DRI.d.b, Sect); 482 483 strcpy(result, Sect->SegmentName); 484 strcat(result, ","); 485 strcat(result, Sect->Name); 486 } else { 487 InMemoryStruct<macho::SegmentLoadCommand> SLC; 488 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 489 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 490 InMemoryStruct<macho::Section> Sect; 491 MachOObj->ReadSection(LCI, DRI.d.b, Sect); 492 493 strcpy(result, Sect->SegmentName); 494 strcat(result, ","); 495 strcat(result, Sect->Name); 496 } 497 Result = StringRef(result); 498 return object_error::success; 499 } 500 501 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, 502 uint64_t &Result) const { 503 if (is64BitLoadCommand(MachOObj, DRI)) { 504 InMemoryStruct<macho::Section64> Sect; 505 getSection64(DRI, Sect); 506 Result = Sect->Address; 507 } else { 508 InMemoryStruct<macho::Section> Sect; 509 getSection(DRI, Sect); 510 Result = Sect->Address; 511 } 512 return object_error::success; 513 } 514 515 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, 516 uint64_t &Result) const { 517 if (is64BitLoadCommand(MachOObj, DRI)) { 518 InMemoryStruct<macho::Section64> Sect; 519 getSection64(DRI, Sect); 520 Result = Sect->Size; 521 } else { 522 InMemoryStruct<macho::Section> Sect; 523 getSection(DRI, Sect); 524 Result = Sect->Size; 525 } 526 return object_error::success; 527 } 528 529 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, 530 StringRef &Result) const { 531 if (is64BitLoadCommand(MachOObj, DRI)) { 532 InMemoryStruct<macho::Section64> Sect; 533 getSection64(DRI, Sect); 534 Result = MachOObj->getData(Sect->Offset, Sect->Size); 535 } else { 536 InMemoryStruct<macho::Section> Sect; 537 getSection(DRI, Sect); 538 Result = MachOObj->getData(Sect->Offset, Sect->Size); 539 } 540 return object_error::success; 541 } 542 543 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, 544 uint64_t &Result) const { 545 if (is64BitLoadCommand(MachOObj, DRI)) { 546 InMemoryStruct<macho::Section64> Sect; 547 getSection64(DRI, Sect); 548 Result = uint64_t(1) << Sect->Align; 549 } else { 550 InMemoryStruct<macho::Section> Sect; 551 getSection(DRI, Sect); 552 Result = uint64_t(1) << Sect->Align; 553 } 554 return object_error::success; 555 } 556 557 error_code MachOObjectFile::isSectionText(DataRefImpl DRI, 558 bool &Result) const { 559 if (is64BitLoadCommand(MachOObj, DRI)) { 560 InMemoryStruct<macho::Section64> Sect; 561 getSection64(DRI, Sect); 562 Result = !strcmp(Sect->Name, "__text"); 563 } else { 564 InMemoryStruct<macho::Section> Sect; 565 getSection(DRI, Sect); 566 Result = !strcmp(Sect->Name, "__text"); 567 } 568 return object_error::success; 569 } 570 571 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, 572 bool &Result) const { 573 // FIXME: Unimplemented. 574 Result = false; 575 return object_error::success; 576 } 577 578 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, 579 bool &Result) const { 580 // FIXME: Unimplemented. 581 Result = false; 582 return object_error::success; 583 } 584 585 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 586 bool &Result) const { 587 // FIXME: Unimplemented 588 Result = true; 589 return object_error::success; 590 } 591 592 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 593 bool &Result) const { 594 // FIXME: Unimplemented 595 Result = false; 596 return object_error::success; 597 } 598 599 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, 600 bool &Result) const { 601 if (MachOObj->is64Bit()) { 602 InMemoryStruct<macho::Section64> Sect; 603 getSection64(DRI, Sect); 604 Result = (Sect->Flags & MachO::SectionTypeZeroFill || 605 Sect->Flags & MachO::SectionTypeZeroFillLarge); 606 } else { 607 InMemoryStruct<macho::Section> Sect; 608 getSection(DRI, Sect); 609 Result = (Sect->Flags & MachO::SectionTypeZeroFill || 610 Sect->Flags & MachO::SectionTypeZeroFillLarge); 611 } 612 613 return object_error::success; 614 } 615 616 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 617 DataRefImpl Symb, 618 bool &Result) const { 619 SymbolRef::Type ST; 620 getSymbolType(Symb, ST); 621 if (ST == SymbolRef::ST_Unknown) { 622 Result = false; 623 return object_error::success; 624 } 625 626 uint64_t SectBegin, SectEnd; 627 getSectionAddress(Sec, SectBegin); 628 getSectionSize(Sec, SectEnd); 629 SectEnd += SectBegin; 630 631 if (MachOObj->is64Bit()) { 632 InMemoryStruct<macho::Symbol64TableEntry> Entry; 633 getSymbol64TableEntry(Symb, Entry); 634 uint64_t SymAddr= Entry->Value; 635 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 636 } else { 637 InMemoryStruct<macho::SymbolTableEntry> Entry; 638 getSymbolTableEntry(Symb, Entry); 639 uint64_t SymAddr= Entry->Value; 640 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 641 } 642 643 return object_error::success; 644 } 645 646 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 647 DataRefImpl ret; 648 ret.d.b = getSectionIndex(Sec); 649 return relocation_iterator(RelocationRef(ret, this)); 650 } 651 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 652 uint32_t last_reloc; 653 if (is64BitLoadCommand(MachOObj, Sec)) { 654 InMemoryStruct<macho::Section64> Sect; 655 getSection64(Sec, Sect); 656 last_reloc = Sect->NumRelocationTableEntries; 657 } else { 658 InMemoryStruct<macho::Section> Sect; 659 getSection(Sec, Sect); 660 last_reloc = Sect->NumRelocationTableEntries; 661 } 662 DataRefImpl ret; 663 ret.d.a = last_reloc; 664 ret.d.b = getSectionIndex(Sec); 665 return relocation_iterator(RelocationRef(ret, this)); 666 } 667 668 section_iterator MachOObjectFile::begin_sections() const { 669 DataRefImpl DRI; 670 moveToNextSection(DRI); 671 return section_iterator(SectionRef(DRI, this)); 672 } 673 674 section_iterator MachOObjectFile::end_sections() const { 675 DataRefImpl DRI; 676 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 677 return section_iterator(SectionRef(DRI, this)); 678 } 679 680 /*===-- Relocations -------------------------------------------------------===*/ 681 682 void MachOObjectFile:: 683 getRelocation(DataRefImpl Rel, 684 InMemoryStruct<macho::RelocationEntry> &Res) const { 685 uint32_t relOffset; 686 if (MachOObj->is64Bit()) { 687 InMemoryStruct<macho::Section64> Sect; 688 getSection64(Sections[Rel.d.b], Sect); 689 relOffset = Sect->RelocationTableOffset; 690 } else { 691 InMemoryStruct<macho::Section> Sect; 692 getSection(Sections[Rel.d.b], Sect); 693 relOffset = Sect->RelocationTableOffset; 694 } 695 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); 696 } 697 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 698 RelocationRef &Res) const { 699 ++Rel.d.a; 700 Res = RelocationRef(Rel, this); 701 return object_error::success; 702 } 703 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 704 uint64_t &Res) const { 705 const uint8_t* sectAddress = 0; 706 if (MachOObj->is64Bit()) { 707 InMemoryStruct<macho::Section64> Sect; 708 getSection64(Sections[Rel.d.b], Sect); 709 sectAddress += Sect->Address; 710 } else { 711 InMemoryStruct<macho::Section> Sect; 712 getSection(Sections[Rel.d.b], Sect); 713 sectAddress += Sect->Address; 714 } 715 InMemoryStruct<macho::RelocationEntry> RE; 716 getRelocation(Rel, RE); 717 718 unsigned Arch = getArch(); 719 bool isScattered = (Arch != Triple::x86_64) && 720 (RE->Word0 & macho::RF_Scattered); 721 uint64_t RelAddr = 0; 722 if (isScattered) 723 RelAddr = RE->Word0 & 0xFFFFFF; 724 else 725 RelAddr = RE->Word0; 726 727 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr); 728 return object_error::success; 729 } 730 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 731 uint64_t &Res) const { 732 InMemoryStruct<macho::RelocationEntry> RE; 733 getRelocation(Rel, RE); 734 735 unsigned Arch = getArch(); 736 bool isScattered = (Arch != Triple::x86_64) && 737 (RE->Word0 & macho::RF_Scattered); 738 if (isScattered) 739 Res = RE->Word0 & 0xFFFFFF; 740 else 741 Res = RE->Word0; 742 return object_error::success; 743 } 744 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, 745 SymbolRef &Res) const { 746 InMemoryStruct<macho::RelocationEntry> RE; 747 getRelocation(Rel, RE); 748 uint32_t SymbolIdx = RE->Word1 & 0xffffff; 749 bool isExtern = (RE->Word1 >> 27) & 1; 750 751 DataRefImpl Sym; 752 moveToNextSymbol(Sym); 753 if (isExtern) { 754 for (unsigned i = 0; i < SymbolIdx; i++) { 755 Sym.d.b++; 756 moveToNextSymbol(Sym); 757 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && 758 "Relocation symbol index out of range!"); 759 } 760 } 761 Res = SymbolRef(Sym, this); 762 return object_error::success; 763 } 764 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 765 uint64_t &Res) const { 766 InMemoryStruct<macho::RelocationEntry> RE; 767 getRelocation(Rel, RE); 768 Res = RE->Word0; 769 Res <<= 32; 770 Res |= RE->Word1; 771 return object_error::success; 772 } 773 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 774 SmallVectorImpl<char> &Result) const { 775 // TODO: Support scattered relocations. 776 StringRef res; 777 InMemoryStruct<macho::RelocationEntry> RE; 778 getRelocation(Rel, RE); 779 780 unsigned Arch = getArch(); 781 bool isScattered = (Arch != Triple::x86_64) && 782 (RE->Word0 & macho::RF_Scattered); 783 784 unsigned r_type; 785 if (isScattered) 786 r_type = (RE->Word0 >> 24) & 0xF; 787 else 788 r_type = (RE->Word1 >> 28) & 0xF; 789 790 switch (Arch) { 791 case Triple::x86: { 792 const char* Table[] = { 793 "GENERIC_RELOC_VANILLA", 794 "GENERIC_RELOC_PAIR", 795 "GENERIC_RELOC_SECTDIFF", 796 "GENERIC_RELOC_PB_LA_PTR", 797 "GENERIC_RELOC_LOCAL_SECTDIFF", 798 "GENERIC_RELOC_TLV" }; 799 800 if (r_type > 6) 801 res = "Unknown"; 802 else 803 res = Table[r_type]; 804 break; 805 } 806 case Triple::x86_64: { 807 const char* Table[] = { 808 "X86_64_RELOC_UNSIGNED", 809 "X86_64_RELOC_SIGNED", 810 "X86_64_RELOC_BRANCH", 811 "X86_64_RELOC_GOT_LOAD", 812 "X86_64_RELOC_GOT", 813 "X86_64_RELOC_SUBTRACTOR", 814 "X86_64_RELOC_SIGNED_1", 815 "X86_64_RELOC_SIGNED_2", 816 "X86_64_RELOC_SIGNED_4", 817 "X86_64_RELOC_TLV" }; 818 819 if (r_type > 9) 820 res = "Unknown"; 821 else 822 res = Table[r_type]; 823 break; 824 } 825 case Triple::arm: { 826 const char* Table[] = { 827 "ARM_RELOC_VANILLA", 828 "ARM_RELOC_PAIR", 829 "ARM_RELOC_SECTDIFF", 830 "ARM_RELOC_LOCAL_SECTDIFF", 831 "ARM_RELOC_PB_LA_PTR", 832 "ARM_RELOC_BR24", 833 "ARM_THUMB_RELOC_BR22", 834 "ARM_THUMB_32BIT_BRANCH", 835 "ARM_RELOC_HALF", 836 "ARM_RELOC_HALF_SECTDIFF" }; 837 838 if (r_type > 9) 839 res = "Unknown"; 840 else 841 res = Table[r_type]; 842 break; 843 } 844 case Triple::ppc: { 845 const char* Table[] = { 846 "PPC_RELOC_VANILLA", 847 "PPC_RELOC_PAIR", 848 "PPC_RELOC_BR14", 849 "PPC_RELOC_BR24", 850 "PPC_RELOC_HI16", 851 "PPC_RELOC_LO16", 852 "PPC_RELOC_HA16", 853 "PPC_RELOC_LO14", 854 "PPC_RELOC_SECTDIFF", 855 "PPC_RELOC_PB_LA_PTR", 856 "PPC_RELOC_HI16_SECTDIFF", 857 "PPC_RELOC_LO16_SECTDIFF", 858 "PPC_RELOC_HA16_SECTDIFF", 859 "PPC_RELOC_JBSR", 860 "PPC_RELOC_LO14_SECTDIFF", 861 "PPC_RELOC_LOCAL_SECTDIFF" }; 862 863 res = Table[r_type]; 864 break; 865 } 866 case Triple::UnknownArch: 867 res = "Unknown"; 868 break; 869 } 870 Result.append(res.begin(), res.end()); 871 return object_error::success; 872 } 873 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 874 int64_t &Res) const { 875 InMemoryStruct<macho::RelocationEntry> RE; 876 getRelocation(Rel, RE); 877 bool isExtern = (RE->Word1 >> 27) & 1; 878 Res = 0; 879 if (!isExtern) { 880 const uint8_t* sectAddress = base(); 881 if (MachOObj->is64Bit()) { 882 InMemoryStruct<macho::Section64> Sect; 883 getSection64(Sections[Rel.d.b], Sect); 884 sectAddress += Sect->Offset; 885 } else { 886 InMemoryStruct<macho::Section> Sect; 887 getSection(Sections[Rel.d.b], Sect); 888 sectAddress += Sect->Offset; 889 } 890 Res = reinterpret_cast<uintptr_t>(sectAddress); 891 } 892 return object_error::success; 893 } 894 895 // Helper to advance a section or symbol iterator multiple increments at a time. 896 template<class T> 897 error_code advance(T &it, size_t Val) { 898 error_code ec; 899 while (Val--) { 900 it.increment(ec); 901 } 902 return ec; 903 } 904 905 template<class T> 906 void advanceTo(T &it, size_t Val) { 907 if (error_code ec = advance(it, Val)) 908 report_fatal_error(ec.message()); 909 } 910 911 void MachOObjectFile::printRelocationTargetName( 912 InMemoryStruct<macho::RelocationEntry>& RE, 913 raw_string_ostream &fmt) const { 914 unsigned Arch = getArch(); 915 bool isScattered = (Arch != Triple::x86_64) && 916 (RE->Word0 & macho::RF_Scattered); 917 918 // Target of a scattered relocation is an address. In the interest of 919 // generating pretty output, scan through the symbol table looking for a 920 // symbol that aligns with that address. If we find one, print it. 921 // Otherwise, we just print the hex address of the target. 922 if (isScattered) { 923 uint32_t Val = RE->Word1; 924 925 error_code ec; 926 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; 927 SI.increment(ec)) { 928 if (ec) report_fatal_error(ec.message()); 929 930 uint64_t Addr; 931 StringRef Name; 932 933 if ((ec = SI->getAddress(Addr))) 934 report_fatal_error(ec.message()); 935 if (Addr != Val) continue; 936 if ((ec = SI->getName(Name))) 937 report_fatal_error(ec.message()); 938 fmt << Name; 939 return; 940 } 941 942 // If we couldn't find a symbol that this relocation refers to, try 943 // to find a section beginning instead. 944 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; 945 SI.increment(ec)) { 946 if (ec) report_fatal_error(ec.message()); 947 948 uint64_t Addr; 949 StringRef Name; 950 951 if ((ec = SI->getAddress(Addr))) 952 report_fatal_error(ec.message()); 953 if (Addr != Val) continue; 954 if ((ec = SI->getName(Name))) 955 report_fatal_error(ec.message()); 956 fmt << Name; 957 return; 958 } 959 960 fmt << format("0x%x", Val); 961 return; 962 } 963 964 StringRef S; 965 bool isExtern = (RE->Word1 >> 27) & 1; 966 uint32_t Val = RE->Word1 & 0xFFFFFF; 967 968 if (isExtern) { 969 symbol_iterator SI = begin_symbols(); 970 advanceTo(SI, Val); 971 SI->getName(S); 972 } else { 973 section_iterator SI = begin_sections(); 974 advanceTo(SI, Val); 975 SI->getName(S); 976 } 977 978 fmt << S; 979 } 980 981 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 982 SmallVectorImpl<char> &Result) const { 983 InMemoryStruct<macho::RelocationEntry> RE; 984 getRelocation(Rel, RE); 985 986 unsigned Arch = getArch(); 987 bool isScattered = (Arch != Triple::x86_64) && 988 (RE->Word0 & macho::RF_Scattered); 989 990 std::string fmtbuf; 991 raw_string_ostream fmt(fmtbuf); 992 993 unsigned Type; 994 if (isScattered) 995 Type = (RE->Word0 >> 24) & 0xF; 996 else 997 Type = (RE->Word1 >> 28) & 0xF; 998 999 bool isPCRel; 1000 if (isScattered) 1001 isPCRel = ((RE->Word0 >> 30) & 1); 1002 else 1003 isPCRel = ((RE->Word1 >> 24) & 1); 1004 1005 // Determine any addends that should be displayed with the relocation. 1006 // These require decoding the relocation type, which is triple-specific. 1007 1008 // X86_64 has entirely custom relocation types. 1009 if (Arch == Triple::x86_64) { 1010 bool isPCRel = ((RE->Word1 >> 24) & 1); 1011 1012 switch (Type) { 1013 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD 1014 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT 1015 printRelocationTargetName(RE, fmt); 1016 fmt << "@GOT"; 1017 if (isPCRel) fmt << "PCREL"; 1018 break; 1019 } 1020 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR 1021 InMemoryStruct<macho::RelocationEntry> RENext; 1022 DataRefImpl RelNext = Rel; 1023 RelNext.d.a++; 1024 getRelocation(RelNext, RENext); 1025 1026 // X86_64_SUBTRACTOR must be followed by a relocation of type 1027 // X86_64_RELOC_UNSIGNED. 1028 // NOTE: Scattered relocations don't exist on x86_64. 1029 unsigned RType = (RENext->Word1 >> 28) & 0xF; 1030 if (RType != 0) 1031 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 1032 "X86_64_RELOC_SUBTRACTOR."); 1033 1034 // The X86_64_RELOC_UNSIGNED contains the minuend symbol, 1035 // X86_64_SUBTRACTOR contains to the subtrahend. 1036 printRelocationTargetName(RENext, fmt); 1037 fmt << "-"; 1038 printRelocationTargetName(RE, fmt); 1039 } 1040 case macho::RIT_X86_64_TLV: 1041 printRelocationTargetName(RE, fmt); 1042 fmt << "@TLV"; 1043 if (isPCRel) fmt << "P"; 1044 break; 1045 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 1046 printRelocationTargetName(RE, fmt); 1047 fmt << "-1"; 1048 break; 1049 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 1050 printRelocationTargetName(RE, fmt); 1051 fmt << "-2"; 1052 break; 1053 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 1054 printRelocationTargetName(RE, fmt); 1055 fmt << "-4"; 1056 break; 1057 default: 1058 printRelocationTargetName(RE, fmt); 1059 break; 1060 } 1061 // X86 and ARM share some relocation types in common. 1062 } else if (Arch == Triple::x86 || Arch == Triple::arm) { 1063 // Generic relocation types... 1064 switch (Type) { 1065 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info 1066 return object_error::success; 1067 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF 1068 InMemoryStruct<macho::RelocationEntry> RENext; 1069 DataRefImpl RelNext = Rel; 1070 RelNext.d.a++; 1071 getRelocation(RelNext, RENext); 1072 1073 // X86 sect diff's must be followed by a relocation of type 1074 // GENERIC_RELOC_PAIR. 1075 bool isNextScattered = (Arch != Triple::x86_64) && 1076 (RENext->Word0 & macho::RF_Scattered); 1077 unsigned RType; 1078 if (isNextScattered) 1079 RType = (RENext->Word0 >> 24) & 0xF; 1080 else 1081 RType = (RENext->Word1 >> 28) & 0xF; 1082 if (RType != 1) 1083 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1084 "GENERIC_RELOC_SECTDIFF."); 1085 1086 printRelocationTargetName(RE, fmt); 1087 fmt << "-"; 1088 printRelocationTargetName(RENext, fmt); 1089 break; 1090 } 1091 } 1092 1093 if (Arch == Triple::x86) { 1094 // All X86 relocations that need special printing were already 1095 // handled in the generic code. 1096 switch (Type) { 1097 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF 1098 InMemoryStruct<macho::RelocationEntry> RENext; 1099 DataRefImpl RelNext = Rel; 1100 RelNext.d.a++; 1101 getRelocation(RelNext, RENext); 1102 1103 // X86 sect diff's must be followed by a relocation of type 1104 // GENERIC_RELOC_PAIR. 1105 bool isNextScattered = (Arch != Triple::x86_64) && 1106 (RENext->Word0 & macho::RF_Scattered); 1107 unsigned RType; 1108 if (isNextScattered) 1109 RType = (RENext->Word0 >> 24) & 0xF; 1110 else 1111 RType = (RENext->Word1 >> 28) & 0xF; 1112 if (RType != 1) 1113 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1114 "GENERIC_RELOC_LOCAL_SECTDIFF."); 1115 1116 printRelocationTargetName(RE, fmt); 1117 fmt << "-"; 1118 printRelocationTargetName(RENext, fmt); 1119 break; 1120 } 1121 case macho::RIT_Generic_TLV: { 1122 printRelocationTargetName(RE, fmt); 1123 fmt << "@TLV"; 1124 if (isPCRel) fmt << "P"; 1125 break; 1126 } 1127 default: 1128 printRelocationTargetName(RE, fmt); 1129 } 1130 } else { // ARM-specific relocations 1131 switch (Type) { 1132 case macho::RIT_ARM_Half: // ARM_RELOC_HALF 1133 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF 1134 // Half relocations steal a bit from the length field to encode 1135 // whether this is an upper16 or a lower16 relocation. 1136 bool isUpper; 1137 if (isScattered) 1138 isUpper = (RE->Word0 >> 28) & 1; 1139 else 1140 isUpper = (RE->Word1 >> 25) & 1; 1141 1142 if (isUpper) 1143 fmt << ":upper16:("; 1144 else 1145 fmt << ":lower16:("; 1146 printRelocationTargetName(RE, fmt); 1147 1148 InMemoryStruct<macho::RelocationEntry> RENext; 1149 DataRefImpl RelNext = Rel; 1150 RelNext.d.a++; 1151 getRelocation(RelNext, RENext); 1152 1153 // ARM half relocs must be followed by a relocation of type 1154 // ARM_RELOC_PAIR. 1155 bool isNextScattered = (Arch != Triple::x86_64) && 1156 (RENext->Word0 & macho::RF_Scattered); 1157 unsigned RType; 1158 if (isNextScattered) 1159 RType = (RENext->Word0 >> 24) & 0xF; 1160 else 1161 RType = (RENext->Word1 >> 28) & 0xF; 1162 1163 if (RType != 1) 1164 report_fatal_error("Expected ARM_RELOC_PAIR after " 1165 "GENERIC_RELOC_HALF"); 1166 1167 // NOTE: The half of the target virtual address is stashed in the 1168 // address field of the secondary relocation, but we can't reverse 1169 // engineer the constant offset from it without decoding the movw/movt 1170 // instruction to find the other half in its immediate field. 1171 1172 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1173 // symbol/section pointer of the follow-on relocation. 1174 if (Type == macho::RIT_ARM_HalfDifference) { 1175 fmt << "-"; 1176 printRelocationTargetName(RENext, fmt); 1177 } 1178 1179 fmt << ")"; 1180 break; 1181 } 1182 default: { 1183 printRelocationTargetName(RE, fmt); 1184 } 1185 } 1186 } 1187 } else 1188 printRelocationTargetName(RE, fmt); 1189 1190 fmt.flush(); 1191 Result.append(fmtbuf.begin(), fmtbuf.end()); 1192 return object_error::success; 1193 } 1194 1195 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 1196 bool &Result) const { 1197 InMemoryStruct<macho::RelocationEntry> RE; 1198 getRelocation(Rel, RE); 1199 1200 unsigned Arch = getArch(); 1201 bool isScattered = (Arch != Triple::x86_64) && 1202 (RE->Word0 & macho::RF_Scattered); 1203 unsigned Type; 1204 if (isScattered) 1205 Type = (RE->Word0 >> 24) & 0xF; 1206 else 1207 Type = (RE->Word1 >> 28) & 0xF; 1208 1209 Result = false; 1210 1211 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1212 // is always hidden. 1213 if (Arch == Triple::x86 || Arch == Triple::arm) { 1214 if (Type == macho::RIT_Pair) Result = true; 1215 } else if (Arch == Triple::x86_64) { 1216 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1217 // an X864_64_RELOC_SUBTRACTOR. 1218 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { 1219 DataRefImpl RelPrev = Rel; 1220 RelPrev.d.a--; 1221 InMemoryStruct<macho::RelocationEntry> REPrev; 1222 getRelocation(RelPrev, REPrev); 1223 1224 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; 1225 1226 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; 1227 } 1228 } 1229 1230 return object_error::success; 1231 } 1232 1233 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1234 LibraryRef &Res) const { 1235 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1236 } 1237 1238 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1239 StringRef &Res) const { 1240 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1241 } 1242 1243 1244 /*===-- Miscellaneous -----------------------------------------------------===*/ 1245 1246 uint8_t MachOObjectFile::getBytesInAddress() const { 1247 return MachOObj->is64Bit() ? 8 : 4; 1248 } 1249 1250 StringRef MachOObjectFile::getFileFormatName() const { 1251 if (!MachOObj->is64Bit()) { 1252 switch (MachOObj->getHeader().CPUType) { 1253 case llvm::MachO::CPUTypeI386: 1254 return "Mach-O 32-bit i386"; 1255 case llvm::MachO::CPUTypeARM: 1256 return "Mach-O arm"; 1257 case llvm::MachO::CPUTypePowerPC: 1258 return "Mach-O 32-bit ppc"; 1259 default: 1260 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && 1261 "64-bit object file when we're not 64-bit?"); 1262 return "Mach-O 32-bit unknown"; 1263 } 1264 } 1265 1266 switch (MachOObj->getHeader().CPUType) { 1267 case llvm::MachO::CPUTypeX86_64: 1268 return "Mach-O 64-bit x86-64"; 1269 case llvm::MachO::CPUTypePowerPC64: 1270 return "Mach-O 64-bit ppc64"; 1271 default: 1272 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && 1273 "32-bit object file when we're 64-bit?"); 1274 return "Mach-O 64-bit unknown"; 1275 } 1276 } 1277 1278 unsigned MachOObjectFile::getArch() const { 1279 switch (MachOObj->getHeader().CPUType) { 1280 case llvm::MachO::CPUTypeI386: 1281 return Triple::x86; 1282 case llvm::MachO::CPUTypeX86_64: 1283 return Triple::x86_64; 1284 case llvm::MachO::CPUTypeARM: 1285 return Triple::arm; 1286 case llvm::MachO::CPUTypePowerPC: 1287 return Triple::ppc; 1288 case llvm::MachO::CPUTypePowerPC64: 1289 return Triple::ppc64; 1290 default: 1291 return Triple::UnknownArch; 1292 } 1293 } 1294 1295 } // end namespace object 1296 } // end namespace llvm 1297