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