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