static void DumpLiteralPointerSection()

in MachODump.cpp [457:622]


static void DumpLiteralPointerSection(MachOObjectFile *O,
                                      const SectionRef &Section,
                                      const char *sect, uint32_t sect_size,
                                      uint64_t sect_addr,
                                      bool print_addresses) {
  // Collect the literal sections in this Mach-O file.
  std::vector<SectionRef> LiteralSections;
  for (const SectionRef &Section : O->sections()) {
    DataRefImpl Ref = Section.getRawDataRefImpl();
    uint32_t section_type;
    if (O->is64Bit()) {
      const MachO::section_64 Sec = O->getSection64(Ref);
      section_type = Sec.flags & MachO::SECTION_TYPE;
    } else {
      const MachO::section Sec = O->getSection(Ref);
      section_type = Sec.flags & MachO::SECTION_TYPE;
    }
    if (section_type == MachO::S_CSTRING_LITERALS ||
        section_type == MachO::S_4BYTE_LITERALS ||
        section_type == MachO::S_8BYTE_LITERALS ||
        section_type == MachO::S_16BYTE_LITERALS)
      LiteralSections.push_back(Section);
  }

  // Set the size of the literal pointer.
  uint32_t lp_size = O->is64Bit() ? 8 : 4;

  // Collect the external relocation symbols for the literal pointers.
  std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
  for (const RelocationRef &Reloc : Section.relocations()) {
    DataRefImpl Rel;
    MachO::any_relocation_info RE;
    bool isExtern = false;
    Rel = Reloc.getRawDataRefImpl();
    RE = O->getRelocation(Rel);
    isExtern = O->getPlainRelocationExternal(RE);
    if (isExtern) {
      uint64_t RelocOffset = Reloc.getOffset();
      symbol_iterator RelocSym = Reloc.getSymbol();
      Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
    }
  }
  array_pod_sort(Relocs.begin(), Relocs.end());

  // Dump each literal pointer.
  for (uint32_t i = 0; i < sect_size; i += lp_size) {
    if (print_addresses) {
      if (O->is64Bit())
        outs() << format("%016" PRIx64, sect_addr + i) << "  ";
      else
        outs() << format("%08" PRIx64, sect_addr + i) << "  ";
    }
    uint64_t lp;
    if (O->is64Bit()) {
      memcpy(&lp, sect + i, sizeof(uint64_t));
      if (O->isLittleEndian() != sys::IsLittleEndianHost)
        sys::swapByteOrder(lp);
    } else {
      uint32_t li;
      memcpy(&li, sect + i, sizeof(uint32_t));
      if (O->isLittleEndian() != sys::IsLittleEndianHost)
        sys::swapByteOrder(li);
      lp = li;
    }

    // First look for an external relocation entry for this literal pointer.
    auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
      return P.first == i;
    });
    if (Reloc != Relocs.end()) {
      symbol_iterator RelocSym = Reloc->second;
      StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName());
      outs() << "external relocation entry for symbol:" << SymName << "\n";
      continue;
    }

    // For local references see what the section the literal pointer points to.
    auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
      return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
    });
    if (Sect == LiteralSections.end()) {
      outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
      continue;
    }

    uint64_t SectAddress = Sect->getAddress();
    uint64_t SectSize = Sect->getSize();

    StringRef SectName;
    if (auto NameOrErr = Section.getName())
      SectName = *NameOrErr;
    else
      consumeError(NameOrErr.takeError());

    DataRefImpl Ref = Sect->getRawDataRefImpl();
    StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
    outs() << SegmentName << ":" << SectName << ":";

    uint32_t section_type;
    if (O->is64Bit()) {
      const MachO::section_64 Sec = O->getSection64(Ref);
      section_type = Sec.flags & MachO::SECTION_TYPE;
    } else {
      const MachO::section Sec = O->getSection(Ref);
      section_type = Sec.flags & MachO::SECTION_TYPE;
    }

    StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName());

    const char *Contents = reinterpret_cast<const char *>(BytesStr.data());

    switch (section_type) {
    case MachO::S_CSTRING_LITERALS:
      for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
           i++) {
        DumpCstringChar(Contents[i]);
      }
      outs() << "\n";
      break;
    case MachO::S_4BYTE_LITERALS:
      float f;
      memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
      uint32_t l;
      memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
      if (O->isLittleEndian() != sys::IsLittleEndianHost) {
        sys::swapByteOrder(f);
        sys::swapByteOrder(l);
      }
      DumpLiteral4(l, f);
      break;
    case MachO::S_8BYTE_LITERALS: {
      double d;
      memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
      uint32_t l0, l1;
      memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
      memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
             sizeof(uint32_t));
      if (O->isLittleEndian() != sys::IsLittleEndianHost) {
        sys::swapByteOrder(f);
        sys::swapByteOrder(l0);
        sys::swapByteOrder(l1);
      }
      DumpLiteral8(O, l0, l1, d);
      break;
    }
    case MachO::S_16BYTE_LITERALS: {
      uint32_t l0, l1, l2, l3;
      memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
      memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
             sizeof(uint32_t));
      memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
             sizeof(uint32_t));
      memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
             sizeof(uint32_t));
      if (O->isLittleEndian() != sys::IsLittleEndianHost) {
        sys::swapByteOrder(l0);
        sys::swapByteOrder(l1);
        sys::swapByteOrder(l2);
        sys::swapByteOrder(l3);
      }
      DumpLiteral16(l0, l1, l2, l3);
      break;
    }
    }
  }
}