+typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
+
+static void CreateSymbolAddressMap(MachOObjectFile *O,
+ SymbolAddressMap *AddrMap) {
+ // Create a map of symbol addresses to symbol names.
+ for (const SymbolRef &Symbol : O->symbols()) {
+ SymbolRef::Type ST;
+ Symbol.getType(ST);
+ if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
+ ST == SymbolRef::ST_Other) {
+ uint64_t Address;
+ Symbol.getAddress(Address);
+ StringRef SymName;
+ Symbol.getName(SymName);
+ (*AddrMap)[Address] = SymName;
+ }
+ }
+}
+
+// GuessSymbolName is passed the address of what might be a symbol and a
+// pointer to the SymbolAddressMap. It returns the name of a symbol
+// with that address or nullptr if no symbol is found with that address.
+static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
+ const char *SymbolName = nullptr;
+ // A DenseMap can't lookup up some values.
+ if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
+ StringRef name = AddrMap->lookup(value);
+ if (!name.empty())
+ SymbolName = name.data();
+ }
+ return SymbolName;
+}
+
+static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
+ uint32_t sect_size, uint64_t sect_addr,
+ SymbolAddressMap *AddrMap,
+ bool verbose) {
+ uint32_t stride;
+ if (O->is64Bit())
+ stride = sizeof(uint64_t);
+ else
+ stride = sizeof(uint32_t);
+ for (uint32_t i = 0; i < sect_size; i += stride) {
+ const char *SymbolName = nullptr;
+ if (O->is64Bit()) {
+ outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
+ uint64_t pointer_value;
+ memcpy(&pointer_value, sect + i, stride);
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(pointer_value);
+ outs() << format("0x%016" PRIx64, pointer_value);
+ if (verbose)
+ SymbolName = GuessSymbolName(pointer_value, AddrMap);
+ } else {
+ outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
+ uint32_t pointer_value;
+ memcpy(&pointer_value, sect + i, stride);
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(pointer_value);
+ outs() << format("0x%08" PRIx32, pointer_value);
+ if (verbose)
+ SymbolName = GuessSymbolName(pointer_value, AddrMap);
+ }
+ if (SymbolName)
+ outs() << " " << SymbolName;
+ outs() << "\n";
+ }
+}
+
+static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
+ uint32_t size, uint64_t addr) {
+ uint32_t cputype = O->getHeader().cputype;
+ if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
+ uint32_t j;
+ for (uint32_t i = 0; i < size; i += j, addr += j) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, addr) << "\t";
+ else
+ outs() << format("%08" PRIx64, sect) << "\t";
+ for (j = 0; j < 16 && i + j < size; j++) {
+ uint8_t byte_word = *(sect + i + j);
+ outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
+ }
+ outs() << "\n";
+ }
+ } else {
+ uint32_t j;
+ for (uint32_t i = 0; i < size; i += j, addr += j) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, addr) << "\t";
+ else
+ outs() << format("%08" PRIx64, sect) << "\t";
+ for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
+ j += sizeof(int32_t)) {
+ if (i + j + sizeof(int32_t) < size) {
+ uint32_t long_word;
+ memcpy(&long_word, sect + i + j, sizeof(int32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(long_word);
+ outs() << format("%08" PRIx32, long_word) << " ";
+ } else {
+ for (uint32_t k = 0; i + j + k < size; k++) {
+ uint8_t byte_word = *(sect + i + j);
+ outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
+ }
+ }
+ }
+ outs() << "\n";
+ }
+ }
+}
+
+static void DumpSectionContents(MachOObjectFile *O, bool verbose) {
+ SymbolAddressMap AddrMap;
+ if (verbose)
+ CreateSymbolAddressMap(O, &AddrMap);
+
+ for (unsigned i = 0; i < DumpSections.size(); ++i) {
+ StringRef DumpSection = DumpSections[i];
+ std::pair<StringRef, StringRef> DumpSegSectName;
+ DumpSegSectName = DumpSection.split(',');
+ StringRef DumpSegName, DumpSectName;
+ if (DumpSegSectName.second.size()) {
+ DumpSegName = DumpSegSectName.first;
+ DumpSectName = DumpSegSectName.second;
+ } else {
+ DumpSegName = "";
+ DumpSectName = DumpSegSectName.first;
+ }
+ for (const SectionRef &Section : O->sections()) {
+ StringRef SectName;
+ Section.getName(SectName);
+ DataRefImpl Ref = Section.getRawDataRefImpl();
+ StringRef SegName = O->getSectionFinalSegmentName(Ref);
+ if ((DumpSegName.empty() || SegName == DumpSegName) &&
+ (SectName == DumpSectName)) {
+ outs() << "Contents of (" << SegName << "," << SectName
+ << ") section\n";
+ 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;
+ Section.getContents(BytesStr);
+ const char *sect = reinterpret_cast<const char *>(BytesStr.data());
+ uint32_t sect_size = BytesStr.size();
+ uint64_t sect_addr = Section.getAddress();
+
+ if (verbose) {
+ switch (section_type) {
+ case MachO::S_REGULAR:
+ DumpRawSectionContents(O, sect, sect_size, sect_addr);
+ break;
+ case MachO::S_ZEROFILL:
+ outs() << "zerofill section and has no contents in the file\n";
+ break;
+ case MachO::S_MOD_INIT_FUNC_POINTERS:
+ case MachO::S_MOD_TERM_FUNC_POINTERS:
+ DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,
+ verbose);
+ break;
+ default:
+ outs() << "Unknown section type ("
+ << format("0x%08" PRIx32, section_type) << ")\n";
+ DumpRawSectionContents(O, sect, sect_size, sect_addr);
+ break;
+ }
+ } else {
+ if (section_type == MachO::S_ZEROFILL)
+ outs() << "zerofill section and has no contents in the file\n";
+ else
+ DumpRawSectionContents(O, sect, sect_size, sect_addr);
+ }
+ }
+ }
+ }
+}
+