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