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