diff options
| author | Frederic Riss <friss@apple.com> | 2015-08-31 00:29:09 +0000 |
|---|---|---|
| committer | Frederic Riss <friss@apple.com> | 2015-08-31 00:29:09 +0000 |
| commit | 5ba01d6d95418507192283393ca613fafb0299bf (patch) | |
| tree | 4a4e76b4df4d66b00667fc7dbf8bd02a0206d9e0 /llvm/tools/dsymutil/MachODebugMapParser.cpp | |
| parent | 592ee15e14b9ae3bb02320ed55c1daf55f980a94 (diff) | |
| download | bcm5719-llvm-5ba01d6d95418507192283393ca613fafb0299bf.tar.gz bcm5719-llvm-5ba01d6d95418507192283393ca613fafb0299bf.zip | |
[dsymutil] Implement -symtab/-s option.
This option dumps the STAB entries that define the debug map(s)
stored in the input binaries, and then exits.
llvm-svn: 246403
Diffstat (limited to 'llvm/tools/dsymutil/MachODebugMapParser.cpp')
| -rw-r--r-- | llvm/tools/dsymutil/MachODebugMapParser.cpp | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp index 8d17d527dfc..107bff7c5b8 100644 --- a/llvm/tools/dsymutil/MachODebugMapParser.cpp +++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp @@ -34,6 +34,9 @@ public: /// or isn't of a supported type. ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parse(); + /// Walk the symbol table and dump it. + bool dumpStab(); + private: std::string BinaryPath; SmallVector<StringRef, 1> Archs; @@ -74,6 +77,22 @@ private: handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc, STE.n_value); } + + /// Dump the symbol table output header. + void dumpSymTabHeader(raw_ostream &OS, StringRef Arch); + + /// Dump the contents of nlist entries. + void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, uint32_t StringIndex, + uint8_t Type, uint8_t SectionIndex, uint16_t Flags, + uint64_t Value); + + template <typename STEType> + void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, const STEType &STE) { + dumpSymTabEntry(OS, Index, STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc, + STE.n_value); + } + void dumpOneBinaryStab(const MachOObjectFile &MainBinary, + StringRef BinaryPath); }; static void Warning(const Twine &Msg) { errs() << "warning: " + Msg + "\n"; } @@ -116,6 +135,12 @@ void MachODebugMapParser::switchToNewDebugMapObject(StringRef Filename, loadCurrentObjectFileSymbols(*ErrOrAchObj); } +static std::string getArchName(const object::MachOObjectFile &Obj) { + Triple ThumbTriple; + Triple T = Obj.getArch(nullptr, &ThumbTriple); + return T.getArchName(); +} + std::unique_ptr<DebugMap> MachODebugMapParser::parseOneBinary(const MachOObjectFile &MainBinary, StringRef BinaryPath) { @@ -135,6 +160,133 @@ MachODebugMapParser::parseOneBinary(const MachOObjectFile &MainBinary, return std::move(Result); } +// Table that maps Darwin's Mach-O stab constants to strings to allow printing. +// llvm-nm has very similar code, the strings used here are however slightly +// different and part of the interface of dsymutil (some project's build-systems +// parse the ouptut of dsymutil -s), thus they shouldn't be changed. +struct DarwinStabName { + uint8_t NType; + const char *Name; +}; + +static const struct DarwinStabName DarwinStabNames[] = { + {MachO::N_GSYM, "N_GSYM"}, {MachO::N_FNAME, "N_FNAME"}, + {MachO::N_FUN, "N_FUN"}, {MachO::N_STSYM, "N_STSYM"}, + {MachO::N_LCSYM, "N_LCSYM"}, {MachO::N_BNSYM, "N_BNSYM"}, + {MachO::N_PC, "N_PC"}, {MachO::N_AST, "N_AST"}, + {MachO::N_OPT, "N_OPT"}, {MachO::N_RSYM, "N_RSYM"}, + {MachO::N_SLINE, "N_SLINE"}, {MachO::N_ENSYM, "N_ENSYM"}, + {MachO::N_SSYM, "N_SSYM"}, {MachO::N_SO, "N_SO"}, + {MachO::N_OSO, "N_OSO"}, {MachO::N_LSYM, "N_LSYM"}, + {MachO::N_BINCL, "N_BINCL"}, {MachO::N_SOL, "N_SOL"}, + {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"}, + {MachO::N_OLEVEL, "N_OLEV"}, {MachO::N_PSYM, "N_PSYM"}, + {MachO::N_EINCL, "N_EINCL"}, {MachO::N_ENTRY, "N_ENTRY"}, + {MachO::N_LBRAC, "N_LBRAC"}, {MachO::N_EXCL, "N_EXCL"}, + {MachO::N_RBRAC, "N_RBRAC"}, {MachO::N_BCOMM, "N_BCOMM"}, + {MachO::N_ECOMM, "N_ECOMM"}, {MachO::N_ECOML, "N_ECOML"}, + {MachO::N_LENG, "N_LENG"}, {0, 0}}; + +static const char *getDarwinStabString(uint8_t NType) { + for (unsigned i = 0; DarwinStabNames[i].Name; i++) { + if (DarwinStabNames[i].NType == NType) + return DarwinStabNames[i].Name; + } + return 0; +} + +void MachODebugMapParser::dumpSymTabHeader(raw_ostream &OS, StringRef Arch) { + OS << "-----------------------------------" + "-----------------------------------\n"; + OS << "Symbol table for: '" << BinaryPath << "' (" << Arch.data() << ")\n"; + OS << "-----------------------------------" + "-----------------------------------\n"; + OS << "Index n_strx n_type n_sect n_desc n_value\n"; + OS << "======== -------- ------------------ ------ ------ ----------------\n"; +} + +void MachODebugMapParser::dumpSymTabEntry(raw_ostream &OS, uint64_t Index, + uint32_t StringIndex, uint8_t Type, + uint8_t SectionIndex, uint16_t Flags, + uint64_t Value) { + + // Index + OS << '[' << format_decimal(Index, 6) << "] " + // n_strx + << format_hex_no_prefix(StringIndex, 8) << ' ' + // n_type... + << format_hex_no_prefix(Type, 2) << " ("; + + if (Type & MachO::N_STAB) + OS << left_justify(getDarwinStabString(Type), 13); + else { + if (Type & MachO::N_PEXT) + OS << "PEXT "; + else + OS << " "; + switch (Type & MachO::N_TYPE) { + case MachO::N_UNDF: // 0x0 undefined, n_sect == NO_SECT + OS << "UNDF"; + break; + case MachO::N_ABS: // 0x2 absolute, n_sect == NO_SECT + OS << "ABS "; + break; + case MachO::N_SECT: // 0xe defined in section number n_sect + OS << "SECT"; + break; + case MachO::N_PBUD: // 0xc prebound undefined (defined in a dylib) + OS << "PBUD"; + break; + case MachO::N_INDR: // 0xa indirect + OS << "INDR"; + break; + default: + OS << format_hex_no_prefix(Type, 2) << " "; + break; + } + if (Type & MachO::N_EXT) + OS << " EXT"; + else + OS << " "; + } + + OS << ") " + // n_sect + << format_hex_no_prefix(SectionIndex, 2) << " " + // n_desc + << format_hex_no_prefix(Flags, 4) << " " + // n_value + << format_hex_no_prefix(Value, 16); + + const char *Name = &MainBinaryStrings.data()[StringIndex]; + if (Name && Name[0]) + OS << " '" << Name << "'"; + + OS << "\n"; +} + +void MachODebugMapParser::dumpOneBinaryStab(const MachOObjectFile &MainBinary, + StringRef BinaryPath) { + loadMainBinarySymbols(MainBinary); + MainBinaryStrings = MainBinary.getStringTableData(); + raw_ostream &OS(llvm::outs()); + + StringRef ArchName = getArchName(MainBinary); + dumpSymTabHeader(OS, ArchName); + uint64_t Idx = 0; + for (const SymbolRef &Symbol : MainBinary.symbols()) { + const DataRefImpl &DRI = Symbol.getRawDataRefImpl(); + if (MainBinary.is64Bit()) + dumpSymTabEntry(OS, Idx, MainBinary.getSymbol64TableEntry(DRI)); + else + dumpSymTabEntry(OS, Idx, MainBinary.getSymbolTableEntry(DRI)); + Idx++; + } + + OS << "\n\n"; + resetParserState(); +} + static bool shouldLinkArch(SmallVectorImpl<StringRef> &Archs, StringRef Arch) { if (Archs.empty() || std::find(Archs.begin(), Archs.end(), "all") != Archs.end() || @@ -148,6 +300,23 @@ static bool shouldLinkArch(SmallVectorImpl<StringRef> &Archs, StringRef Arch) { return std::find(Archs.begin(), Archs.end(), Arch) != Archs.end(); } +bool MachODebugMapParser::dumpStab() { + auto MainBinOrError = + MainBinaryHolder.GetFilesAs<MachOObjectFile>(BinaryPath); + if (auto Error = MainBinOrError.getError()) { + llvm::errs() << "Cannot get '" << BinaryPath + << "' as MachO file: " << Error.message() << "\n"; + return false; + } + + Triple T; + for (const auto *Binary : *MainBinOrError) + if (shouldLinkArch(Archs, Binary->getArch(nullptr, &T).getArchName())) + dumpOneBinaryStab(*Binary, BinaryPath); + + return true; +} + /// This main parsing routine tries to open the main binary and if /// successful iterates over the STAB entries. The real parsing is /// done in handleStabSymbolTableEntry. @@ -297,5 +466,11 @@ parseDebugMap(StringRef InputFile, ArrayRef<std::string> Archs, return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose); } } + +bool dumpStab(StringRef InputFile, ArrayRef<std::string> Archs, + StringRef PrependPath) { + MachODebugMapParser Parser(InputFile, Archs, PrependPath, false); + return Parser.dumpStab(); +} } } |

