From 2acadbddf6783055249da9fc9ea40a05b83ce56a Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Sat, 27 Nov 2010 13:33:15 +0000 Subject: [PATCH] macho-dump: Add support for dumping sections. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120215 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachOFormat.h | 31 ++++++++++++ include/llvm/Object/MachOObject.h | 8 ++++ lib/Object/MachOObject.cpp | 46 ++++++++++++++++++ tools/macho-dump/macho-dump.cpp | 78 ++++++++++++++++++++++++++++--- 4 files changed, 157 insertions(+), 6 deletions(-) diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index a6f0afbd94a..320140773d4 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -219,7 +219,38 @@ namespace macho { }; /// @} + /// @name Section Data + /// @{ + struct Section { + char Name[16]; + char SegmentName[16]; + uint32_t Address; + uint32_t Size; + uint32_t Offset; + uint32_t Align; + uint32_t RelocationTableOffset; + uint32_t NumRelocationTableEntries; + uint32_t Flags; + uint32_t Reserved1; + uint32_t Reserved2; + }; + struct Section64 { + char Name[16]; + char SegmentName[16]; + uint64_t Address; + uint64_t Size; + uint32_t Offset; + uint32_t Align; + uint32_t RelocationTableOffset; + uint32_t NumRelocationTableEntries; + uint32_t Flags; + uint32_t Reserved1; + uint32_t Reserved2; + uint32_t Reserved3; + }; + + /// @} /// @name Indirect Symbol Table /// @{ diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h index 79fbfd21b64..77a8d3592e4 100644 --- a/include/llvm/Object/MachOObject.h +++ b/include/llvm/Object/MachOObject.h @@ -129,6 +129,14 @@ public: const macho::DysymtabLoadCommand &DLC, unsigned Index, InMemoryStruct &Res) const; + void ReadSection( + const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct &Res) const; + void ReadSection64( + const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct &Res) const; /// @} }; diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp index 236dfe0ce50..1e9ec70d422 100644 --- a/lib/Object/MachOObject.cpp +++ b/lib/Object/MachOObject.cpp @@ -243,3 +243,49 @@ MachOObject::ReadIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, Index * sizeof(macho::IndirectSymbolTableEntry)); ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); } + + +template<> +void SwapStruct(macho::Section &Value) { + SwapValue(Value.Address); + SwapValue(Value.Size); + SwapValue(Value.Offset); + SwapValue(Value.Align); + SwapValue(Value.RelocationTableOffset); + SwapValue(Value.NumRelocationTableEntries); + SwapValue(Value.Flags); + SwapValue(Value.Reserved1); + SwapValue(Value.Reserved2); +} +void MachOObject::ReadSection(const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct &Res) const { + assert(LCI.Command.Type == macho::LCT_Segment && + "Unexpected load command info!"); + uint64_t Offset = (LCI.Offset + sizeof(macho::SegmentLoadCommand) + + Index * sizeof(macho::Section)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} + +template<> +void SwapStruct(macho::Section64 &Value) { + SwapValue(Value.Address); + SwapValue(Value.Size); + SwapValue(Value.Offset); + SwapValue(Value.Align); + SwapValue(Value.RelocationTableOffset); + SwapValue(Value.NumRelocationTableEntries); + SwapValue(Value.Flags); + SwapValue(Value.Reserved1); + SwapValue(Value.Reserved2); + SwapValue(Value.Reserved3); +} +void MachOObject::ReadSection64(const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct &Res) const { + assert(LCI.Command.Type == macho::LCT_Segment64 && + "Unexpected load command info!"); + uint64_t Offset = (LCI.Offset + sizeof(macho::Segment64LoadCommand) + + Index * sizeof(macho::Section64)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp index 487a00607b8..68e61ba8d66 100644 --- a/tools/macho-dump/macho-dump.cpp +++ b/tools/macho-dump/macho-dump.cpp @@ -25,7 +25,7 @@ static cl::opt InputFile(cl::Positional, cl::desc(""), cl::init("-")); static cl::opt -DumpSectionData("dump-section-data", cl::desc("Dump the contents of sections"), +ShowSectionData("dump-section-data", cl::desc("Dump the contents of sections"), cl::init(false)); /// @@ -83,6 +83,31 @@ static void DumpSegmentCommandData(StringRef Name, outs() << " ('flags', " << Flags << ")\n"; } +static void DumpSectionData(unsigned Index, StringRef Name, + StringRef SegmentName, uint64_t Address, + uint64_t Size, uint32_t Offset, + uint32_t Align, uint32_t RelocationTableOffset, + uint32_t NumRelocationTableEntries, + uint32_t Flags, uint32_t Reserved1, + uint32_t Reserved2, uint64_t Reserved3 = ~0ULL) { + outs() << " # Section " << Index << "\n"; + outs() << " (('section_name', '"; + outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; + outs() << " ('segment_name', '"; + outs().write_escaped(SegmentName, /*UseHexEscapes=*/true) << "')\n"; + outs() << " ('address', " << Address << ")\n"; + outs() << " ('size', " << Size << ")\n"; + outs() << " ('offset', " << Offset << ")\n"; + outs() << " ('alignment', " << Align << ")\n"; + outs() << " ('reloc_offset', " << RelocationTableOffset << ")\n"; + outs() << " ('num_reloc', " << NumRelocationTableEntries << ")\n"; + outs() << " ('flags', " << format("%#x", Flags) << ")\n"; + outs() << " ('reserved1', " << Reserved1 << ")\n"; + outs() << " ('reserved2', " << Reserved2 << ")\n"; + if (Reserved3 != ~0ULL) + outs() << " ('reserved3', " << Reserved3 << ")\n"; +} + static int DumpSegmentCommand(MachOObject &Obj, const MachOObject::LoadCommandInfo &LCI) { InMemoryStruct SLC; @@ -90,13 +115,34 @@ static int DumpSegmentCommand(MachOObject &Obj, if (!SLC) return Error("unable to read segment load command"); - DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, SLC->VMSize, - SLC->FileOffset, SLC->FileSize, + DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, + SLC->VMSize, SLC->FileOffset, SLC->FileSize, SLC->MaxVMProtection, SLC->InitialVMProtection, SLC->NumSections, SLC->Flags); - return 0; + // Dump the sections. + int Res = 0; + outs() << " ('sections', [\n"; + for (unsigned i = 0; i != SLC->NumSections; ++i) { + InMemoryStruct Sect; + Obj.ReadSection(LCI, i, Sect); + if (!SLC) { + Res = Error("unable to read section '" + Twine(i) + "'"); + break; + } + + DumpSectionData(i, StringRef(Sect->Name, 16), + StringRef(Sect->SegmentName, 16), Sect->Address, Sect->Size, + Sect->Offset, Sect->Align, Sect->RelocationTableOffset, + Sect->NumRelocationTableEntries, Sect->Flags, + Sect->Reserved1, Sect->Reserved2); + outs() << " ),\n"; + } + outs() << " ])\n"; + + return Res; } + static int DumpSegment64Command(MachOObject &Obj, const MachOObject::LoadCommandInfo &LCI) { InMemoryStruct SLC; @@ -104,11 +150,31 @@ static int DumpSegment64Command(MachOObject &Obj, if (!SLC) return Error("unable to read segment load command"); - DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, SLC->VMSize, - SLC->FileOffset, SLC->FileSize, + DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, + SLC->VMSize, SLC->FileOffset, SLC->FileSize, SLC->MaxVMProtection, SLC->InitialVMProtection, SLC->NumSections, SLC->Flags); + // Dump the sections. + int Res = 0; + outs() << " ('sections', [\n"; + for (unsigned i = 0; i != SLC->NumSections; ++i) { + InMemoryStruct Sect; + Obj.ReadSection64(LCI, i, Sect); + if (!SLC) { + Res = Error("unable to read section '" + Twine(i) + "'"); + break; + } + + DumpSectionData(i, StringRef(Sect->Name, 16), + StringRef(Sect->SegmentName, 16), Sect->Address, Sect->Size, + Sect->Offset, Sect->Align, Sect->RelocationTableOffset, + Sect->NumRelocationTableEntries, Sect->Flags, + Sect->Reserved1, Sect->Reserved2, Sect->Reserved3); + outs() << " ),\n"; + } + outs() << " ])\n"; + return 0; }