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