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