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