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