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