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