diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index 0a2cceccb83..28bb40fba97 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -250,6 +250,25 @@ namespace macho { uint32_t Reserved3; }; + /// @} + /// @name Symbol Table Entries + /// @{ + + struct SymbolTableEntry { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; + uint32_t Value; + }; + struct Symbol64TableEntry { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; + uint64_t Value; + }; + /// @} /// @name Indirect Symbol Table /// @{ diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h index 836e5491d21..6c0a1d0cad0 100644 --- a/include/llvm/Object/MachOObject.h +++ b/include/llvm/Object/MachOObject.h @@ -111,6 +111,11 @@ public: return StringTable; } + StringRef getStringAtIndex(unsigned Index) const { + size_t End = getStringTableData().find('\0', Index); + return getStringTableData().slice(Index, End); + } + void RegisterStringTable(macho::SymtabLoadCommand &SLC); /// @} @@ -157,6 +162,12 @@ public: void ReadRelocationEntry( uint64_t RelocationTableOffset, unsigned Index, InMemoryStruct &Res) const; + void ReadSymbolTableEntry( + uint64_t SymbolTableOffset, unsigned Index, + InMemoryStruct &Res) const; + void ReadSymbol64TableEntry( + uint64_t SymbolTableOffset, unsigned Index, + InMemoryStruct &Res) const; /// @} }; diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp index 45c9bff45fc..33890f6617a 100644 --- a/lib/Object/MachOObject.cpp +++ b/lib/Object/MachOObject.cpp @@ -308,3 +308,31 @@ void MachOObject::ReadRelocationEntry(uint64_t RelocationTableOffset, Index * sizeof(macho::RelocationEntry)); ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); } + +template<> +void SwapStruct(macho::SymbolTableEntry &Value) { + SwapValue(Value.StringIndex); + SwapValue(Value.Flags); + SwapValue(Value.Value); +} +void MachOObject::ReadSymbolTableEntry(uint64_t SymbolTableOffset, + unsigned Index, + InMemoryStruct &Res) const { + uint64_t Offset = (SymbolTableOffset + + Index * sizeof(macho::SymbolTableEntry)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} + +template<> +void SwapStruct(macho::Symbol64TableEntry &Value) { + SwapValue(Value.StringIndex); + SwapValue(Value.Flags); + SwapValue(Value.Value); +} +void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset, + unsigned Index, + InMemoryStruct &Res) const { + uint64_t Offset = (SymbolTableOffset + + Index * sizeof(macho::Symbol64TableEntry)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp index e2a8ef136ec..abe06f4f4dc 100644 --- a/tools/macho-dump/macho-dump.cpp +++ b/tools/macho-dump/macho-dump.cpp @@ -201,6 +201,20 @@ static int DumpSegment64Command(MachOObject &Obj, return 0; } +static void DumpSymbolTableEntryData(MachOObject &Obj, + unsigned Index, uint32_t StringIndex, + uint8_t Type, uint8_t SectionIndex, + uint16_t Flags, uint64_t Value) { + outs() << " # Symbol " << Index << "\n"; + outs() << " (('n_strx', " << StringIndex << ")\n"; + outs() << " ('n_type', " << format("%#x", Type) << ")\n"; + outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n"; + outs() << " ('n_desc', " << Flags << ")\n"; + outs() << " ('n_value', " << Value << ")\n"; + outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n"; + outs() << " ),\n"; +} + static int DumpSymtabCommand(MachOObject &Obj, const MachOObject::LoadCommandInfo &LCI) { InMemoryStruct SLC; @@ -221,7 +235,35 @@ static int DumpSymtabCommand(MachOObject &Obj, outs().write_escaped(Obj.getStringTableData(), /*UseHexEscapes=*/true) << "')\n"; - return 0; + // Dump the symbol table. + int Res = 0; + outs() << " ('_symbols', [\n"; + for (unsigned i = 0; i != SLC->NumSymbolTableEntries; ++i) { + if (Obj.is64Bit()) { + InMemoryStruct STE; + Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE); + if (!STE) { + Res = Error("unable to read symbol: '" + Twine(i) + "'"); + break; + } + + DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, + STE->SectionIndex, STE->Flags, STE->Value); + } else { + InMemoryStruct STE; + Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE); + if (!SLC) { + Res = Error("unable to read symbol: '" + Twine(i) + "'"); + break; + } + + DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, + STE->SectionIndex, STE->Flags, STE->Value); + } + } + outs() << " ])\n"; + + return Res; } static int DumpDysymtabCommand(MachOObject &Obj,