diff options
author | Timur Iskhodzhanov <timurrrr@google.com> | 2014-10-23 22:25:31 +0000 |
---|---|---|
committer | Timur Iskhodzhanov <timurrrr@google.com> | 2014-10-23 22:25:31 +0000 |
commit | 13535f412a3fbd0374060ea6af38c0cde01e34ae (patch) | |
tree | cbb45843b363996b02f4885eb8a886c668ad838c /tools/llvm-readobj | |
parent | 48ba51a8cddd823f1c6823218b982b87b0018c0d (diff) |
PR21189: Teach llvm-readobj to dump bits of COFF symbol subsections required to debug using VS2012+
Reviewed at http://reviews.llvm.org/D5755
Thanks to Andrey Guskov for his help investigating this!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220526 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-readobj')
-rw-r--r-- | tools/llvm-readobj/COFFDumper.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index dc280a634dc..6242a790f5a 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -69,6 +69,10 @@ private: void printCodeViewLineTables(const SectionRef &Section); + void printCodeViewSymbolsSubsection(StringRef Subsection, + const SectionRef &Section, + uint32_t Offset); + void cacheRelocations(); std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset, @@ -444,6 +448,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { ListScope D(W, "CodeViewLineTables"); { + // FIXME: Add more offset correctness checks. DataExtractor DE(Data, true, 4); uint32_t Offset = 0, Magic = DE.getU32(&Offset); @@ -473,6 +478,9 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { W.printBinaryBlock("Contents", Contents); switch (SubSectionType) { + case COFF::DEBUG_SYMBOL_SUBSECTION: + printCodeViewSymbolsSubsection(Contents, Section, Offset); + break; case COFF::DEBUG_LINE_TABLE_SUBSECTION: { // Holds a PC to file:line table. Some data to parse this subsection is // stored in the other subsections, so just check sanity and store the @@ -592,6 +600,80 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { } } +void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, + const SectionRef &Section, + uint32_t OffsetInSection) { + if (Subsection.size() == 0) { + error(object_error::parse_failed); + return; + } + DataExtractor DE(Subsection, true, 4); + uint32_t Offset = 0; + + // Function-level subsections have "procedure start" and "procedure end" + // commands that should come in pairs and surround relevant info. + bool InFunctionScope = false; + while (DE.isValidOffset(Offset)) { + // Read subsection segments one by one. + uint16_t Size = DE.getU16(&Offset); + // The section size includes the size of the type identifier. + if (Size < 2 || !DE.isValidOffsetForDataOfSize(Offset, Size)) { + error(object_error::parse_failed); + return; + } + Size -= 2; + uint16_t Type = DE.getU16(&Offset); + switch (Type) { + case COFF::DEBUG_SYMBOL_TYPE_PROC_START: { + DictScope S(W, "ProcStart"); + if (InFunctionScope || Size < 36) { + error(object_error::parse_failed); + return; + } + InFunctionScope = true; + + // We're currently interested in a limited subset of fields in this + // segment, just ignore the rest of the fields for now. + uint8_t Unused[12]; + DE.getU8(&Offset, Unused, 12); + uint32_t CodeSize = DE.getU32(&Offset); + DE.getU8(&Offset, Unused, 12); + StringRef SectionName; + if (error(resolveSymbolName(Obj->getCOFFSection(Section), + OffsetInSection + Offset, SectionName))) + return; + Offset += 4; + DE.getU8(&Offset, Unused, 3); + StringRef FunctionName = DE.getCStr(&Offset); + if (!DE.isValidOffset(Offset)) { + error(object_error::parse_failed); + return; + } + W.printString("FunctionName", FunctionName); + W.printString("Section", SectionName); + W.printHex("CodeSize", CodeSize); + + break; + } + case COFF::DEBUG_SYMBOL_TYPE_PROC_END: { + W.startLine() << "ProcEnd\n"; + if (!InFunctionScope || Size > 0) { + error(object_error::parse_failed); + return; + } + InFunctionScope = false; + break; + } + default: + Offset += Size; + break; + } + } + + if (InFunctionScope) + error(object_error::parse_failed); +} + void COFFDumper::printSections() { ListScope SectionsD(W, "Sections"); int SectionNumber = 0; |