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