diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-04-14 13:54:10 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-04-14 13:54:10 +0000 | 
| commit | 63faed5b8e4f2755f127fcb8aa440480c0649327 (patch) | |
| tree | 19c69a04768629f2d440944b71cbe90adae0b615 /lib/Object/MachOObjectFile.cpp | |
| parent | d4c8b5d2e851b0e8a063c6bf8543a4823a26c15a (diff) | |
Notes
Diffstat (limited to 'lib/Object/MachOObjectFile.cpp')
| -rw-r--r-- | lib/Object/MachOObjectFile.cpp | 694 | 
1 files changed, 658 insertions, 36 deletions
| diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 507df5865eb1..3bcda1700b8c 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -15,6 +15,7 @@  #include "llvm/ADT/Triple.h"  #include "llvm/Object/MachO.h"  #include "llvm/Object/MachOFormat.h" +#include "llvm/Support/Format.h"  #include "llvm/Support/MemoryBuffer.h"  #include <cctype> @@ -29,11 +30,10 @@ namespace object {  MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,                                   error_code &ec) -    : ObjectFile(Binary::isMachO, Object, ec), +    : ObjectFile(Binary::ID_MachO, Object, ec),        MachOObj(MOO),        RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {    DataRefImpl DRI; -  DRI.d.a = DRI.d.b = 0;    moveToNextSection(DRI);    uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;    while (DRI.d.a < LoadCommandCount) { @@ -124,23 +124,27 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,    return object_error::success;  } -error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI, -                                             uint64_t &Result) const { -  uint64_t SectionOffset; -  uint8_t SectionIndex; +error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, +                                                uint64_t &Result) const {    if (MachOObj->is64Bit()) {      InMemoryStruct<macho::Symbol64TableEntry> Entry;      getSymbol64TableEntry(DRI, Entry);      Result = Entry->Value; -    SectionIndex = Entry->SectionIndex; +    if (Entry->SectionIndex) { +      InMemoryStruct<macho::Section64> Section; +      getSection64(Sections[Entry->SectionIndex-1], Section); +      Result += Section->Offset - Section->Address; +    }    } else {      InMemoryStruct<macho::SymbolTableEntry> Entry;      getSymbolTableEntry(DRI, Entry);      Result = Entry->Value; -    SectionIndex = Entry->SectionIndex; +    if (Entry->SectionIndex) { +      InMemoryStruct<macho::Section> Section; +      getSection(Sections[Entry->SectionIndex-1], Section); +      Result += Section->Offset - Section->Address; +    }    } -  getSectionAddress(Sections[SectionIndex-1], SectionOffset); -  Result -= SectionOffset;    return object_error::success;  } @@ -161,7 +165,74 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,  error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,                                            uint64_t &Result) const { -  Result = UnknownAddressOrSize; +  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; +  uint64_t BeginOffset; +  uint64_t EndOffset = 0; +  uint8_t SectionIndex; +  if (MachOObj->is64Bit()) { +    InMemoryStruct<macho::Symbol64TableEntry> Entry; +    getSymbol64TableEntry(DRI, Entry); +    BeginOffset = Entry->Value; +    SectionIndex = Entry->SectionIndex; +    if (!SectionIndex) { +      uint32_t flags = SymbolRef::SF_None; +      getSymbolFlags(DRI, flags); +      if (flags & SymbolRef::SF_Common) +        Result = Entry->Value; +      else +        Result = UnknownAddressOrSize; +      return object_error::success; +    } +    // Unfortunately symbols are unsorted so we need to touch all +    // symbols from load command +    DRI.d.b = 0; +    uint32_t Command = DRI.d.a; +    while (Command == DRI.d.a) { +      moveToNextSymbol(DRI); +      if (DRI.d.a < LoadCommandCount) { +        getSymbol64TableEntry(DRI, Entry); +        if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) +          if (!EndOffset || Entry->Value < EndOffset) +            EndOffset = Entry->Value; +      } +      DRI.d.b++; +    } +  } else { +    InMemoryStruct<macho::SymbolTableEntry> Entry; +    getSymbolTableEntry(DRI, Entry); +    BeginOffset = Entry->Value; +    SectionIndex = Entry->SectionIndex; +    if (!SectionIndex) { +      uint32_t flags = SymbolRef::SF_None; +      getSymbolFlags(DRI, flags); +      if (flags & SymbolRef::SF_Common) +        Result = Entry->Value; +      else +        Result = UnknownAddressOrSize; +      return object_error::success; +    } +    // Unfortunately symbols are unsorted so we need to touch all +    // symbols from load command +    DRI.d.b = 0; +    uint32_t Command = DRI.d.a; +    while (Command == DRI.d.a) { +      moveToNextSymbol(DRI); +      if (DRI.d.a < LoadCommandCount) { +        getSymbolTableEntry(DRI, Entry); +        if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) +          if (!EndOffset || Entry->Value < EndOffset) +            EndOffset = Entry->Value; +      } +      DRI.d.b++; +    } +  } +  if (!EndOffset) { +    uint64_t Size; +    getSectionSize(Sections[SectionIndex-1], Size); +    getSectionAddress(Sections[SectionIndex-1], EndOffset); +    EndOffset += Size; +  } +  Result = EndOffset - BeginOffset;    return object_error::success;  } @@ -200,36 +271,69 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,    return object_error::success;  } -error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI, -                                             bool &Result) const { +error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, +                                           uint32_t &Result) const { +  uint16_t MachOFlags; +  uint8_t MachOType;    if (MachOObj->is64Bit()) {      InMemoryStruct<macho::Symbol64TableEntry> Entry;      getSymbol64TableEntry(DRI, Entry); -    Result = Entry->Flags & macho::STF_StabsEntryMask; +    MachOFlags = Entry->Flags; +    MachOType = Entry->Type;    } else {      InMemoryStruct<macho::SymbolTableEntry> Entry;      getSymbolTableEntry(DRI, Entry); -    Result = Entry->Flags & macho::STF_StabsEntryMask; +    MachOFlags = Entry->Flags; +    MachOType = Entry->Type;    } + +  // TODO: Correctly set SF_ThreadLocal +  Result = SymbolRef::SF_None; + +  if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) +    Result |= SymbolRef::SF_Undefined; + +  if (MachOFlags & macho::STF_StabsEntryMask) +    Result |= SymbolRef::SF_FormatSpecific; + +  if (MachOType & MachO::NlistMaskExternal) { +    Result |= SymbolRef::SF_Global; +    if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) +      Result |= SymbolRef::SF_Common; +  } + +  if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) +    Result |= SymbolRef::SF_Weak; + +  if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) +    Result |= SymbolRef::SF_Absolute; +    return object_error::success;  } -error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const { - +error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, +                                             section_iterator &Res) const { +  uint8_t index;    if (MachOObj->is64Bit()) {      InMemoryStruct<macho::Symbol64TableEntry> Entry;      getSymbol64TableEntry(Symb, Entry); -    Res = Entry->Type & MachO::NlistMaskExternal; +    index = Entry->SectionIndex;    } else {      InMemoryStruct<macho::SymbolTableEntry> Entry;      getSymbolTableEntry(Symb, Entry); -    Res = Entry->Type & MachO::NlistMaskExternal; +    index = Entry->SectionIndex;    } + +  if (index == 0) +    Res = end_sections(); +  else +    Res = section_iterator(SectionRef(Sections[index-1], this)); +    return object_error::success;  }  error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, -                                          SymbolRef::SymbolType &Res) const { +                                          SymbolRef::Type &Res) const {    uint8_t n_type;    if (MachOObj->is64Bit()) {      InMemoryStruct<macho::Symbol64TableEntry> Entry; @@ -243,12 +347,14 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,    Res = SymbolRef::ST_Other;    // If this is a STAB debugging symbol, we can do nothing more. -  if (n_type & MachO::NlistMaskStab) +  if (n_type & MachO::NlistMaskStab) { +    Res = SymbolRef::ST_Debug;      return object_error::success; +  }    switch (n_type & MachO::NlistMaskType) {      case MachO::NListTypeUndefined : -      Res = SymbolRef::ST_External; +      Res = SymbolRef::ST_Unknown;        break;      case MachO::NListTypeSection :        Res = SymbolRef::ST_Function; @@ -261,7 +367,6 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,  symbol_iterator MachOObjectFile::begin_symbols() const {    // DRI.d.a = segment number; DRI.d.b = symbol index.    DataRefImpl DRI; -  DRI.d.a = DRI.d.b = 0;    moveToNextSymbol(DRI);    return symbol_iterator(SymbolRef(DRI, this));  } @@ -269,10 +374,33 @@ symbol_iterator MachOObjectFile::begin_symbols() const {  symbol_iterator MachOObjectFile::end_symbols() const {    DataRefImpl DRI;    DRI.d.a = MachOObj->getHeader().NumLoadCommands; -  DRI.d.b = 0;    return symbol_iterator(SymbolRef(DRI, this));  } +symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { +  // TODO: implement +  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); +} + +symbol_iterator MachOObjectFile::end_dynamic_symbols() const { +  // TODO: implement +  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); +} + +library_iterator MachOObjectFile::begin_libraries_needed() const { +  // TODO: implement +  report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +library_iterator MachOObjectFile::end_libraries_needed() const { +  // TODO: implement +  report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +StringRef MachOObjectFile::getLoadName() const { +  // TODO: Implement +  report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); +}  /*===-- Sections ----------------------------------------------------------===*/ @@ -451,12 +579,43 @@ error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,    return object_error::success;  } +error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, +                                                          bool &Result) const { +  // FIXME: Unimplemented +  Result = true; +  return object_error::success; +} + +error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, +                                            bool &Result) const { +  // FIXME: Unimplemented +  Result = false; +  return object_error::success; +} + +error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, +                                              bool &Result) const { +  if (MachOObj->is64Bit()) { +    InMemoryStruct<macho::Section64> Sect; +    getSection64(DRI, Sect); +    Result = (Sect->Flags & MachO::SectionTypeZeroFill || +              Sect->Flags & MachO::SectionTypeZeroFillLarge); +  } else { +    InMemoryStruct<macho::Section> Sect; +    getSection(DRI, Sect); +    Result = (Sect->Flags & MachO::SectionTypeZeroFill || +              Sect->Flags & MachO::SectionTypeZeroFillLarge); +  } + +  return object_error::success; +} +  error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,                                                    DataRefImpl Symb,                                                    bool &Result) const { -  SymbolRef::SymbolType ST; +  SymbolRef::Type ST;    getSymbolType(Symb, ST); -  if (ST == SymbolRef::ST_External) { +  if (ST == SymbolRef::ST_Unknown) {      Result = false;      return object_error::success;    } @@ -483,7 +642,6 @@ error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,  relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {    DataRefImpl ret; -  ret.d.a = 0;    ret.d.b = getSectionIndex(Sec);    return relocation_iterator(RelocationRef(ret, this));  } @@ -506,7 +664,6 @@ relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {  section_iterator MachOObjectFile::begin_sections() const {    DataRefImpl DRI; -  DRI.d.a = DRI.d.b = 0;    moveToNextSection(DRI);    return section_iterator(SectionRef(DRI, this));  } @@ -514,7 +671,6 @@ section_iterator MachOObjectFile::begin_sections() const {  section_iterator MachOObjectFile::end_sections() const {    DataRefImpl DRI;    DRI.d.a = MachOObj->getHeader().NumLoadCommands; -  DRI.d.b = 0;    return section_iterator(SectionRef(DRI, this));  } @@ -543,19 +699,43 @@ error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,  }  error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,                                                   uint64_t &Res) const { -  const uint8_t* sectAddress = base(); +  const uint8_t* sectAddress = 0;    if (MachOObj->is64Bit()) {      InMemoryStruct<macho::Section64> Sect;      getSection64(Sections[Rel.d.b], Sect); -    sectAddress += Sect->Offset; +    sectAddress += Sect->Address;    } else {      InMemoryStruct<macho::Section> Sect;      getSection(Sections[Rel.d.b], Sect); -    sectAddress += Sect->Offset; +    sectAddress += Sect->Address;    }    InMemoryStruct<macho::RelocationEntry> RE;    getRelocation(Rel, RE); -  Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0); + +  unsigned Arch = getArch(); +  bool isScattered = (Arch != Triple::x86_64) && +                     (RE->Word0 & macho::RF_Scattered); +  uint64_t RelAddr = 0; +  if (isScattered) +    RelAddr = RE->Word0 & 0xFFFFFF; +  else +    RelAddr = RE->Word0; + +  Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr); +  return object_error::success; +} +error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, +                                                uint64_t &Res) const { +  InMemoryStruct<macho::RelocationEntry> RE; +  getRelocation(Rel, RE); + +  unsigned Arch = getArch(); +  bool isScattered = (Arch != Triple::x86_64) && +                     (RE->Word0 & macho::RF_Scattered); +  if (isScattered) +    Res = RE->Word0 & 0xFFFFFF; +  else +    Res = RE->Word0;    return object_error::success;  }  error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, @@ -566,7 +746,6 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,    bool isExtern = (RE->Word1 >> 27) & 1;    DataRefImpl Sym; -  Sym.d.a = Sym.d.b = 0;    moveToNextSymbol(Sym);    if (isExtern) {      for (unsigned i = 0; i < SymbolIdx; i++) { @@ -580,14 +759,112 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,    return object_error::success;  }  error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, -                                              uint32_t &Res) const { +                                              uint64_t &Res) const {    InMemoryStruct<macho::RelocationEntry> RE;    getRelocation(Rel, RE); -  Res = RE->Word1; +  Res = RE->Word0; +  Res <<= 32; +  Res |= RE->Word1;    return object_error::success;  }  error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,                                            SmallVectorImpl<char> &Result) const { +  // TODO: Support scattered relocations. +  StringRef res; +  InMemoryStruct<macho::RelocationEntry> RE; +  getRelocation(Rel, RE); + +  unsigned Arch = getArch(); +  bool isScattered = (Arch != Triple::x86_64) && +                     (RE->Word0 & macho::RF_Scattered); + +  unsigned r_type; +  if (isScattered) +    r_type = (RE->Word0 >> 24) & 0xF; +  else +    r_type = (RE->Word1 >> 28) & 0xF; + +  switch (Arch) { +    case Triple::x86: { +      const char* Table[] =  { +        "GENERIC_RELOC_VANILLA", +        "GENERIC_RELOC_PAIR", +        "GENERIC_RELOC_SECTDIFF", +        "GENERIC_RELOC_PB_LA_PTR", +        "GENERIC_RELOC_LOCAL_SECTDIFF", +        "GENERIC_RELOC_TLV" }; + +      if (r_type > 6) +        res = "Unknown"; +      else +        res = Table[r_type]; +      break; +    } +    case Triple::x86_64: { +      const char* Table[] =  { +        "X86_64_RELOC_UNSIGNED", +        "X86_64_RELOC_SIGNED", +        "X86_64_RELOC_BRANCH", +        "X86_64_RELOC_GOT_LOAD", +        "X86_64_RELOC_GOT", +        "X86_64_RELOC_SUBTRACTOR", +        "X86_64_RELOC_SIGNED_1", +        "X86_64_RELOC_SIGNED_2", +        "X86_64_RELOC_SIGNED_4", +        "X86_64_RELOC_TLV" }; + +      if (r_type > 9) +        res = "Unknown"; +      else +        res = Table[r_type]; +      break; +    } +    case Triple::arm: { +      const char* Table[] =  { +        "ARM_RELOC_VANILLA", +        "ARM_RELOC_PAIR", +        "ARM_RELOC_SECTDIFF", +        "ARM_RELOC_LOCAL_SECTDIFF", +        "ARM_RELOC_PB_LA_PTR", +        "ARM_RELOC_BR24", +        "ARM_THUMB_RELOC_BR22", +        "ARM_THUMB_32BIT_BRANCH", +        "ARM_RELOC_HALF", +        "ARM_RELOC_HALF_SECTDIFF" }; + +      if (r_type > 9) +        res = "Unknown"; +      else +        res = Table[r_type]; +      break; +    } +    case Triple::ppc: { +      const char* Table[] =  { +        "PPC_RELOC_VANILLA", +        "PPC_RELOC_PAIR", +        "PPC_RELOC_BR14", +        "PPC_RELOC_BR24", +        "PPC_RELOC_HI16", +        "PPC_RELOC_LO16", +        "PPC_RELOC_HA16", +        "PPC_RELOC_LO14", +        "PPC_RELOC_SECTDIFF", +        "PPC_RELOC_PB_LA_PTR", +        "PPC_RELOC_HI16_SECTDIFF", +        "PPC_RELOC_LO16_SECTDIFF", +        "PPC_RELOC_HA16_SECTDIFF", +        "PPC_RELOC_JBSR", +        "PPC_RELOC_LO14_SECTDIFF", +        "PPC_RELOC_LOCAL_SECTDIFF" }; + +      res = Table[r_type]; +      break; +    } +    case Triple::UnknownArch: +      res = "Unknown"; +      break; +  } +  Result.append(res.begin(), res.end());    return object_error::success;  }  error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, @@ -611,11 +888,356 @@ error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,    }    return object_error::success;  } + +// Helper to advance a section or symbol iterator multiple increments at a time. +template<class T> +error_code advance(T &it, size_t Val) { +  error_code ec; +  while (Val--) { +    it.increment(ec); +  } +  return ec; +} + +template<class T> +void advanceTo(T &it, size_t Val) { +  if (error_code ec = advance(it, Val)) +    report_fatal_error(ec.message()); +} + +void MachOObjectFile::printRelocationTargetName( +                                     InMemoryStruct<macho::RelocationEntry>& RE, +                                     raw_string_ostream &fmt) const { +  unsigned Arch = getArch(); +  bool isScattered = (Arch != Triple::x86_64) && +                     (RE->Word0 & macho::RF_Scattered); + +  // Target of a scattered relocation is an address.  In the interest of +  // generating pretty output, scan through the symbol table looking for a +  // symbol that aligns with that address.  If we find one, print it. +  // Otherwise, we just print the hex address of the target. +  if (isScattered) { +    uint32_t Val = RE->Word1; + +    error_code ec; +    for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; +        SI.increment(ec)) { +      if (ec) report_fatal_error(ec.message()); + +      uint64_t Addr; +      StringRef Name; + +      if ((ec = SI->getAddress(Addr))) +        report_fatal_error(ec.message()); +      if (Addr != Val) continue; +      if ((ec = SI->getName(Name))) +        report_fatal_error(ec.message()); +      fmt << Name; +      return; +    } + +    // If we couldn't find a symbol that this relocation refers to, try +    // to find a section beginning instead. +    for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; +         SI.increment(ec)) { +      if (ec) report_fatal_error(ec.message()); + +      uint64_t Addr; +      StringRef Name; + +      if ((ec = SI->getAddress(Addr))) +        report_fatal_error(ec.message()); +      if (Addr != Val) continue; +      if ((ec = SI->getName(Name))) +        report_fatal_error(ec.message()); +      fmt << Name; +      return; +    } + +    fmt << format("0x%x", Val); +    return; +  } + +  StringRef S; +  bool isExtern = (RE->Word1 >> 27) & 1; +  uint32_t Val = RE->Word1 & 0xFFFFFF; + +  if (isExtern) { +    symbol_iterator SI = begin_symbols(); +    advanceTo(SI, Val); +    SI->getName(S); +  } else { +    section_iterator SI = begin_sections(); +    advanceTo(SI, Val); +    SI->getName(S); +  } + +  fmt << S; +} +  error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,                                            SmallVectorImpl<char> &Result) const { +  InMemoryStruct<macho::RelocationEntry> RE; +  getRelocation(Rel, RE); + +  unsigned Arch = getArch(); +  bool isScattered = (Arch != Triple::x86_64) && +                     (RE->Word0 & macho::RF_Scattered); + +  std::string fmtbuf; +  raw_string_ostream fmt(fmtbuf); + +  unsigned Type; +  if (isScattered) +    Type = (RE->Word0 >> 24) & 0xF; +  else +    Type = (RE->Word1 >> 28) & 0xF; + +  bool isPCRel; +  if (isScattered) +    isPCRel = ((RE->Word0 >> 30) & 1); +  else +    isPCRel = ((RE->Word1 >> 24) & 1); + +  // Determine any addends that should be displayed with the relocation. +  // These require decoding the relocation type, which is triple-specific. + +  // X86_64 has entirely custom relocation types. +  if (Arch == Triple::x86_64) { +    bool isPCRel = ((RE->Word1 >> 24) & 1); + +    switch (Type) { +      case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD +      case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT +        printRelocationTargetName(RE, fmt); +        fmt << "@GOT"; +        if (isPCRel) fmt << "PCREL"; +        break; +      } +      case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR +        InMemoryStruct<macho::RelocationEntry> RENext; +        DataRefImpl RelNext = Rel; +        RelNext.d.a++; +        getRelocation(RelNext, RENext); + +        // X86_64_SUBTRACTOR must be followed by a relocation of type +        // X86_64_RELOC_UNSIGNED. +        // NOTE: Scattered relocations don't exist on x86_64. +        unsigned RType = (RENext->Word1 >> 28) & 0xF; +        if (RType != 0) +          report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " +                             "X86_64_RELOC_SUBTRACTOR."); + +        // The X86_64_RELOC_UNSIGNED contains the minuend symbol, +        // X86_64_SUBTRACTOR contains to the subtrahend. +        printRelocationTargetName(RENext, fmt); +        fmt << "-"; +        printRelocationTargetName(RE, fmt); +      } +      case macho::RIT_X86_64_TLV: +        printRelocationTargetName(RE, fmt); +        fmt << "@TLV"; +        if (isPCRel) fmt << "P"; +        break; +      case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 +        printRelocationTargetName(RE, fmt); +        fmt << "-1"; +        break; +      case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 +        printRelocationTargetName(RE, fmt); +        fmt << "-2"; +        break; +      case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 +        printRelocationTargetName(RE, fmt); +        fmt << "-4"; +        break; +      default: +        printRelocationTargetName(RE, fmt); +        break; +    } +  // X86 and ARM share some relocation types in common. +  } else if (Arch == Triple::x86 || Arch == Triple::arm) { +    // Generic relocation types... +    switch (Type) { +      case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info +        return object_error::success; +      case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF +        InMemoryStruct<macho::RelocationEntry> RENext; +        DataRefImpl RelNext = Rel; +        RelNext.d.a++; +        getRelocation(RelNext, RENext); + +        // X86 sect diff's must be followed by a relocation of type +        // GENERIC_RELOC_PAIR. +        bool isNextScattered = (Arch != Triple::x86_64) && +                               (RENext->Word0 & macho::RF_Scattered); +        unsigned RType; +        if (isNextScattered) +          RType = (RENext->Word0 >> 24) & 0xF; +        else +          RType = (RENext->Word1 >> 28) & 0xF; +        if (RType != 1) +          report_fatal_error("Expected GENERIC_RELOC_PAIR after " +                             "GENERIC_RELOC_SECTDIFF."); + +        printRelocationTargetName(RE, fmt); +        fmt << "-"; +        printRelocationTargetName(RENext, fmt); +        break; +      } +    } + +    if (Arch == Triple::x86) { +      // All X86 relocations that need special printing were already +      // handled in the generic code. +      switch (Type) { +        case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF +          InMemoryStruct<macho::RelocationEntry> RENext; +          DataRefImpl RelNext = Rel; +          RelNext.d.a++; +          getRelocation(RelNext, RENext); + +          // X86 sect diff's must be followed by a relocation of type +          // GENERIC_RELOC_PAIR. +          bool isNextScattered = (Arch != Triple::x86_64) && +                               (RENext->Word0 & macho::RF_Scattered); +          unsigned RType; +          if (isNextScattered) +            RType = (RENext->Word0 >> 24) & 0xF; +          else +            RType = (RENext->Word1 >> 28) & 0xF; +          if (RType != 1) +            report_fatal_error("Expected GENERIC_RELOC_PAIR after " +                               "GENERIC_RELOC_LOCAL_SECTDIFF."); + +          printRelocationTargetName(RE, fmt); +          fmt << "-"; +          printRelocationTargetName(RENext, fmt); +          break; +        } +        case macho::RIT_Generic_TLV: { +          printRelocationTargetName(RE, fmt); +          fmt << "@TLV"; +          if (isPCRel) fmt << "P"; +          break; +        } +        default: +          printRelocationTargetName(RE, fmt); +      } +    } else { // ARM-specific relocations +      switch (Type) { +        case macho::RIT_ARM_Half:             // ARM_RELOC_HALF +        case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF +          // Half relocations steal a bit from the length field to encode +          // whether this is an upper16 or a lower16 relocation. +          bool isUpper; +          if (isScattered) +            isUpper = (RE->Word0 >> 28) & 1; +          else +            isUpper = (RE->Word1 >> 25) & 1; + +          if (isUpper) +            fmt << ":upper16:("; +          else +            fmt << ":lower16:("; +          printRelocationTargetName(RE, fmt); + +          InMemoryStruct<macho::RelocationEntry> RENext; +          DataRefImpl RelNext = Rel; +          RelNext.d.a++; +          getRelocation(RelNext, RENext); + +          // ARM half relocs must be followed by a relocation of type +          // ARM_RELOC_PAIR. +          bool isNextScattered = (Arch != Triple::x86_64) && +                                 (RENext->Word0 & macho::RF_Scattered); +          unsigned RType; +          if (isNextScattered) +            RType = (RENext->Word0 >> 24) & 0xF; +          else +            RType = (RENext->Word1 >> 28) & 0xF; + +          if (RType != 1) +            report_fatal_error("Expected ARM_RELOC_PAIR after " +                               "GENERIC_RELOC_HALF"); + +          // NOTE: The half of the target virtual address is stashed in the +          // address field of the secondary relocation, but we can't reverse +          // engineer the constant offset from it without decoding the movw/movt +          // instruction to find the other half in its immediate field. + +          // ARM_RELOC_HALF_SECTDIFF encodes the second section in the +          // symbol/section pointer of the follow-on relocation. +          if (Type == macho::RIT_ARM_HalfDifference) { +            fmt << "-"; +            printRelocationTargetName(RENext, fmt); +          } + +          fmt << ")"; +          break; +        } +        default: { +          printRelocationTargetName(RE, fmt); +        } +      } +    } +  } else +    printRelocationTargetName(RE, fmt); + +  fmt.flush(); +  Result.append(fmtbuf.begin(), fmtbuf.end()); +  return object_error::success; +} + +error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, +                                                bool &Result) const { +  InMemoryStruct<macho::RelocationEntry> RE; +  getRelocation(Rel, RE); + +  unsigned Arch = getArch(); +  bool isScattered = (Arch != Triple::x86_64) && +                     (RE->Word0 & macho::RF_Scattered); +  unsigned Type; +  if (isScattered) +    Type = (RE->Word0 >> 24) & 0xF; +  else +    Type = (RE->Word1 >> 28) & 0xF; + +  Result = false; + +  // On arches that use the generic relocations, GENERIC_RELOC_PAIR +  // is always hidden. +  if (Arch == Triple::x86 || Arch == Triple::arm) { +    if (Type == macho::RIT_Pair) Result = true; +  } else if (Arch == Triple::x86_64) { +    // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows +    // an X864_64_RELOC_SUBTRACTOR. +    if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { +      DataRefImpl RelPrev = Rel; +      RelPrev.d.a--; +      InMemoryStruct<macho::RelocationEntry> REPrev; +      getRelocation(RelPrev, REPrev); + +      unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; + +      if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; +    } +  } +    return object_error::success;  } +error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, +                                           LibraryRef &Res) const { +  report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, +                                           StringRef &Res) const { +  report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +  /*===-- Miscellaneous -----------------------------------------------------===*/  uint8_t MachOObjectFile::getBytesInAddress() const { | 
