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