diff options
| -rw-r--r-- | llvm/include/llvm/Object/MachO.h | 3 | ||||
| -rw-r--r-- | llvm/lib/Object/MachOObjectFile.cpp | 24 | ||||
| -rwxr-xr-x | llvm/test/tools/llvm-objdump/X86/Inputs/macho-preload-x86_64 | bin | 0 -> 1084 bytes | |||
| -rw-r--r-- | llvm/test/tools/llvm-objdump/X86/macho-preload-relocations.test | 5 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-objdump/X86/macho-relocations.test | 12 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-objdump/X86/malformed-machos.test | 2 | ||||
| -rw-r--r-- | llvm/tools/llvm-objdump/MachODump.cpp | 336 | 
7 files changed, 371 insertions, 11 deletions
diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h index 03fd52fb482..c3ec1f6fcfe 100644 --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -329,6 +329,9 @@ public:      return make_range(extrel_begin(), extrel_end());    } +  relocation_iterator locrel_begin() const; +  relocation_iterator locrel_end() const; +      void moveRelocationNext(DataRefImpl &Rel) const override;    uint64_t getRelocationOffset(DataRefImpl Rel) const override;    symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 4620fdde81d..aa4015c5f90 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -1960,6 +1960,7 @@ MachOObjectFile::section_rel_end(DataRefImpl Sec) const {  relocation_iterator MachOObjectFile::extrel_begin() const {    DataRefImpl Ret; +  // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations    Ret.d.a = 0; // Would normally be a section index.    Ret.d.b = 0; // Index into the external relocations    return relocation_iterator(RelocationRef(Ret, this)); @@ -1968,11 +1969,29 @@ relocation_iterator MachOObjectFile::extrel_begin() const {  relocation_iterator MachOObjectFile::extrel_end() const {    MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();    DataRefImpl Ret; +  // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations    Ret.d.a = 0; // Would normally be a section index.    Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations    return relocation_iterator(RelocationRef(Ret, this));  } +relocation_iterator MachOObjectFile::locrel_begin() const { +  DataRefImpl Ret; +  // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations +  Ret.d.a = 1; // Would normally be a section index. +  Ret.d.b = 0; // Index into the local relocations +  return relocation_iterator(RelocationRef(Ret, this)); +} + +relocation_iterator MachOObjectFile::locrel_end() const { +  MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand(); +  DataRefImpl Ret; +  // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations +  Ret.d.a = 1; // Would normally be a section index. +  Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations +  return relocation_iterator(RelocationRef(Ret, this)); +} +  void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {    ++Rel.d.b;  } @@ -4301,7 +4320,10 @@ MachOObjectFile::getRelocation(DataRefImpl Rel) const {      }    } else {      MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand(); -    Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations +    if (Rel.d.a == 0) +      Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations +    else +      Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations    }    auto P = reinterpret_cast<const MachO::any_relocation_info *>( diff --git a/llvm/test/tools/llvm-objdump/X86/Inputs/macho-preload-x86_64 b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-preload-x86_64 Binary files differnew file mode 100755 index 00000000000..236606e77c6 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-preload-x86_64 diff --git a/llvm/test/tools/llvm-objdump/X86/macho-preload-relocations.test b/llvm/test/tools/llvm-objdump/X86/macho-preload-relocations.test new file mode 100644 index 00000000000..dda0b2b465b --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/macho-preload-relocations.test @@ -0,0 +1,5 @@ +// RUN: llvm-objdump -macho -r %p/Inputs/macho-preload-x86_64 | FileCheck %s + +CHECK: Local relocation information 1 entries +CHECK: address  pcrel length extern type    scattered symbolnum/value +CHECK: 00000000 False quad   False  UNSIGND False     2 (__TEXT,__cstring) diff --git a/llvm/test/tools/llvm-objdump/X86/macho-relocations.test b/llvm/test/tools/llvm-objdump/X86/macho-relocations.test index 536aec8b1bc..111cf0cc95b 100644 --- a/llvm/test/tools/llvm-objdump/X86/macho-relocations.test +++ b/llvm/test/tools/llvm-objdump/X86/macho-relocations.test @@ -1,7 +1,9 @@  RUN: llvm-objdump -macho -r %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s -CHECK: RELOCATION RECORDS FOR [__text]: -CHECK: 0000000000000027 X86_64_RELOC_BRANCH _printf -CHECK: 000000000000000b X86_64_RELOC_SIGNED L_.str -CHECK: RELOCATION RECORDS FOR [__compact_unwind]: -CHECK: 0000000000000000 X86_64_RELOC_UNSIGNED __text +CHECK: Relocation information (__TEXT,__text) 2 entries +CHECK: address  pcrel length extern type    scattered symbolnum/value +CHECK: 00000027 True  long   True   BRANCH  False     _printf +CHECK: 0000000b True  long   True   SIGNED  False     L_.str +CHECK: Relocation information (__LD,__compact_unwind) 1 entries +CHECK: address  pcrel length extern type    scattered symbolnum/value +CHECK: 00000000 False quad   False  UNSIGND False     1 (__TEXT,__text) diff --git a/llvm/test/tools/llvm-objdump/X86/malformed-machos.test b/llvm/test/tools/llvm-objdump/X86/malformed-machos.test index e29df464a4e..414cf973b9d 100644 --- a/llvm/test/tools/llvm-objdump/X86/malformed-machos.test +++ b/llvm/test/tools/llvm-objdump/X86/malformed-machos.test @@ -68,4 +68,4 @@ RUN: not llvm-objdump -macho -objc-meta-data %p/Inputs/macho-invalid-bind-entry  INVALID-BIND-ENTRY: macho-invalid-bind-entry': truncated or malformed object (for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad library ordinal: 83 (max 0) for opcode at: 0x0)  RUN: llvm-objdump -macho -r %p/Inputs/macho-invalid-reloc-section-index | FileCheck -check-prefix INVALID-RELOC-SECTION-INDEX %s -INVALID-RELOC-SECTION-INDEX: 0000000000000021 X86_64_RELOC_UNSIGNED 8388613 (?,?) +INVALID-RELOC-SECTION-INDEX: 00000021 False byte   False  UNSIGND False     8388613 (?,?) diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index 4412d683341..80061f0544f 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -467,6 +467,333 @@ static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {    }  } +static void PrintRType(const uint64_t cputype, const unsigned r_type) { +  static char const *generic_r_types[] = { +    "VANILLA ", "PAIR    ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV     ", +    "  6 (?) ", "  7 (?) ", "  8 (?) ", "  9 (?) ", " 10 (?) ", " 11 (?) ", +    " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " +  }; +  static char const *x86_64_r_types[] = { +    "UNSIGND ", "SIGNED  ", "BRANCH  ", "GOT_LD  ", "GOT     ", "SUB     ", +    "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV     ", " 10 (?) ", " 11 (?) ", +    " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " +  }; +  static char const *arm_r_types[] = { +    "VANILLA ", "PAIR    ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", +    "BR24    ", "T_BR22  ", "T_BR32  ", "HALF    ", "HALFDIF ", +    " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " +  }; +  static char const *arm64_r_types[] = { +    "UNSIGND ", "SUB     ", "BR26    ", "PAGE21  ", "PAGOF12 ", +    "GOTLDP  ", "GOTLDPOF", "PTRTGOT ", "TLVLDP  ", "TLVLDPOF", +    "ADDEND  ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " +  }; +   +  if (r_type > 0xf){ +    outs() << format("%-7u", r_type) << " "; +    return; +  } +  switch (cputype) { +    case MachO::CPU_TYPE_I386: +      outs() << generic_r_types[r_type]; +      break; +    case MachO::CPU_TYPE_X86_64: +      outs() << x86_64_r_types[r_type]; +      break; +    case MachO::CPU_TYPE_ARM: +      outs() << arm_r_types[r_type]; +      break; +    case MachO::CPU_TYPE_ARM64: +      outs() << arm64_r_types[r_type]; +      break; +    default: +      outs() << format("%-7u ", r_type); +  } +} + +static void PrintRLength(const uint64_t cputype, const unsigned r_type, +                         const unsigned r_length, const bool previous_arm_half){ +  if (cputype == MachO::CPU_TYPE_ARM && +      (r_type == llvm::MachO::ARM_RELOC_HALF || +       r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF || +       previous_arm_half == true)) { +    if ((r_length & 0x1) == 0) +      outs() << "lo/"; +    else +      outs() << "hi/"; +    if ((r_length & 0x1) == 0) +      outs() << "arm "; +    else +      outs() << "thm "; +  } else { +    switch (r_length) { +      case 0: +        outs() << "byte   "; +        break; +      case 1: +        outs() << "word   "; +        break; +      case 2: +        outs() << "long   "; +        break; +      case 3: +        if (cputype == MachO::CPU_TYPE_X86_64) +          outs() << "quad   "; +        else +          outs() << format("?(%2d)  ", r_length); +        break; +      default: +        outs() << format("?(%2d)  ", r_length); +    } +  } +} + +static void PrintRelocationEntries(const MachOObjectFile *O, +                                   const relocation_iterator Begin, +                                   const relocation_iterator End, +                                   const uint64_t cputype, +                                   const bool verbose) { +  const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); +  bool previous_arm_half = false; +  bool previous_sectdiff = false; +  uint32_t sectdiff_r_type = 0; +   +  for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { +    const DataRefImpl Rel = Reloc->getRawDataRefImpl(); +    const MachO::any_relocation_info RE = O->getRelocation(Rel); +    const unsigned r_type = O->getAnyRelocationType(RE); +    const bool r_scattered = O->isRelocationScattered(RE); +    const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); +    const unsigned r_length = O->getAnyRelocationLength(RE); +    const unsigned r_address = O->getAnyRelocationAddress(RE); +    const bool r_extern = (r_scattered ? false : +                           O->getPlainRelocationExternal(RE)); +    const uint32_t r_value = (r_scattered ? +                              O->getScatteredRelocationValue(RE) : 0); +    const unsigned r_symbolnum = (r_scattered ? 0 : +                                  O->getPlainRelocationSymbolNum(RE)); +     +    if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { +      if (verbose) { +        // scattered: address +        if ((cputype == MachO::CPU_TYPE_I386 && +             r_type == llvm::MachO::GENERIC_RELOC_PAIR) || +            (cputype == MachO::CPU_TYPE_ARM && +             r_type == llvm::MachO::ARM_RELOC_PAIR)) +          outs() << "         "; +        else +          outs() << format("%08x ", (unsigned int)r_address); +         +        // scattered: pcrel +        if (r_pcrel) +          outs() << "True  "; +        else +          outs() << "False "; +         +        // scattered: length +        PrintRLength(cputype, r_type, r_length, previous_arm_half); +         +        // scattered: extern & type +        outs() << "n/a    "; +        PrintRType(cputype, r_type); +         +        // scattered: scattered & value +        outs() << format("True      0x%08x", (unsigned int)r_value); +        if (previous_sectdiff == false) { +          if ((cputype == MachO::CPU_TYPE_ARM && +               r_type == llvm::MachO::ARM_RELOC_PAIR)) +            outs() << format(" half = 0x%04x ", (unsigned int)r_address); +        } +        else if (cputype == MachO::CPU_TYPE_ARM && +                 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF) +          outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); +        if ((cputype == MachO::CPU_TYPE_I386 && +             (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF || +              r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || +            (cputype == MachO::CPU_TYPE_ARM && +             (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF || +              sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF || +              sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) { +               previous_sectdiff = true; +               sectdiff_r_type = r_type; +             } +        else { +          previous_sectdiff = false; +          sectdiff_r_type = 0; +        } +        if (cputype == MachO::CPU_TYPE_ARM && +            (r_type == llvm::MachO::ARM_RELOC_HALF || +             r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) +          previous_arm_half = true; +        else +          previous_arm_half = false; +        outs() << "\n"; +      } +      else { +        // scattered: address pcrel length extern type scattered value +        outs() << format("%08x %1d     %-2d     n/a    %-7d 1         0x%08x\n", +                         (unsigned int)r_address, r_pcrel, r_length, r_type, +                         (unsigned int)r_value); +      } +    } +    else { +      if (verbose) { +        // plain: address +        if (cputype == MachO::CPU_TYPE_ARM && +            r_type == llvm::MachO::ARM_RELOC_PAIR) +          outs() << "         "; +        else +          outs() << format("%08x ", (unsigned int)r_address); +         +        // plain: pcrel +        if (r_pcrel) +          outs() << "True  "; +        else +          outs() << "False "; +         +        // plain: length +        PrintRLength(cputype, r_type, r_length, previous_arm_half); +         +        if (r_extern) { +          // plain: extern & type & scattered +          outs() << "True   "; +          PrintRType(cputype, r_type); +          outs() << "False     "; +           +          // plain: symbolnum/value +          if (r_symbolnum > Symtab.nsyms) +            outs() << format("?(%d)\n", r_symbolnum); +          else { +            SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); +            Expected<StringRef> SymNameNext = Symbol.getName(); +            const char *name = NULL; +            if (SymNameNext) +              name = SymNameNext->data(); +            if (name == NULL) +              outs() << format("?(%d)\n", r_symbolnum); +            else +              outs() << name << "\n"; +          } +        } +        else { +          // plain: extern & type & scattered +          outs() << "False  "; +          PrintRType(cputype, r_type); +          outs() << "False     "; +           +          // plain: symbolnum/value +          if (cputype == MachO::CPU_TYPE_ARM && +                   r_type == llvm::MachO::ARM_RELOC_PAIR) +            outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); +          else if (cputype == MachO::CPU_TYPE_ARM64 && +                   r_type == llvm::MachO::ARM64_RELOC_ADDEND) +            outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); +          else { +            outs() << format("%d ", r_symbolnum); +            if (r_symbolnum == llvm::MachO::R_ABS) +              outs() << "R_ABS\n"; +            else { +              // in this case, r_symbolnum is actually a 1-based section number +              uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; +              if (r_symbolnum > 0 && r_symbolnum <= nsects) { +                llvm::object::DataRefImpl DRI; +                DRI.d.a = r_symbolnum-1; +                StringRef SegName = O->getSectionFinalSegmentName(DRI); +                StringRef SectName; +                if (O->getSectionName(DRI, SectName)) +                  outs() << "(?,?)\n"; +                else +                  outs() << "(" << SegName << "," << SectName << ")\n"; +              } +              else { +                outs() << "(?,?)\n"; +              } +            } +          } +        } +        if (cputype == MachO::CPU_TYPE_ARM && +            (r_type == llvm::MachO::ARM_RELOC_HALF || +             r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) +          previous_arm_half = true; +        else +          previous_arm_half = false; +      } +      else { +        // plain: address pcrel length extern type scattered symbolnum/section +        outs() << format("%08x %1d     %-2d     %1d      %-7d 0         %d\n", +                         (unsigned int)r_address, r_pcrel, r_length, r_extern, +                         r_type, r_symbolnum); +      } +    } +  } +} + +static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { +  const uint64_t cputype = O->getHeader().cputype; +  const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); +  if (Dysymtab.nextrel != 0) { +    outs() << "External relocation information " << Dysymtab.nextrel +           << " entries"; +    outs() << "\naddress  pcrel length extern type    scattered " +              "symbolnum/value\n"; +    PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, +                           verbose); +  } +  if (Dysymtab.nlocrel != 0) { +    outs() << format("Local relocation information %u entries", +                     Dysymtab.nlocrel); +    outs() << format("\naddress  pcrel length extern type    scattered " +                     "symbolnum/value\n"); +    PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, +                           verbose); +  } +  for (const auto &Load : O->load_commands()) { +    if (Load.C.cmd == MachO::LC_SEGMENT_64) { +      const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); +      for (unsigned J = 0; J < Seg.nsects; ++J) { +        const MachO::section_64 Sec = O->getSection64(Load, J); +        if (Sec.nreloc != 0) { +          DataRefImpl DRI; +          DRI.d.a = J; +          const StringRef SegName = O->getSectionFinalSegmentName(DRI); +          StringRef SectName; +          if (O->getSectionName(DRI, SectName)) +            outs() << "Relocation information (" << SegName << ",?) " +                   << format("%u entries", Sec.nreloc); +          else +            outs() << "Relocation information (" << SegName << "," +                   << SectName << format(") %u entries", Sec.nreloc); +          outs() << "\naddress  pcrel length extern type    scattered " +                    "symbolnum/value\n"; +          PrintRelocationEntries(O, O->section_rel_begin(DRI), +                                 O->section_rel_end(DRI), cputype, verbose); +        } +      } +    } else if (Load.C.cmd == MachO::LC_SEGMENT) { +      const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); +      for (unsigned J = 0; J < Seg.nsects; ++J) { +        const MachO::section Sec = O->getSection(Load, J); +        if (Sec.nreloc != 0) { +          DataRefImpl DRI; +          DRI.d.a = J; +          const StringRef SegName = O->getSectionFinalSegmentName(DRI); +          StringRef SectName; +          if (O->getSectionName(DRI, SectName)) +            outs() << "Relocation information (" << SegName << ",?) " +                   << format("%u entries", Sec.nreloc); +          else +            outs() << "Relocation information (" << SegName << "," +                   << SectName << format(") %u entries", Sec.nreloc); +          outs() << "\naddress  pcrel length extern type    scattered " +                    "symbolnum/value\n"; +          PrintRelocationEntries(O, O->section_rel_begin(DRI), +                                 O->section_rel_end(DRI), cputype, verbose); +        } +      } +    } +  } +} +  static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {    MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();    uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); @@ -1221,9 +1548,10 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,    // If we are doing some processing here on the Mach-O file print the header    // info.  And don't print it otherwise like in the case of printing the    // UniversalHeaders or ArchiveHeaders. -  if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable || -      LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints || -      DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) { +  if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || +      Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || +      DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || +      (FilterSections.size() != 0)) {      if (!NoLeadingHeaders) {        outs() << Name;        if (!ArchiveMemberName.empty()) @@ -1267,7 +1595,7 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,    if (LinkOptHints)      PrintLinkOptHints(MachOOF);    if (Relocations) -    PrintRelocations(MachOOF); +    PrintRelocations(MachOOF, !NonVerbose);    if (SectionHeaders)      PrintSectionHeaders(MachOOF);    if (SectionContents)  | 

