llvm.org GIT mirror llvm / 4c78c0e
[CodeView] Write CodeView line information. Differential Revision: https://reviews.llvm.org/D32716 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301882 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
24 changed file(s) with 526 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
1010 #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFILECHECKSUMFRAGMENT_H
1111
1212 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/DenseMap.h"
1314 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
15 #include "llvm/Support/Allocator.h"
1416 #include "llvm/Support/BinaryStreamArray.h"
1517 #include "llvm/Support/BinaryStreamReader.h"
1618 #include "llvm/Support/Endian.h"
6062 private:
6163 FileChecksumArray Checksums;
6264 };
65
66 class ModuleDebugFileChecksumFragment final : public ModuleDebugFragment {
67 public:
68 ModuleDebugFileChecksumFragment();
69
70 static bool classof(const ModuleDebugFragment *S) {
71 return S->kind() == ModuleDebugFragmentKind::FileChecksums;
72 }
73
74 void addChecksum(uint32_t StringTableOffset, FileChecksumKind Kind,
75 ArrayRef Bytes);
76
77 uint32_t calculateSerializedLength() override;
78 Error commit(BinaryStreamWriter &Writer) override;
79 uint32_t mapChecksumOffset(uint32_t StringTableOffset) const;
80
81 private:
82 DenseMap OffsetMap;
83 uint32_t SerializedSize = 0;
84 llvm::BumpPtrAllocator Storage;
85 std::vector Checksums;
86 };
6387 }
6488 }
6589
1010 #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H
1111
1212 #include "llvm/DebugInfo/CodeView/CodeView.h"
13 #include "llvm/Support/BinaryStreamWriter.h"
1314 #include "llvm/Support/Casting.h"
1415
1516 namespace llvm {
2627 ModuleDebugFragmentKind Kind;
2728 };
2829
30 class ModuleDebugFragment {
31 public:
32 explicit ModuleDebugFragment(ModuleDebugFragmentKind Kind) : Kind(Kind) {}
33 virtual ~ModuleDebugFragment();
34
35 ModuleDebugFragmentKind kind() const { return Kind; }
36
37 virtual Error commit(BinaryStreamWriter &Writer) = 0;
38 virtual uint32_t calculateSerializedLength() = 0;
39
40 protected:
41 ModuleDebugFragmentKind Kind;
42 };
43
2944 } // namespace codeview
3045 } // namespace llvm
3146
1212 #include "llvm/DebugInfo/CodeView/CodeView.h"
1313 #include "llvm/Support/BinaryStreamArray.h"
1414 #include "llvm/Support/BinaryStreamRef.h"
15 #include "llvm/Support/BinaryStreamWriter.h"
1516 #include "llvm/Support/Endian.h"
1617 #include "llvm/Support/Error.h"
1718
1819 namespace llvm {
1920 namespace codeview {
21
22 class ModuleDebugFragment;
2023
2124 // Corresponds to the `CV_DebugSSubsectionHeader_t` structure.
2225 struct ModuleDebugFragmentHeader {
3134
3235 static Error initialize(BinaryStreamRef Stream,
3336 ModuleDebugFragmentRecord &Info);
37
3438 uint32_t getRecordLength() const;
3539 ModuleDebugFragmentKind kind() const;
3640 BinaryStreamRef getRecordData() const;
3842 private:
3943 ModuleDebugFragmentKind Kind;
4044 BinaryStreamRef Data;
45 };
46
47 class ModuleDebugFragmentRecordBuilder {
48 public:
49 ModuleDebugFragmentRecordBuilder(ModuleDebugFragmentKind Kind,
50 ModuleDebugFragment &Frag);
51 uint32_t calculateSerializedLength();
52 Error commit(BinaryStreamWriter &Writer);
53
54 private:
55 ModuleDebugFragmentKind Kind;
56 ModuleDebugFragment &Frag;
4157 };
4258
4359 typedef VarStreamArray ModuleDebugFragmentArray;
99 #ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
1010 #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
1111
12 #include "llvm/DebugInfo/CodeView/Line.h"
1213 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
1314 #include "llvm/Support/BinaryStreamArray.h"
1415 #include "llvm/Support/BinaryStreamReader.h"
2728
2829 // Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
2930 struct LineBlockFragmentHeader {
30 support::ulittle32_t NameIndex; // Index in DBI name buffer of filename.
31 support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File
32 // checksums buffer. The checksum entry then
33 // contains another offset into the string
34 // table of the actual name.
3135 support::ulittle32_t NumLines; // Number of lines
3236 support::ulittle32_t BlockSize; // Code size of block, in bytes.
3337 // The following two variable length arrays appear immediately after the
8791 const LineFragmentHeader *Header = nullptr;
8892 LineInfoArray LinesAndColumns;
8993 };
94
95 class ModuleDebugLineFragment final : public ModuleDebugFragment {
96 struct Block {
97 Block(uint32_t ChecksumBufferOffset)
98 : ChecksumBufferOffset(ChecksumBufferOffset) {}
99
100 uint32_t ChecksumBufferOffset;
101 std::vector Lines;
102 std::vector Columns;
103 };
104
105 public:
106 ModuleDebugLineFragment();
107
108 static bool classof(const ModuleDebugFragment *S) {
109 return S->kind() == ModuleDebugFragmentKind::Lines;
110 }
111
112 void createBlock(uint32_t ChecksumBufferOffset);
113 void addLineInfo(uint32_t Offset, const LineInfo &Line);
114 void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line,
115 uint32_t ColStart, uint32_t ColEnd);
116
117 uint32_t calculateSerializedLength() override;
118 Error commit(BinaryStreamWriter &Writer) override;
119
120 void setRelocationAddress(uint16_t Segment, uint16_t Offset);
121 void setCodeSize(uint32_t Size);
122 void setFlags(LineFlags Flags);
123
124 bool hasColumnInfo() const;
125
126 private:
127 uint16_t RelocOffset = 0;
128 uint16_t RelocSegment = 0;
129 uint32_t CodeSize = 0;
130 LineFlags Flags = LF_None;
131 std::vector Blocks;
132 };
90133 }
91134 }
92135
3434 StringRef getTypeName(TypeIndex Index) const;
3535
3636 const CVType &getTypeRecord(TypeIndex Index) const;
37 CVType &getTypeRecord(TypeIndex Index);
3738
3839 bool containsTypeIndex(TypeIndex Index) const;
3940
1010 #define LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTORBUILDER_H
1111
1212 #include "llvm/ADT/StringRef.h"
13 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
14 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
1315 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1416 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
1517 #include "llvm/Support/Error.h"
1921
2022 namespace llvm {
2123 class BinaryStreamWriter;
24
25 namespace codeview {
26 class ModuleDebugFragmentRecordBuilder;
27 }
2228
2329 namespace msf {
2430 class MSFBuilder;
3238 public:
3339 DbiModuleDescriptorBuilder(StringRef ModuleName, uint32_t ModIndex,
3440 msf::MSFBuilder &Msf);
41 ~DbiModuleDescriptorBuilder();
3542
3643 DbiModuleDescriptorBuilder(const DbiModuleDescriptorBuilder &) = delete;
3744 DbiModuleDescriptorBuilder &
3946
4047 void setObjFileName(StringRef Name);
4148 void addSymbol(codeview::CVSymbol Symbol);
49
50 void
51 addC13LineFragment(std::unique_ptr Lines);
52 void setC13FileChecksums(
53 std::unique_ptr Checksums);
4254
4355 uint16_t getStreamIndex() const;
4456 StringRef getModuleName() const { return ModuleName; }
5769 WritableBinaryStreamRef MsfBuffer);
5870
5971 private:
72 uint32_t calculateC13DebugInfoSize() const;
73
6074 void addSourceFile(StringRef Path);
6175 msf::MSFBuilder &MSF;
6276
6579 std::string ObjFileName;
6680 std::vector SourceFiles;
6781 std::vector Symbols;
82 std::vector> LineInfo;
83 std::unique_ptr ChecksumInfo;
84
85 std::vector>
86 C13Builders;
87
6888 ModuleInfoHeader Layout;
6989 };
7090
5858
5959 Expected addModuleInfo(StringRef ModuleName);
6060 Error addModuleSourceFile(StringRef Module, StringRef File);
61 Expected getSourceFileNameIndex(StringRef FileName);
6162
6263 Error finalizeMsfLayout();
6364
2828 // If string S does not exist in the string table, insert it.
2929 // Returns the ID for S.
3030 uint32_t insert(StringRef S);
31 uint32_t getStringIndex(StringRef S);
3132
3233 uint32_t finalize();
3334 Error commit(BinaryStreamWriter &Writer) const;
4747
4848 return Error::success();
4949 }
50
51 ModuleDebugFileChecksumFragment::ModuleDebugFileChecksumFragment()
52 : ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums) {}
53
54 void ModuleDebugFileChecksumFragment::addChecksum(uint32_t StringTableOffset,
55 FileChecksumKind Kind,
56 ArrayRef Bytes) {
57 FileChecksumEntry Entry;
58 if (!Bytes.empty()) {
59 uint8_t *Copy = Storage.Allocate(Bytes.size());
60 ::memcpy(Copy, Bytes.data(), Bytes.size());
61 Entry.Checksum = makeArrayRef(Copy, Bytes.size());
62 }
63 Entry.FileNameOffset = StringTableOffset;
64 Entry.Kind = Kind;
65 Checksums.push_back(Entry);
66
67 // This maps the offset of this string in the string table to the offset
68 // of this checksum entry in the checksum buffer.
69 OffsetMap[StringTableOffset] = SerializedSize;
70 SerializedSize += sizeof(FileChecksumEntryHeader) + Bytes.size();
71 }
72
73 uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() {
74 return SerializedSize;
75 }
76
77 Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) {
78 for (const auto &FC : Checksums) {
79 FileChecksumEntryHeader Header;
80 Header.ChecksumKind = uint8_t(FC.Kind);
81 Header.ChecksumSize = FC.Checksum.size();
82 Header.FileNameOffset = FC.FileNameOffset;
83 if (auto EC = Writer.writeObject(Header))
84 return EC;
85 if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
86 return EC;
87 }
88 return Error::success();
89 }
90
91 uint32_t ModuleDebugFileChecksumFragment::mapChecksumOffset(
92 uint32_t StringTableOffset) const {
93 auto Iter = OffsetMap.find(StringTableOffset);
94 assert(Iter != OffsetMap.end());
95 return Iter->second;
96 }
1111 using namespace llvm::codeview;
1212
1313 ModuleDebugFragmentRef::~ModuleDebugFragmentRef() {}
14
15 ModuleDebugFragment::~ModuleDebugFragment() {}
77 //===----------------------------------------------------------------------===//
88
99 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
10 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
1011
1112 #include "llvm/Support/BinaryStreamReader.h"
1213
2930
3031 ModuleDebugFragmentKind Kind =
3132 static_cast(uint32_t(Header->Kind));
33 switch (Kind) {
34 case ModuleDebugFragmentKind::FileChecksums:
35 case ModuleDebugFragmentKind::Lines:
36 break;
37 default:
38 llvm_unreachable("Unexpected debug fragment kind!");
39 }
3240 if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
3341 return EC;
3442 Info.Kind = Kind;
3644 }
3745
3846 uint32_t ModuleDebugFragmentRecord::getRecordLength() const {
39 return sizeof(ModuleDebugFragmentHeader) + Data.getLength();
47 uint32_t Result = sizeof(ModuleDebugFragmentHeader) + Data.getLength();
48 assert(Result % 4 == 0);
49 return Result;
4050 }
4151
4252 ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; }
4454 BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const {
4555 return Data;
4656 }
57
58 ModuleDebugFragmentRecordBuilder::ModuleDebugFragmentRecordBuilder(
59 ModuleDebugFragmentKind Kind, ModuleDebugFragment &Frag)
60 : Kind(Kind), Frag(Frag) {}
61
62 uint32_t ModuleDebugFragmentRecordBuilder::calculateSerializedLength() {
63 uint32_t Size = sizeof(ModuleDebugFragmentHeader) +
64 alignTo(Frag.calculateSerializedLength(), 4);
65 return Size;
66 }
67
68 Error ModuleDebugFragmentRecordBuilder::commit(BinaryStreamWriter &Writer) {
69 ModuleDebugFragmentHeader Header;
70 Header.Kind = uint32_t(Kind);
71 Header.Length =
72 calculateSerializedLength() - sizeof(ModuleDebugFragmentHeader);
73
74 if (auto EC = Writer.writeObject(Header))
75 return EC;
76 if (auto EC = Frag.commit(Writer))
77 return EC;
78 if (auto EC = Writer.padToAlignment(4))
79 return EC;
80
81 return Error::success();
82 }
6363 bool ModuleDebugLineFragmentRef::hasColumnInfo() const {
6464 return !!(Header->Flags & LF_HaveColumns);
6565 }
66
67 ModuleDebugLineFragment::ModuleDebugLineFragment()
68 : ModuleDebugFragment(ModuleDebugFragmentKind::Lines) {}
69
70 void ModuleDebugLineFragment::createBlock(uint32_t ChecksumBufferOffset) {
71 Blocks.emplace_back(ChecksumBufferOffset);
72 }
73
74 void ModuleDebugLineFragment::addLineInfo(uint32_t Offset,
75 const LineInfo &Line) {
76 Block &B = Blocks.back();
77 LineNumberEntry LNE;
78 LNE.Flags = Line.getRawData();
79 LNE.Offset = Offset;
80 B.Lines.push_back(LNE);
81 }
82
83 void ModuleDebugLineFragment::addLineAndColumnInfo(uint32_t Offset,
84 const LineInfo &Line,
85 uint32_t ColStart,
86 uint32_t ColEnd) {
87 Block &B = Blocks.back();
88 assert(B.Lines.size() == B.Columns.size());
89
90 addLineInfo(Offset, Line);
91 ColumnNumberEntry CNE;
92 CNE.StartColumn = ColStart;
93 CNE.EndColumn = ColEnd;
94 B.Columns.push_back(CNE);
95 }
96
97 Error ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) {
98 LineFragmentHeader Header;
99 Header.CodeSize = CodeSize;
100 Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0;
101 Header.RelocOffset = RelocOffset;
102 Header.RelocSegment = RelocSegment;
103
104 if (auto EC = Writer.writeObject(Header))
105 return EC;
106
107 for (const auto &B : Blocks) {
108 LineBlockFragmentHeader BlockHeader;
109 assert(B.Lines.size() == B.Columns.size() || B.Columns.empty());
110
111 BlockHeader.NumLines = B.Lines.size();
112 BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader);
113 BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry);
114 if (hasColumnInfo())
115 BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry);
116 BlockHeader.NameIndex = B.ChecksumBufferOffset;
117 if (auto EC = Writer.writeObject(BlockHeader))
118 return EC;
119
120 if (auto EC = Writer.writeArray(makeArrayRef(B.Lines)))
121 return EC;
122
123 if (hasColumnInfo()) {
124 if (auto EC = Writer.writeArray(makeArrayRef(B.Columns)))
125 return EC;
126 }
127 }
128 return Error::success();
129 }
130
131 uint32_t ModuleDebugLineFragment::calculateSerializedLength() {
132 uint32_t Size = sizeof(LineFragmentHeader);
133 for (const auto &B : Blocks) {
134 Size += sizeof(LineBlockFragmentHeader);
135 Size += B.Lines.size() * sizeof(LineNumberEntry);
136 if (hasColumnInfo())
137 Size += B.Columns.size() * sizeof(ColumnNumberEntry);
138 }
139 return Size;
140 }
141
142 void ModuleDebugLineFragment::setRelocationAddress(uint16_t Segment,
143 uint16_t Offset) {
144 RelocOffset = Offset;
145 RelocSegment = Segment;
146 }
147
148 void ModuleDebugLineFragment::setCodeSize(uint32_t Size) { CodeSize = Size; }
149
150 void ModuleDebugLineFragment::setFlags(LineFlags Flags) { this->Flags = Flags; }
151
152 bool ModuleDebugLineFragment::hasColumnInfo() const {
153 return Flags & LF_HaveColumns;
154 }
109109 return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
110110 }
111111
112 CVType &TypeDatabase::getTypeRecord(TypeIndex Index) {
113 return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
114 }
115
112116 bool TypeDatabase::containsTypeIndex(TypeIndex Index) const {
113117 uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
114118 return I < CVUDTNames.size();
99 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
1010
1111 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
1213 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
1314 #include "llvm/DebugInfo/MSF/MSFCommon.h"
1415 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
3435 };
3536 }
3637
37 static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize) {
38 static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
39 uint32_t C13Size) {
3840 uint32_t Size = sizeof(uint32_t); // Signature
3941 Size += SymbolByteSize; // Symbol Data
40 Size += 0; // TODO: Layout.LineBytes
41 Size += 0; // TODO: Layout.C13Bytes
42 Size += 0; // TODO: Layout.C11Bytes
43 Size += C13Size; // C13 Debug Info Size
4244 Size += sizeof(uint32_t); // GlobalRefs substream size (always 0)
4345 Size += 0; // GlobalRefs substream bytes
4446 return Size;
5052 : MSF(Msf), ModuleName(ModuleName) {
5153 Layout.Mod = ModIndex;
5254 }
55
56 DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
5357
5458 uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
5559 return Layout.ModDiStream;
6872 SourceFiles.push_back(Path);
6973 }
7074
75 uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
76 uint32_t Result = 0;
77 for (const auto &Builder : C13Builders) {
78 assert(Builder && "Empty C13 Fragment Builder!");
79 Result += Builder->calculateSerializedLength();
80 }
81 return Result;
82 }
83
7184 uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
7285 uint32_t L = sizeof(Layout);
7386 uint32_t M = ModuleName.size() + 1;
7992 Layout.FileNameOffs = 0; // TODO: Fix this
8093 Layout.Flags = 0; // TODO: Fix this
8194 Layout.C11Bytes = 0;
82 Layout.C13Bytes = 0;
95 Layout.C13Bytes = calculateC13DebugInfoSize();
8396 (void)Layout.Mod; // Set in constructor
8497 (void)Layout.ModDiStream; // Set in finalizeMsfLayout
8598 Layout.NumFiles = SourceFiles.size();
93106
94107 Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
95108 this->Layout.ModDiStream = kInvalidStreamIndex;
96 auto ExpectedSN = MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize));
109 uint32_t C13Size = calculateC13DebugInfoSize();
110 auto ExpectedSN =
111 MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
97112 if (!ExpectedSN)
98113 return ExpectedSN.takeError();
99114 Layout.ModDiStream = *ExpectedSN;
129144 if (auto EC = SymbolWriter.writeStreamRef(RecordsRef))
130145 return EC;
131146 // TODO: Write C11 Line data
132 // TODO: Write C13 Line data
147
148 for (const auto &Builder : C13Builders) {
149 assert(Builder && "Empty C13 Fragment Builder!");
150 if (auto EC = Builder->commit(SymbolWriter))
151 return EC;
152 }
153
133154 // TODO: Figure out what GlobalRefs substream actually is and populate it.
134155 if (auto EC = SymbolWriter.writeInteger(0))
135156 return EC;
138159 }
139160 return Error::success();
140161 }
162
163 void DbiModuleDescriptorBuilder::addC13LineFragment(
164 std::unique_ptr Lines) {
165 ModuleDebugLineFragment &Frag = *Lines;
166
167 // File Checksums have to come first, so push an empty entry on if this
168 // is the first.
169 if (C13Builders.empty())
170 C13Builders.push_back(nullptr);
171
172 this->LineInfo.push_back(std::move(Lines));
173 C13Builders.push_back(
174 llvm::make_unique(Frag.kind(), Frag));
175 }
176
177 void DbiModuleDescriptorBuilder::setC13FileChecksums(
178 std::unique_ptr Checksums) {
179 assert(!ChecksumInfo && "Can't have more than one checksum info!");
180
181 if (C13Builders.empty())
182 C13Builders.push_back(nullptr);
183
184 ChecksumInfo = std::move(Checksums);
185 C13Builders[0] = llvm::make_unique(
186 ChecksumInfo->kind(), *ChecksumInfo);
187 }
9898 auto &ModEntry = *ModIter;
9999 ModEntry.second->addSourceFile(File);
100100 return Error::success();
101 }
102
103 Expected DbiStreamBuilder::getSourceFileNameIndex(StringRef File) {
104 auto NameIter = SourceFileNames.find(File);
105 if (NameIter == SourceFileNames.end())
106 return make_error(raw_error_code::no_entry,
107 "The specified source file was not found");
108 return NameIter->getValue();
101109 }
102110
103111 uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
2626 if (P.second)
2727 StringSize += S.size() + 1; // +1 for '\0'
2828 return P.first->second;
29 }
30
31 uint32_t StringTableBuilder::getStringIndex(StringRef S) {
32 auto Iter = Strings.find(S);
33 assert(Iter != Strings.end());
34 return Iter->second;
2935 }
3036
3137 static uint32_t computeBucketCount(uint32_t NumStrings) {
0 ---
1 StringTable:
2 - 'junk_a'
3 - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
4 - 'junk_b'
5 DbiStream:
6 Modules:
7 - Module: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
8 ObjFile: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
9 SourceFiles:
10 - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
11 LineInfo:
12 Checksums:
13 - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
14 Kind: MD5
15 Checksum: A0A5BD0D3ECD93FC29D19DE826FBF4BC
16 Lines:
17 - CodeSize: 10
18 Flags: [ ]
19 RelocOffset: 16
20 RelocSegment: 1
21 Blocks:
22 - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
23 Lines:
24 - Offset: 0
25 LineStart: 5
26 IsStatement: true
27 EndDelta: 0
28 - Offset: 3
29 LineStart: 6
30 IsStatement: true
31 EndDelta: 0
32 - Offset: 8
33 LineStart: 7
34 IsStatement: true
35 EndDelta: 0
36 Columns:
37 ...
494494 ; EMPTY-NEXT: }
495495 ; EMPTY-NEXT: }
496496 ; EMPTY-NEXT: Lines {
497 ; EMPTY-NEXT: LineFragment {
497 ; EMPTY-NEXT: Block {
498498 ; EMPTY-NEXT: RelocSegment: 1
499499 ; EMPTY-NEXT: RelocOffset: 16
500500 ; EMPTY-NEXT: CodeSize: 10
501 ; EMPTY-NEXT: HasColumns: 0
501 ; EMPTY-NEXT: HasColumns: No
502502 ; EMPTY-NEXT: Lines {
503503 ; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
504504 ; EMPTY-NEXT: Line {
0 ; This testcase verifies that we can produce a PDB with line
1 ; information. It does this by describing some line information
2 ; manually in YAML, creating a PDB out of it, then dumping then
3 ; line information from the resulting PDB.
4
5 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/simple-line-info.yaml
6 ; RUN: llvm-pdbdump raw -line-info %t.pdb | FileCheck -check-prefix=LINES %s
7
8 LINES: Modules [
9 LINES-NEXT: {
10 LINES-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
11 LINES: LineInfo [
12 LINES-NEXT: FileChecksums {
13 LINES-NEXT: Checksum {
14 LINES-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
15 LINES-NEXT: Kind: MD5 (0x1)
16 LINES-NEXT: Checksum (
17 LINES-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
18 LINES-NEXT: )
19 LINES-NEXT: }
20 LINES-NEXT: }
21 LINES-NEXT: Lines {
22 LINES-NEXT: Block {
23 LINES-NEXT: RelocSegment: 1
24 LINES-NEXT: RelocOffset: 16
25 LINES-NEXT: CodeSize: 10
26 LINES-NEXT: HasColumns: No
27 LINES-NEXT: Lines {
28 LINES-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
29 LINES-NEXT: Line {
30 LINES-NEXT: Offset: 0
31 LINES-NEXT: LineNumberStart: 5
32 LINES-NEXT: EndDelta: 0
33 LINES-NEXT: IsStatement: Yes
34 LINES-NEXT: }
35 LINES-NEXT: Line {
36 LINES-NEXT: Offset: 3
37 LINES-NEXT: LineNumberStart: 6
38 LINES-NEXT: EndDelta: 0
39 LINES-NEXT: IsStatement: Yes
40 LINES-NEXT: }
41 LINES-NEXT: Line {
42 LINES-NEXT: Offset: 8
43 LINES-NEXT: LineNumberStart: 7
44 LINES-NEXT: EndDelta: 0
45 LINES-NEXT: IsStatement: Yes
46 LINES-NEXT: }
47 LINES-NEXT: }
48 LINES-NEXT: }
49 LINES-NEXT: }
50 LINES-NEXT: ]
51 LINES-NEXT: }
8888 DictScope DD(P, "Lines");
8989
9090 for (const auto &Fragment : Lines) {
91 DictScope DDD(P, "LineFragment");
91 DictScope DDD(P, "Block");
9292 P.printNumber("RelocSegment", Fragment.header()->RelocSegment);
9393 P.printNumber("RelocOffset", Fragment.header()->RelocOffset);
9494 P.printNumber("CodeSize", Fragment.header()->CodeSize);
95 P.printNumber("HasColumns", Fragment.hasColumnInfo());
95 P.printBoolean("HasColumns", Fragment.hasColumnInfo());
9696
9797 for (const auto &L : Fragment) {
9898 DictScope DDDD(P, "Lines");
556556
557557 bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash;
558558 if (IsSilentDatabaseBuild) {
559 outs().flush();
559560 errs() << "Building Type Information For " << Label << "\n";
560561 }
561562
285285 continue;
286286
287287 auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
288 File.getMsfLayout(), File.getMsfBuffer(),
289 MI.Info.getModuleStreamIndex());
288 File.getMsfLayout(), File.getMsfBuffer(), ModiStream);
290289
291290 pdb::ModuleDebugStreamRef ModS(MI.Info, std::move(ModStreamData));
292291 if (auto EC = ModS.reload())
2727 #include "llvm/ADT/ArrayRef.h"
2828 #include "llvm/ADT/BitVector.h"
2929 #include "llvm/ADT/DenseMap.h"
30 #include "llvm/ADT/STLExtras.h"
3031 #include "llvm/ADT/StringExtras.h"
3132 #include "llvm/Config/config.h"
3233 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
490491 for (auto Symbol : ModiStream.Symbols)
491492 ModiBuilder.addSymbol(Symbol.Record);
492493 }
494 if (MI.FileLineInfo.hasValue()) {
495 const auto &FLI = *MI.FileLineInfo;
496
497 // File Checksums must be emitted before line information, because line
498 // info records use offsets into the checksum buffer to reference a file's
499 // source file name.
500 auto Checksums = llvm::make_unique();
501 auto &ChecksumRef = *Checksums;
502 if (!FLI.FileChecksums.empty()) {
503 auto &Strings = Builder.getStringTableBuilder();
504 for (auto &FC : FLI.FileChecksums) {
505 uint32_t STOffset = Strings.getStringIndex(FC.FileName);
506 Checksums->addChecksum(STOffset, FC.Kind, FC.ChecksumBytes.Bytes);
507 }
508 }
509 ModiBuilder.setC13FileChecksums(std::move(Checksums));
510
511 for (const auto &Fragment : FLI.LineFragments) {
512 auto Lines = llvm::make_unique();
513 Lines->setCodeSize(Fragment.CodeSize);
514 Lines->setRelocationAddress(Fragment.RelocSegment,
515 Fragment.RelocOffset);
516 Lines->setFlags(Fragment.Flags);
517 for (const auto &LC : Fragment.Blocks) {
518 // FIXME: StringTable / StringTableBuilder should really be in
519 // DebugInfoCodeView. This would allow us to construct the
520 // ModuleDebugLineFragment with a reference to the string table,
521 // and we could just pass strings around rather than having to
522 // remember how to calculate the right offset.
523 auto &Strings = Builder.getStringTableBuilder();
524 // The offset in the line info record is the offset of the checksum
525 // entry for the corresponding file. That entry then contains an
526 // offset into the global string table of the file name. So to
527 // compute the proper offset to write into the line info record, we
528 // must first get its offset in the global string table, then ask the
529 // checksum builder to find the offset in its serialized buffer that
530 // it mapped that filename string table offset to.
531 uint32_t StringOffset = Strings.getStringIndex(LC.FileName);
532 uint32_t ChecksumOffset = ChecksumRef.mapChecksumOffset(StringOffset);
533
534 Lines->createBlock(ChecksumOffset);
535 if (Lines->hasColumnInfo()) {
536 for (const auto &Item : zip(LC.Lines, LC.Columns)) {
537 auto &L = std::get<0>(Item);
538 auto &C = std::get<1>(Item);
539 uint32_t LE = L.LineStart + L.EndDelta;
540 Lines->addLineAndColumnInfo(
541 L.Offset, LineInfo(L.LineStart, LE, L.IsStatement),
542 C.StartColumn, C.EndColumn);
543 }
544 } else {
545 for (const auto &L : LC.Lines) {
546 uint32_t LE = L.LineStart + L.EndDelta;
547 Lines->addLineInfo(L.Offset,
548 LineInfo(L.LineStart, LE, L.IsStatement));
549 }
550 }
551 }
552 ModiBuilder.addC13LineFragment(std::move(Lines));
553 }
554 }
493555 }
494556
495557 auto &TpiBuilder = Builder.getTpiBuilder();