From c2046c01da82135fa8e6ab40ce6563c7f13c648c Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 14 Jan 2016 19:20:17 +0000 Subject: [PATCH] [codeview] Dump CodeView inlinee lines subsection git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257790 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/CodeView/Line.h | 22 +++++- .../Inputs/codeview-inlining.obj.coff | Bin 0 -> 8396 bytes .../tools/llvm-readobj/codeview-inlining.test | 65 ++++++++++++++++++ tools/llvm-readobj/COFFDumper.cpp | 36 ++++++++++ 4 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 test/tools/llvm-readobj/Inputs/codeview-inlining.obj.coff create mode 100644 test/tools/llvm-readobj/codeview-inlining.test diff --git a/include/llvm/DebugInfo/CodeView/Line.h b/include/llvm/DebugInfo/CodeView/Line.h index a7cdbdaac32..b466ca6e223 100644 --- a/include/llvm/DebugInfo/CodeView/Line.h +++ b/include/llvm/DebugInfo/CodeView/Line.h @@ -10,11 +10,14 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_LINE_H #define LLVM_DEBUGINFO_CODEVIEW_LINE_H +#include "llvm/Support/Endian.h" #include namespace llvm { namespace codeview { +using llvm::support::ulittle32_t; + class LineInfo { public: static const uint32_t AlwaysStepIntoLineNumber = 0xfeefee; @@ -118,7 +121,22 @@ public: bool isNeverStepInto() const { return LineInf.isNeverStepInto(); } }; -} -} + +enum class InlineeLinesSignature : uint32_t { + Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE + ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX +}; + +struct InlineeSourceLine { + TypeIndex Inlinee; // ID of the function that was inlined. + ulittle32_t FileID; // Offset into FileChecksums subsection. + ulittle32_t SourceLineNum; // First line of inlined code. + // If extra files present: + // ulittle32_t ExtraFileCount; + // ulittle32_t Files[]; +}; + +} // namespace codeview +} // namespace llvm #endif diff --git a/test/tools/llvm-readobj/Inputs/codeview-inlining.obj.coff b/test/tools/llvm-readobj/Inputs/codeview-inlining.obj.coff new file mode 100644 index 0000000000000000000000000000000000000000..782e991c3bc70aef0db0e1ea4cb958abbc335704 GIT binary patch literal 8396 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 E1GYU&O#lD@ literal 0 HcmV?d00001 diff --git a/test/tools/llvm-readobj/codeview-inlining.test b/test/tools/llvm-readobj/codeview-inlining.test new file mode 100644 index 00000000000..13be86b6337 --- /dev/null +++ b/test/tools/llvm-readobj/codeview-inlining.test @@ -0,0 +1,65 @@ +; The following two object files were generated using the following command: +; $ cl /d2Zi+ /Zc:inline /O2 /Z7 /c t.cpp +; The contents of t.cpp follow: +; static void bar() { +; __asm nop +; } +; static void baz() { +; __asm nop +; } +; static __forceinline void foo() { +; __asm nop +; #include "a.h" +; #include "b.h" +; __asm nop +; goto forwards; +; +; backwards: +; __asm nop +; return; +; +; forwards: +; __asm rep nop +; goto backwards; +; } +; int main() { +; bar(); +; baz(); +; foo(); +; } +; +; Both a.h and b.h contain "__asm nop". + +RUN: llvm-readobj -s -codeview -section-symbols %p/Inputs/codeview-inlining.obj.coff | FileCheck %s + +; FIXME: If we were more clever, we could turn FileIDs into paths. + +; CHECK: SubSectionType: InlineeLines (0xF6) +; CHECK-NEXT: SubSectionSize: 0x3C +; CHECK-NEXT: InlineeSourceLine { +; CHECK-NEXT: Inlinee: bar (0x1002) +; CHECK-NEXT: FileID: 0x30 +; CHECK-NEXT: SourceLineNum: 2 +; CHECK-NEXT: ExtraFileCount: 0 +; CHECK-NEXT: ExtraFiles [ +; CHECK-NEXT: ] +; CHECK-NEXT: } +; CHECK-NEXT: InlineeSourceLine { +; CHECK-NEXT: Inlinee: baz (0x1003) +; CHECK-NEXT: FileID: 0x30 +; CHECK-NEXT: SourceLineNum: 5 +; CHECK-NEXT: ExtraFileCount: 0 +; CHECK-NEXT: ExtraFiles [ +; CHECK-NEXT: ] +; CHECK-NEXT: } +; The 'foo' inline site has extra files due to includes. +; CHECK-NEXT: InlineeSourceLine { +; CHECK-NEXT: Inlinee: foo (0x1004) +; CHECK-NEXT: FileID: 0x0 +; CHECK-NEXT: SourceLineNum: 1 +; CHECK-NEXT: ExtraFileCount: 2 +; CHECK-NEXT: ExtraFiles [ +; CHECK-NEXT: FileID: 0x18 +; CHECK-NEXT: FileID: 0x30 +; CHECK-NEXT: ] +; CHECK-NEXT: } diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index e521c3a8fa5..b600fa63261 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -25,6 +25,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" @@ -91,6 +92,8 @@ private: const SectionRef &Section, StringRef SectionContents); + void printCodeViewInlineeLines(StringRef Subsection); + void printMemberAttributes(MemberAttributes Attrs); void printRelocatedField(StringRef Label, const coff_section *Sec, @@ -991,6 +994,11 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, case ModuleSubstreamKind::Symbols: printCodeViewSymbolsSubsection(Contents, Section, SectionContents); break; + + case ModuleSubstreamKind::InlineeLines: + printCodeViewInlineeLines(Contents); + break; + case ModuleSubstreamKind::Lines: { // 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 @@ -1685,6 +1693,34 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, } } +void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) { + StringRef Data = Subsection; + uint32_t Signature; + error(consumeUInt32(Data, Signature)); + bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles); + + while (!Data.empty()) { + const InlineeSourceLine *ISL; + error(consumeObject(Data, ISL)); + DictScope S(W, "InlineeSourceLine"); + printTypeIndex("Inlinee", ISL->Inlinee); + W.printHex("FileID", ISL->FileID); + W.printNumber("SourceLineNum", ISL->SourceLineNum); + + if (HasExtraFiles) { + uint32_t ExtraFileCount; + error(consumeUInt32(Data, ExtraFileCount)); + W.printNumber("ExtraFileCount", ExtraFileCount); + ListScope ExtraFiles(W, "ExtraFiles"); + for (unsigned I = 0; I < ExtraFileCount; ++I) { + uint32_t FileID; + error(consumeUInt32(Data, FileID)); + W.printHex("FileID", FileID); + } + } + } +} + StringRef getRemainingTypeBytes(const TypeRecordPrefix *Rec, const char *Start) { ptrdiff_t StartOffset = Start - reinterpret_cast(Rec); size_t RecSize = Rec->Len + 2;