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