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