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