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