llvm.org GIT mirror llvm / 3796a45
Re-land "Fix Bug 30978 by emitting cv file checksums." This reverts r313431 and brings back r313374 with a fix to write checksums as binary data and not ASCII hex strings. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313657 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 1 year, 11 months ago
16 changed file(s) with 309 addition(s) and 85 deletion(s). Raw diff Collapse all Expand all
472472 friend class MDNode;
473473
474474 public:
475 // These values must be explictly set, as they end up in the final object
476 // file.
475477 enum ChecksumKind {
476 CSK_None,
477 CSK_MD5,
478 CSK_SHA1,
478 CSK_None = 0,
479 CSK_MD5 = 1,
480 CSK_SHA1 = 2,
479481 CSK_Last = CSK_SHA1 // Should be last enumeration.
480482 };
481483
509511 ChecksumKind CSK = CSK_None,
510512 StringRef CS = StringRef()),
511513 (Filename, Directory, CSK, CS))
512 DEFINE_MDNODE_GET(DIFile, (MDString *Filename, MDString *Directory,
514 DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory,
513515 ChecksumKind CSK = CSK_None,
514516 MDString *CS = nullptr),
515517 (Filename, Directory, CSK, CS))
160160 ~CodeViewContext();
161161
162162 bool isValidFileNumber(unsigned FileNumber) const;
163 bool addFile(unsigned FileNumber, StringRef Filename);
164 ArrayRef getFilenames() { return Filenames; }
163 bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,
164 ArrayRef ChecksumBytes, uint8_t ChecksumKind);
165165
166166 /// Records the function id of a normal function. Returns false if the
167167 /// function id has already been used, and true otherwise.
272272 /// Emits the file checksum substream.
273273 void emitFileChecksums(MCObjectStreamer &OS);
274274
275 /// Emits the offset into the checksum table of the given file number.
276 void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo);
277
275278 private:
276279 /// The current CodeView line information from the last .cv_loc directive.
277280 MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true);
286289
287290 MCDataFragment *getStringTableFragment();
288291
289 /// Add something to the string table.
290 StringRef addToStringTable(StringRef S);
292 /// Add something to the string table. Returns the final string as well as
293 /// offset into the string table.
294 std::pair addToStringTable(StringRef S);
291295
292296 /// Get a string table offset.
293297 unsigned getStringTableOffset(StringRef S);
294298
295 /// An array of absolute paths. Eventually this may include the file checksum.
296 SmallVector Filenames;
299 struct FileInfo {
300 unsigned StringTableOffset;
301
302 // Indicates if this FileInfo corresponds to an actual file, or hasn't been
303 // set yet.
304 bool Assigned = false;
305
306 uint8_t ChecksumKind;
307
308 ArrayRef Checksum;
309
310 // Checksum offset stored as a symbol because it might be requested
311 // before it has been calculated, so a fixup may be needed.
312 MCSymbol *ChecksumTableOffset;
313 };
314
315 /// Array storing added file information.
316 SmallVector Files;
297317
298318 /// The offset of the first and last .cv_loc directive for a given function
299319 /// id.
304324
305325 /// All known functions and inlined call sites, indexed by function id.
306326 std::vector Functions;
327
328 /// Indicate whether we have already laid out the checksum table addresses or
329 /// not.
330 bool ChecksumOffsetsAssigned = false;
307331 };
308332
309333 } // end namespace llvm
139139 StringRef FixedSizePortion) override;
140140 void EmitCVStringTableDirective() override;
141141 void EmitCVFileChecksumsDirective() override;
142 void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
142143 void EmitDTPRel32Value(const MCExpr *Value) override;
143144 void EmitDTPRel64Value(const MCExpr *Value) override;
144145 void EmitTPRel32Value(const MCExpr *Value) override;
732732 unsigned Isa, unsigned Discriminator,
733733 StringRef FileName);
734734
735 /// \brief Associate a filename with a specified logical file number. This
736 /// implements the '.cv_file 4 "foo.c"' assembler directive. Returns true on
737 /// success.
738 virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename);
735 /// Associate a filename with a specified logical file number, and also
736 /// specify that file's checksum information. This implements the '.cv_file 4
737 /// "foo.c"' assembler directive. Returns true on success.
738 virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
739 ArrayRef Checksum,
740 unsigned ChecksumKind);
739741
740742 /// \brief Introduces a function id for use with .cv_loc.
741743 virtual bool EmitCVFuncIdDirective(unsigned FunctionId);
776778
777779 /// \brief This implements the CodeView '.cv_filechecksums' assembler directive.
778780 virtual void EmitCVFileChecksumsDirective() {}
781
782 /// This implements the CodeView '.cv_filechecksumoffset' assembler
783 /// directive.
784 virtual void EmitCVFileChecksumOffsetDirective(unsigned FileNo) {}
779785
780786 /// Emit the absolute difference between two symbols.
781787 ///
158158 if (Insertion.second) {
159159 // We have to compute the full filepath and emit a .cv_file directive.
160160 StringRef FullPath = getFullFilepath(F);
161 bool Success = OS.EmitCVFileDirective(NextId, FullPath);
161 std::string Checksum = fromHex(F->getChecksum());
162 void *CKMem = OS.getContext().allocate(Checksum.size(), 1);
163 memcpy(CKMem, Checksum.data(), Checksum.size());
164 ArrayRef ChecksumAsBytes(reinterpret_cast(CKMem),
165 Checksum.size());
166 DIFile::ChecksumKind ChecksumKind = F->getChecksumKind();
167 bool Success = OS.EmitCVFileDirective(NextId, FullPath, ChecksumAsBytes,
168 static_cast(ChecksumKind));
162169 (void)Success;
163170 assert(Success && ".cv_file directive failed");
164171 }
680687 OS.AddComment("Inlinee lines subsection");
681688 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
682689
683 // We don't provide any extra file info.
684 // FIXME: Find out if debuggers use this info.
690 // We emit the checksum info for files. This is used by debuggers to
691 // determine if a pdb matches the source before loading it. Visual Studio,
692 // for instance, will display a warning that the breakpoints are not valid if
693 // the pdb does not match the source.
685694 OS.AddComment("Inlinee lines signature");
686695 OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4);
687696
694703 OS.AddComment("Inlined function " + SP->getName() + " starts at " +
695704 SP->getFilename() + Twine(':') + Twine(SP->getLine()));
696705 OS.AddBlankLine();
697 // The filechecksum table uses 8 byte entries for now, and file ids start at
698 // 1.
699 unsigned FileOffset = (FileId - 1) * 8;
700706 OS.AddComment("Type index of inlined function");
701707 OS.EmitIntValue(InlineeIdx.getIndex(), 4);
702708 OS.AddComment("Offset into filechecksum table");
703 OS.EmitIntValue(FileOffset, 4);
709 OS.EmitCVFileChecksumOffsetDirective(FileId);
704710 OS.AddComment("Starting line number");
705711 OS.EmitIntValue(SP->getLine(), 4);
706712 }
353353 DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
354354 }
355355
356 // FIXME: Implement this string-enum correspondence with a .def file and macros,
357 // so that the association is explicit rather than implied.
356358 static const char *ChecksumKindName[DIFile::CSK_Last + 1] = {
357359 "CSK_None",
358360 "CSK_MD5",
224224 StringRef FileName) override;
225225 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
226226
227 bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
227 bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
228 ArrayRef Checksum,
229 unsigned ChecksumKind) override;
228230 bool EmitCVFuncIdDirective(unsigned FuncId) override;
229231 bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
230232 unsigned IAFile, unsigned IALine,
244246 StringRef FixedSizePortion) override;
245247 void EmitCVStringTableDirective() override;
246248 void EmitCVFileChecksumsDirective() override;
249 void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
247250
248251 void EmitIdent(StringRef IdentString) override;
249252 void EmitCFISections(bool EH, bool Debug) override;
11191122 return MCStreamer::getDwarfLineTableSymbol(0);
11201123 }
11211124
1122 bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
1123 if (!getContext().getCVContext().addFile(FileNo, Filename))
1125 bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
1126 ArrayRef Checksum,
1127 unsigned ChecksumKind) {
1128 if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
1129 ChecksumKind))
11241130 return false;
11251131
11261132 OS << "\t.cv_file\t" << FileNo << ' ';
1127
11281133 PrintQuotedString(Filename, OS);
1134
1135 if (!ChecksumKind) {
1136 EmitEOL();
1137 return true;
1138 }
1139
1140 OS << ' ';
1141 PrintQuotedString(toHex(Checksum), OS);
1142 OS << ' ' << ChecksumKind;
1143
11291144 EmitEOL();
11301145 return true;
11311146 }
12241239
12251240 void MCAsmStreamer::EmitCVFileChecksumsDirective() {
12261241 OS << "\t.cv_filechecksums";
1242 EmitEOL();
1243 }
1244
1245 void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
1246 OS << "\t.cv_filechecksumoffset\t" << FileNo;
12271247 EmitEOL();
12281248 }
12291249
1212
1313 #include "llvm/MC/MCCodeView.h"
1414 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/StringExtras.h"
1516 #include "llvm/BinaryFormat/COFF.h"
1617 #include "llvm/DebugInfo/CodeView/CodeView.h"
1718 #include "llvm/DebugInfo/CodeView/Line.h"
3839 /// for it.
3940 bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
4041 unsigned Idx = FileNumber - 1;
41 if (Idx < Filenames.size())
42 return !Filenames[Idx].empty();
42 if (Idx < Files.size())
43 return Files[Idx].Assigned;
4344 return false;
4445 }
4546
46 bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
47 bool CodeViewContext::addFile(MCStreamer &OS, unsigned FileNumber,
48 StringRef Filename,
49 ArrayRef ChecksumBytes,
50 uint8_t ChecksumKind) {
4751 assert(FileNumber > 0);
48 Filename = addToStringTable(Filename);
52 auto FilenameOffset = addToStringTable(Filename);
53 Filename = FilenameOffset.first;
4954 unsigned Idx = FileNumber - 1;
50 if (Idx >= Filenames.size())
51 Filenames.resize(Idx + 1);
55 if (Idx >= Files.size())
56 Files.resize(Idx + 1);
5257
5358 if (Filename.empty())
5459 Filename = "";
5560
56 if (!Filenames[Idx].empty())
61 if (Files[Idx].Assigned)
5762 return false;
5863
59 // FIXME: We should store the string table offset of the filename, rather than
60 // the filename itself for efficiency.
61 Filename = addToStringTable(Filename);
62
63 Filenames[Idx] = Filename;
64 FilenameOffset = addToStringTable(Filename);
65 Filename = FilenameOffset.first;
66 unsigned Offset = FilenameOffset.second;
67
68 auto ChecksumOffsetSymbol =
69 OS.getContext().createTempSymbol("checksum_offset", false);
70 Files[Idx].StringTableOffset = Offset;
71 Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;
72 Files[Idx].Assigned = true;
73 Files[Idx].Checksum = ChecksumBytes;
74 Files[Idx].ChecksumKind = ChecksumKind;
75
6476 return true;
6577 }
6678
117129 return StrTabFragment;
118130 }
119131
120 StringRef CodeViewContext::addToStringTable(StringRef S) {
132 std::pair CodeViewContext::addToStringTable(StringRef S) {
121133 SmallVectorImpl &Contents = getStringTableFragment()->getContents();
122134 auto Insertion =
123135 StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
124136 // Return the string from the table, since it is stable.
125 S = Insertion.first->first();
137 std::pair Ret =
138 std::make_pair(Insertion.first->first(), Insertion.first->second);
126139 if (Insertion.second) {
127140 // The string map key is always null terminated.
128 Contents.append(S.begin(), S.end() + 1);
129 }
130 return S;
141 Contents.append(Ret.first.begin(), Ret.first.end() + 1);
142 }
143 return Ret;
131144 }
132145
133146 unsigned CodeViewContext::getStringTableOffset(StringRef S) {
164177 void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
165178 // Do nothing if there are no file checksums. Microsoft's linker rejects empty
166179 // CodeView substreams.
167 if (Filenames.empty())
180 if (Files.empty())
168181 return;
169182
170183 MCContext &Ctx = OS.getContext();
175188 OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
176189 OS.EmitLabel(FileBegin);
177190
191 unsigned CurrentOffset = 0;
192
178193 // Emit an array of FileChecksum entries. We index into this table using the
179 // user-provided file number. Each entry is currently 8 bytes, as we don't
180 // emit checksums.
181 for (StringRef Filename : Filenames) {
182 OS.EmitIntValue(getStringTableOffset(Filename), 4);
183 // Zero the next two fields and align back to 4 bytes. This indicates that
184 // no checksum is present.
185 OS.EmitIntValue(0, 4);
194 // user-provided file number. Each entry may be a variable number of bytes
195 // determined by the checksum kind and size.
196 for (auto File : Files) {
197 OS.EmitAssignment(File.ChecksumTableOffset,
198 MCConstantExpr::create(CurrentOffset, Ctx));
199 CurrentOffset += 4; // String table offset.
200 if (!File.ChecksumKind) {
201 CurrentOffset +=
202 4; // One byte each for checksum size and kind, then align to 4 bytes.
203 } else {
204 CurrentOffset += 2; // One byte each for checksum size and kind.
205 CurrentOffset += File.Checksum.size();
206 CurrentOffset = alignTo(CurrentOffset, 4);
207 }
208
209 OS.EmitIntValue(File.StringTableOffset, 4);
210
211 if (!File.ChecksumKind) {
212 // There is no checksum. Therefore zero the next two fields and align
213 // back to 4 bytes.
214 OS.EmitIntValue(0, 4);
215 continue;
216 }
217 OS.EmitIntValue(static_cast(File.Checksum.size()), 1);
218 OS.EmitIntValue(File.ChecksumKind, 1);
219 OS.EmitBytes(toStringRef(File.Checksum));
220 OS.EmitValueToAlignment(4);
186221 }
187222
188223 OS.EmitLabel(FileEnd);
224
225 ChecksumOffsetsAssigned = true;
226 }
227
228 // Output checksum table offset of the given file number. It is possible that
229 // not all files have been registered yet, and so the offset cannot be
230 // calculated. In this case a symbol representing the offset is emitted, and
231 // the value of this symbol will be fixed up at a later time.
232 void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS,
233 unsigned FileNo) {
234 unsigned Idx = FileNo - 1;
235
236 if (Idx >= Files.size())
237 Files.resize(Idx + 1);
238
239 if (ChecksumOffsetsAssigned) {
240 OS.EmitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
241 return;
242 }
243
244 const MCSymbolRefExpr *SRE =
245 MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext());
246
247 OS.EmitValueImpl(SRE, 4);
189248 }
190249
191250 void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
218277 return Loc.getFileNum() != CurFileNum;
219278 });
220279 unsigned EntryCount = FileSegEnd - I;
221 OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) +
222 "' begins");
223 OS.EmitIntValue(8 * (CurFileNum - 1), 4);
280 OS.AddComment(
281 "Segment for file '" +
282 Twine(getStringTableFragment()
283 ->getContents()[Files[CurFileNum - 1].StringTableOffset]) +
284 "' begins");
285 OS.EmitCVFileChecksumOffsetDirective(CurFileNum);
224286 OS.EmitIntValue(EntryCount, 4);
225287 uint32_t SegmentSize = 12;
226288 SegmentSize += 8 * EntryCount;
400462 HaveOpenRange = true;
401463
402464 if (CurSourceLoc.File != LastSourceLoc.File) {
403 // File ids are 1 based, and each file checksum table entry is 8 bytes
404 // long. See emitFileChecksums above.
405 unsigned FileOffset = 8 * (CurSourceLoc.File - 1);
465 unsigned FileOffset = static_cast(
466 Files[CurSourceLoc.File - 1]
467 .ChecksumTableOffset->getVariableValue())
468 ->getValue();
406469 compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
407470 compressAnnotation(FileOffset, Buffer);
408471 }
425425 getContext().getCVContext().emitFileChecksums(*this);
426426 }
427427
428 void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
429 getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
430 }
428431
429432 void MCObjectStreamer::EmitBytes(StringRef Data) {
430433 MCCVLineEntry::Make(this);
1717 #include "llvm/ADT/STLExtras.h"
1818 #include "llvm/ADT/SmallString.h"
1919 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringExtras.h"
2021 #include "llvm/ADT/StringMap.h"
2122 #include "llvm/ADT/StringRef.h"
2223 #include "llvm/ADT/Twine.h"
500501 DK_CV_DEF_RANGE,
501502 DK_CV_STRINGTABLE,
502503 DK_CV_FILECHECKSUMS,
504 DK_CV_FILECHECKSUM_OFFSET,
503505 DK_CFI_SECTIONS,
504506 DK_CFI_STARTPROC,
505507 DK_CFI_ENDPROC,
575577 bool parseDirectiveCVDefRange();
576578 bool parseDirectiveCVStringTable();
577579 bool parseDirectiveCVFileChecksums();
580 bool parseDirectiveCVFileChecksumOffset();
578581
579582 // .cfi directives
580583 bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
20292032 return parseDirectiveCVStringTable();
20302033 case DK_CV_FILECHECKSUMS:
20312034 return parseDirectiveCVFileChecksums();
2035 case DK_CV_FILECHECKSUM_OFFSET:
2036 return parseDirectiveCVFileChecksumOffset();
20322037 case DK_CFI_SECTIONS:
20332038 return parseDirectiveCFISections();
20342039 case DK_CFI_STARTPROC:
34563461 }
34573462
34583463 /// parseDirectiveCVFile
3459 /// ::= .cv_file number filename
3464 /// ::= .cv_file number filename [checksum] [checksumkind]
34603465 bool AsmParser::parseDirectiveCVFile() {
34613466 SMLoc FileNumberLoc = getTok().getLoc();
34623467 int64_t FileNumber;
34633468 std::string Filename;
3469 std::string Checksum;
3470 int64_t ChecksumKind = 0;
34643471
34653472 if (parseIntToken(FileNumber,
34663473 "expected file number in '.cv_file' directive") ||
34673474 check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
34683475 check(getTok().isNot(AsmToken::String),
34693476 "unexpected token in '.cv_file' directive") ||
3470 // Usually directory and filename are together, otherwise just
3471 // directory. Allow the strings to have escaped octal character sequence.
3472 parseEscapedString(Filename) ||
3473 parseToken(AsmToken::EndOfStatement,
3474 "unexpected token in '.cv_file' directive"))
3475 return true;
3476
3477 if (!getStreamer().EmitCVFileDirective(FileNumber, Filename))
3477 parseEscapedString(Filename))
3478 return true;
3479 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3480 if (check(getTok().isNot(AsmToken::String),
3481 "unexpected token in '.cv_file' directive") ||
3482 parseEscapedString(Checksum) ||
3483 parseIntToken(ChecksumKind,
3484 "expected checksum kind in '.cv_file' directive") ||
3485 parseToken(AsmToken::EndOfStatement,
3486 "unexpected token in '.cv_file' directive"))
3487 return true;
3488 }
3489
3490 Checksum = fromHex(Checksum);
3491 void *CKMem = Ctx.allocate(Checksum.size(), 1);
3492 memcpy(CKMem, Checksum.data(), Checksum.size());
3493 ArrayRef ChecksumAsBytes(reinterpret_cast(CKMem),
3494 Checksum.size());
3495
3496 if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
3497 static_cast(ChecksumKind)))
34783498 return Error(FileNumberLoc, "file number already allocated");
34793499
34803500 return false;
37503770 /// ::= .cv_filechecksums
37513771 bool AsmParser::parseDirectiveCVFileChecksums() {
37523772 getStreamer().EmitCVFileChecksumsDirective();
3773 return false;
3774 }
3775
3776 /// parseDirectiveCVFileChecksumOffset
3777 /// ::= .cv_filechecksumoffset fileno
3778 bool AsmParser::parseDirectiveCVFileChecksumOffset() {
3779 int64_t FileNo;
3780 if (parseIntToken(FileNo, "expected identifier in directive"))
3781 return true;
3782 if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
3783 return true;
3784 getStreamer().EmitCVFileChecksumOffsetDirective(FileNo);
37533785 return false;
37543786 }
37553787
51355167 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
51365168 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
51375169 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5170 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
51385171 DirectiveKindMap[".sleb128"] = DK_SLEB128;
51395172 DirectiveKindMap[".uleb128"] = DK_ULEB128;
51405173 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
227227 report_fatal_error("No open frame");
228228 }
229229
230 bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
231 return getContext().getCVContext().addFile(FileNo, Filename);
230 bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
231 ArrayRef Checksum,
232 unsigned ChecksumKind) {
233 return getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
234 ChecksumKind);
232235 }
233236
234237 bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) {
4848 ; ASM: .long 0
4949 ; ASM: # Inlined function bar starts at t.cpp:8
5050 ; ASM: .long 4098 # Type index of inlined function
51 ; ASM: .long 0 # Offset into filechecksum table
51 ; ASM: .cv_filechecksumoffset 1 # Offset into filechecksum table
5252 ; ASM: .long 8 # Starting line number
5353 ; ASM: # Inlined function foo starts at t.cpp:2
5454 ; ASM: .long 4099
55 ; ASM: .long 0
55 ; ASM: .cv_filechecksumoffset 1 # Offset into filechecksum table
5656 ; ASM: .long 2
5757 ; ASM: [[inline_end]]:
5858
7070 ; ASM: .cv_inline_linetable 2 1 2 Lfunc_begin0 Lfunc_end0
7171 ; ASM: .short 4430
7272 ; ASM: .short 4430
73
74 ; ASM: .cv_filechecksums
7375
7476 ; ASM: .section .debug$T,"dr"
7577 ; ASM: .long 4 # Debug section magic
1717
1818 ; X86-LABEL: _f:
1919 ; X86: # BB
20 ; X86: .cv_file 1 "D:\\one.c"
20 ; X86: .cv_file 1 "D:\\one.c" "70B51F534D80639D033AE92C6A856AF6" 1
2121 ; X86: .cv_loc 0 1 1 0 is_stmt 0 # one.c:1:0
2222 ; X86: calll _g
23 ; X86: .cv_file 2 "D:\\two.c"
23 ; X86: .cv_file 2 "D:\\two.c" "70B51F534D80639D033AE92C6A856AF6" 1
2424 ; X86: .cv_loc 0 2 2 0 # two.c:2:0
2525 ; X86: calll _g
2626 ; X86: .cv_loc 0 1 7 0 # one.c:7:0
5050 ; OBJ32-NEXT: ProcEnd {
5151 ; OBJ32: }
5252 ; OBJ32-NEXT: ]
53 ; OBJ32: Subsection [
54 ; OBJ32: SubSectionType: FileChecksums (0xF4)
55 ; OBJ32-NEXT: SubSectionSize: 0x30
56 ; OBJ32-NEXT: FileChecksum {
57 ; OBJ32-NEXT: Filename: D:\one.c (0x1)
58 ; OBJ32-NEXT: ChecksumSize: 0x10
59 ; OBJ32-NEXT: ChecksumKind: MD5 (0x1)
60 ; OBJ32-NEXT: ChecksumBytes: (70 B5 1F 53 4D 80 63 9D 03 3A E9 2C 6A 85 6A F6)
61 ; OBJ32-NEXT: }
62 ; OBJ32-NEXT: FileChecksum {
63 ; OBJ32-NEXT: Filename: D:\two.c (0xA)
64 ; OBJ32-NEXT: ChecksumSize: 0x10
65 ; OBJ32-NEXT: ChecksumKind: MD5 (0x1)
66 ; OBJ32-NEXT: ChecksumBytes: (70 B5 1F 53 4D 80 63 9D 03 3A E9 2C 6A 85 6A F6)
67 ; OBJ32-NEXT: }
68 ; OBJ32-NEXT: ]
5369 ; OBJ32: FunctionLineTable [
5470 ; OBJ32-NEXT: Name: _f
5571 ; OBJ32-NEXT: Flags: 0x0
87103
88104 ; X64-LABEL: f:
89105 ; X64-NEXT: .L{{.*}}:{{$}}
90 ; X64: .cv_file 1 "D:\\input.c"
106 ; X64: .cv_file 1 "D:\\input.c" "70B51F534D80639D033AE92C6A856AF6" 1
91107 ; X64: .cv_loc 0 1 3 0 is_stmt 0 # input.c:3:0
92108 ; X64: # BB
93109 ; X64: subq $40, %rsp
94 ; X64: .cv_file 2 "D:\\one.c"
110 ; X64: .cv_file 2 "D:\\one.c" "70B51F534D80639D033AE92C6A856AF6" 1
95111 ; X64: .cv_loc 0 2 1 0 # one.c:1:0
96112 ; X64: callq g
97 ; X64: .cv_file 3 "D:\\two.c"
113 ; X64: .cv_file 3 "D:\\two.c" "70B51F534D80639D033AE92C6A856AF6" 1
98114 ; X64: .cv_loc 0 3 2 0 # two.c:2:0
99115 ; X64: callq g
100116 ; X64: .cv_loc 0 2 7 0 # one.c:7:0
122138 ; OBJ64-NEXT: ProcEnd {
123139 ; OBJ64: }
124140 ; OBJ64-NEXT: ]
141 ; OBJ64: Subsection [
142 ; OBJ64: SubSectionType: FileChecksums (0xF4)
143 ; OBJ64-NEXT: SubSectionSize: 0x48
144 ; OBJ64-NEXT: FileChecksum {
145 ; OBJ64-NEXT: Filename: D:\input.c (0x1)
146 ; OBJ64-NEXT: ChecksumSize: 0x10
147 ; OBJ64-NEXT: ChecksumKind: MD5 (0x1)
148 ; OBJ64-NEXT: ChecksumBytes: (70 B5 1F 53 4D 80 63 9D 03 3A E9 2C 6A 85 6A F6)
149 ; OBJ64-NEXT: }
150 ; OBJ64-NEXT: FileChecksum {
151 ; OBJ64-NEXT: Filename: D:\one.c (0xC)
152 ; OBJ64-NEXT: ChecksumSize: 0x10
153 ; OBJ64-NEXT: ChecksumKind: MD5 (0x1)
154 ; OBJ64-NEXT: ChecksumBytes: (70 B5 1F 53 4D 80 63 9D 03 3A E9 2C 6A 85 6A F6)
155 ; OBJ64-NEXT: }
156 ; OBJ64-NEXT: FileChecksum {
157 ; OBJ64-NEXT: Filename: D:\two.c (0x15)
158 ; OBJ64-NEXT: ChecksumSize: 0x10
159 ; OBJ64-NEXT: ChecksumKind: MD5 (0x1)
160 ; OBJ64-NEXT: ChecksumBytes: (70 B5 1F 53 4D 80 63 9D 03 3A E9 2C 6A 85 6A F6)
161 ; OBJ64-NEXT: }
162 ; OBJ64-NEXT: ]
125163 ; OBJ64: FunctionLineTable [
126164 ; OBJ64-NEXT: Name: f
127165 ; OBJ64-NEXT: Flags: 0x0
184222 !llvm.ident = !{!11}
185223
186224 !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.5 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
187 !1 = !DIFile(filename: "", directory: "D:\5C")
225 !1 = !DIFile(filename: "", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
188226 !2 = !{}
189227 !4 = distinct !DISubprogram(name: "f", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !5, scope: !6, type: !7, variables: !2)
190 !5 = !DIFile(filename: "input.c", directory: "D:\5C")
191 !6 = !DIFile(filename: "input.c", directory: "D:C")
228 !5 = !DIFile(filename: "input.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
229 !6 = !DIFile(filename: "input.c", directory: "D:C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
192230 !7 = !DISubroutineType(types: !8)
193231 !8 = !{null}
194232 !9 = !{i32 2, !"CodeView", i32 1}
196234 !11 = !{!"clang version 3.5 "}
197235 !12 = !DILocation(line: 1, scope: !13)
198236 !13 = !DILexicalBlockFile(discriminator: 0, file: !14, scope: !4)
199 !14 = !DIFile(filename: "one.c", directory: "D:\5C")
237 !14 = !DIFile(filename: "one.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
200238 !15 = !DILocation(line: 2, scope: !16)
201239 !16 = !DILexicalBlockFile(discriminator: 0, file: !17, scope: !4)
202 !17 = !DIFile(filename: "two.c", directory: "D:\5C")
240 !17 = !DIFile(filename: "two.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
203241 !18 = !DILocation(line: 7, scope: !13)
204242 !19 = !DILocation(line: 8, scope: !13)
1616
1717 ; X86-LABEL: _f:
1818 ; X86: # BB
19 ; X86: .cv_file 1 "D:\\test.c"
19 ; X86: .cv_file 1 "D:\\test.c" "F310AB26998CA831CBDF169E4EECACFA" 1
2020 ; X86: .cv_loc 0 1 4 2 is_stmt 0 # test.c:4:2
2121 ; X86: calll _g
2222 ; X86: .cv_loc 0 1 5 0 # test.c:5:0
8484 ; OBJ32-NEXT: ProcEnd {
8585 ; OBJ32: }
8686 ; OBJ32-NEXT: ]
87 ; OBJ32: Subsection [
88 ; OBJ32: SubSectionType: FileChecksums (0xF4)
89 ; OBJ32-NEXT: SubSectionSize: 0x18
90 ; OBJ32-NEXT: FileChecksum {
91 ; OBJ32-NEXT: Filename: D:\test.c (0x1)
92 ; OBJ32-NEXT: ChecksumSize: 0x10
93 ; OBJ32-NEXT: ChecksumKind: MD5 (0x1)
94 ; OBJ32-NEXT: ChecksumBytes: (F3 10 AB 26 99 8C A8 31 CB DF 16 9E 4E EC AC FA)
95 ; OBJ32-NEXT: }
96 ; OBJ32-NEXT: ]
8797 ; OBJ32: FunctionLineTable [
8898 ; OBJ32-NEXT: Name: _f
8999 ; OBJ32-NEXT: Flags: 0x1
109119
110120 ; X64-LABEL: f:
111121 ; X64-NEXT: .L{{.*}}:{{$}}
112 ; X64: .cv_file 1 "D:\\test.c"
122 ; X64: .cv_file 1 "D:\\test.c" "F310AB26998CA831CBDF169E4EECACFA" 1
113123 ; X64: .cv_loc 0 1 3 0 is_stmt 0 # test.c:3:0
114124 ; X64: # BB
115125 ; X64: subq $40, %rsp
181191 ; OBJ64-NEXT: ProcEnd {
182192 ; OBJ64: }
183193 ; OBJ64-NEXT: ]
194 ; OBJ64: Subsection [
195 ; OBJ64: SubSectionType: FileChecksums (0xF4)
196 ; OBJ64-NEXT: SubSectionSize: 0x18
197 ; OBJ64-NEXT: FileChecksum {
198 ; OBJ64-NEXT: Filename: D:\test.c (0x1)
199 ; OBJ64-NEXT: ChecksumSize: 0x10
200 ; OBJ64-NEXT: ChecksumKind: MD5 (0x1)
201 ; OBJ64-NEXT: ChecksumBytes: (F3 10 AB 26 99 8C A8 31 CB DF 16 9E 4E EC AC FA)
202 ; OBJ64-NEXT: }
203 ; OBJ64-NEXT: ]
184204 ; OBJ64: FunctionLineTable [
185205 ; OBJ64-NEXT: Name: f
186206 ; OBJ64-NEXT: Flags: 0x1
231251 !1 = !DIFile(filename: "", directory: "D:\5C")
232252 !2 = !{}
233253 !4 = distinct !DISubprogram(name: "f", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !5, scope: !6, type: !7, variables: !2)
234 !5 = !DIFile(filename: "test.c", directory: "D:\5C")
235 !6 = !DIFile(filename: "test.c", directory: "D:C")
254 !5 = !DIFile(filename: "test.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum: "f310ab26998ca831cbdf169e4eecacfa")
255 !6 = !DIFile(filename: "test.c", directory: "D:C", checksumkind: CSK_MD5, checksum: "f310ab26998ca831cbdf169e4eecacfa")
236256 !7 = !DISubroutineType(types: !8)
237257 !8 = !{null}
238258 !9 = !{i32 2, !"CodeView", i32 1}
102102 ; CHECK: SubSectionType: FileChecksums (0xF4)
103103 ; CHECK: FileChecksum {
104104 ; CHECK: ChecksumSize: 0x0
105 ; CHECK: ChecksumKind: None (0x0)
105 ; CHECK: ChecksumKind: MD5 (0x1)
106106 ; CHECK: ChecksumBytes: ()
107107 ; CHECK: }
108108 ; CHECK: ]
13821382
13831383 EXPECT_NE(N, DIFile::get(Context, "other", Directory, CSKind, Checksum));
13841384 EXPECT_NE(N, DIFile::get(Context, Filename, "other", CSKind, Checksum));
1385 EXPECT_NE(N, DIFile::get(Context, Filename, Directory, DIFile::CSK_SHA1, Checksum));
1385 EXPECT_NE(
1386 N, DIFile::get(Context, Filename, Directory, DIFile::CSK_SHA1, Checksum));
13861387 EXPECT_NE(N, DIFile::get(Context, Filename, Directory));
13871388
13881389 TempDIFile Temp = N->clone();