summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp16
-rw-r--r--llvm/lib/IR/DebugInfoMetadata.cpp2
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp27
-rw-r--r--llvm/lib/MC/MCCodeView.cpp119
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp3
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp40
-rw-r--r--llvm/lib/MC/MCStreamer.cpp7
7 files changed, 165 insertions, 49 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 87aeb1f03dd..db72269983f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -159,7 +159,10 @@ unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
if (Insertion.second) {
// We have to compute the full filepath and emit a .cv_file directive.
StringRef FullPath = getFullFilepath(F);
- bool Success = OS.EmitCVFileDirective(NextId, FullPath);
+ StringRef Checksum = F->getChecksum();
+ DIFile::ChecksumKind ChecksumKind = F->getChecksumKind();
+ bool Success = OS.EmitCVFileDirective(NextId, FullPath, Checksum,
+ static_cast<unsigned>(ChecksumKind));
(void)Success;
assert(Success && ".cv_file directive failed");
}
@@ -681,8 +684,10 @@ void CodeViewDebug::emitInlineeLinesSubsection() {
OS.AddComment("Inlinee lines subsection");
MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
- // We don't provide any extra file info.
- // FIXME: Find out if debuggers use this info.
+ // We emit the checksum info for files. This is used by debuggers to
+ // determine if a pdb matches the source before loading it. Visual Studio,
+ // for instance, will display a warning that the breakpoints are not valid if
+ // the pdb does not match the source.
OS.AddComment("Inlinee lines signature");
OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4);
@@ -695,13 +700,10 @@ void CodeViewDebug::emitInlineeLinesSubsection() {
OS.AddComment("Inlined function " + SP->getName() + " starts at " +
SP->getFilename() + Twine(':') + Twine(SP->getLine()));
OS.AddBlankLine();
- // The filechecksum table uses 8 byte entries for now, and file ids start at
- // 1.
- unsigned FileOffset = (FileId - 1) * 8;
OS.AddComment("Type index of inlined function");
OS.EmitIntValue(InlineeIdx.getIndex(), 4);
OS.AddComment("Offset into filechecksum table");
- OS.EmitIntValue(FileOffset, 4);
+ OS.EmitCVFileChecksumOffsetDirective(FileId);
OS.AddComment("Starting line number");
OS.EmitIntValue(SP->getLine(), 4);
}
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 9ef8c35dbd0..1ef43e60b54 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -354,6 +354,8 @@ DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
}
+// FIXME: Implement this string-enum correspondence with a .def file and macros,
+// so that the association is explicit rather than implied.
static const char *ChecksumKindName[DIFile::CSK_Last + 1] = {
"CSK_None",
"CSK_MD5",
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 7cc0bcdaaf0..589716bfe8c 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -225,7 +225,8 @@ public:
StringRef FileName) override;
MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
- bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
+ bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
+ StringRef Checksum, unsigned ChecksumKind) override;
bool EmitCVFuncIdDirective(unsigned FuncId) override;
bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
unsigned IAFile, unsigned IALine,
@@ -245,6 +246,7 @@ public:
StringRef FixedSizePortion) override;
void EmitCVStringTableDirective() override;
void EmitCVFileChecksumsDirective() override;
+ void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
void EmitIdent(StringRef IdentString) override;
void EmitCFISections(bool EH, bool Debug) override;
@@ -1120,13 +1122,25 @@ MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
return MCStreamer::getDwarfLineTableSymbol(0);
}
-bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
- if (!getContext().getCVContext().addFile(FileNo, Filename))
+bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
+ StringRef Checksum,
+ unsigned ChecksumKind) {
+ if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
+ ChecksumKind))
return false;
OS << "\t.cv_file\t" << FileNo << ' ';
-
PrintQuotedString(Filename, OS);
+
+ if (!ChecksumKind) {
+ EmitEOL();
+ return true;
+ }
+
+ OS << ' ';
+ PrintQuotedString(Checksum, OS);
+ OS << ' ' << ChecksumKind;
+
EmitEOL();
return true;
}
@@ -1228,6 +1242,11 @@ void MCAsmStreamer::EmitCVFileChecksumsDirective() {
EmitEOL();
}
+void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
+ OS << "\t.cv_filechecksumoffset\t" << FileNo;
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitIdent(StringRef IdentString) {
assert(MAI->hasIdentDirective() && ".ident directive not supported");
OS << "\t.ident\t";
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp
index 92b1e12da55..ad6d9e5a5d8 100644
--- a/llvm/lib/MC/MCCodeView.cpp
+++ b/llvm/lib/MC/MCCodeView.cpp
@@ -39,29 +39,39 @@ CodeViewContext::~CodeViewContext() {
/// for it.
bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
unsigned Idx = FileNumber - 1;
- if (Idx < Filenames.size())
- return !Filenames[Idx].empty();
+ if (Idx < Files.size())
+ return Files[Idx].Assigned;
return false;
}
-bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
+bool CodeViewContext::addFile(MCStreamer &OS, unsigned FileNumber,
+ StringRef Filename, StringRef Checksum,
+ uint8_t ChecksumKind) {
assert(FileNumber > 0);
- Filename = addToStringTable(Filename);
+ auto FilenameOffset = addToStringTable(Filename);
+ Filename = FilenameOffset.first;
unsigned Idx = FileNumber - 1;
- if (Idx >= Filenames.size())
- Filenames.resize(Idx + 1);
+ if (Idx >= Files.size())
+ Files.resize(Idx + 1);
if (Filename.empty())
Filename = "<stdin>";
- if (!Filenames[Idx].empty())
+ if (Files[Idx].Assigned)
return false;
- // FIXME: We should store the string table offset of the filename, rather than
- // the filename itself for efficiency.
- Filename = addToStringTable(Filename);
+ FilenameOffset = addToStringTable(Filename);
+ Filename = FilenameOffset.first;
+ unsigned Offset = FilenameOffset.second;
+
+ auto ChecksumOffsetSymbol =
+ OS.getContext().createTempSymbol("checksum_offset", false);
+ Files[Idx].StringTableOffset = Offset;
+ Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;
+ Files[Idx].Assigned = true;
+ Files[Idx].Checksum = Checksum.str();
+ Files[Idx].ChecksumKind = ChecksumKind;
- Filenames[Idx] = Filename;
return true;
}
@@ -118,17 +128,18 @@ MCDataFragment *CodeViewContext::getStringTableFragment() {
return StrTabFragment;
}
-StringRef CodeViewContext::addToStringTable(StringRef S) {
+std::pair<StringRef, unsigned> CodeViewContext::addToStringTable(StringRef S) {
SmallVectorImpl<char> &Contents = getStringTableFragment()->getContents();
auto Insertion =
StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
// Return the string from the table, since it is stable.
- S = Insertion.first->first();
+ std::pair<StringRef, unsigned> Ret =
+ std::make_pair(Insertion.first->first(), Insertion.first->second);
if (Insertion.second) {
// The string map key is always null terminated.
- Contents.append(S.begin(), S.end() + 1);
+ Contents.append(Ret.first.begin(), Ret.first.end() + 1);
}
- return S;
+ return Ret;
}
unsigned CodeViewContext::getStringTableOffset(StringRef S) {
@@ -165,7 +176,7 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
// Do nothing if there are no file checksums. Microsoft's linker rejects empty
// CodeView substreams.
- if (Filenames.empty())
+ if (Files.empty())
return;
MCContext &Ctx = OS.getContext();
@@ -176,17 +187,63 @@ void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
OS.EmitLabel(FileBegin);
+ unsigned CurrentOffset = 0;
+
// Emit an array of FileChecksum entries. We index into this table using the
- // user-provided file number. Each entry is currently 8 bytes, as we don't
- // emit checksums.
- for (StringRef Filename : Filenames) {
- OS.EmitIntValue(getStringTableOffset(Filename), 4);
- // Zero the next two fields and align back to 4 bytes. This indicates that
- // no checksum is present.
- OS.EmitIntValue(0, 4);
+ // user-provided file number. Each entry may be a variable number of bytes
+ // determined by the checksum kind and size.
+ for (auto File : Files) {
+ OS.EmitAssignment(File.ChecksumTableOffset,
+ MCConstantExpr::create(CurrentOffset, Ctx));
+ CurrentOffset += 4; // String table offset.
+ if (!File.ChecksumKind) {
+ CurrentOffset +=
+ 4; // One byte each for checksum size and kind, then align to 4 bytes.
+ } else {
+ CurrentOffset += 2; // One byte each for checksum size and kind.
+ CurrentOffset += File.Checksum.size();
+ CurrentOffset = alignTo(CurrentOffset, 4);
+ }
+
+ OS.EmitIntValue(File.StringTableOffset, 4);
+
+ if (!File.ChecksumKind) {
+ // There is no checksum. Therefore zero the next two fields and align
+ // back to 4 bytes.
+ OS.EmitIntValue(0, 4);
+ continue;
+ }
+ OS.EmitIntValue(static_cast<uint8_t>(File.Checksum.size()), 1);
+ OS.EmitIntValue(File.ChecksumKind, 1);
+ OS.EmitBytes(File.Checksum);
+ OS.EmitValueToAlignment(4);
}
OS.EmitLabel(FileEnd);
+
+ ChecksumOffsetsAssigned = true;
+}
+
+// Output checksum table offset of the given file number. It is possible that
+// not all files have been registered yet, and so the offset cannot be
+// calculated. In this case a symbol representing the offset is emitted, and
+// the value of this symbol will be fixed up at a later time.
+void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS,
+ unsigned FileNo) {
+ unsigned Idx = FileNo - 1;
+
+ if (Idx >= Files.size())
+ Files.resize(Idx + 1);
+
+ if (ChecksumOffsetsAssigned) {
+ OS.EmitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
+ return;
+ }
+
+ const MCSymbolRefExpr *SRE =
+ MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext());
+
+ OS.EmitValueImpl(SRE, 4);
}
void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
@@ -219,9 +276,12 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
return Loc.getFileNum() != CurFileNum;
});
unsigned EntryCount = FileSegEnd - I;
- OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) +
- "' begins");
- OS.EmitIntValue(8 * (CurFileNum - 1), 4);
+ OS.AddComment(
+ "Segment for file '" +
+ Twine(getStringTableFragment()
+ ->getContents()[Files[CurFileNum - 1].StringTableOffset]) +
+ "' begins");
+ OS.EmitCVFileChecksumOffsetDirective(CurFileNum);
OS.EmitIntValue(EntryCount, 4);
uint32_t SegmentSize = 12;
SegmentSize += 8 * EntryCount;
@@ -401,9 +461,10 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
HaveOpenRange = true;
if (CurSourceLoc.File != LastSourceLoc.File) {
- // File ids are 1 based, and each file checksum table entry is 8 bytes
- // long. See emitFileChecksums above.
- unsigned FileOffset = 8 * (CurSourceLoc.File - 1);
+ unsigned FileOffset = static_cast<const MCConstantExpr *>(
+ Files[CurSourceLoc.File - 1]
+ .ChecksumTableOffset->getVariableValue())
+ ->getValue();
compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
compressAnnotation(FileOffset, Buffer);
}
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 174397e2739..e9e3133582c 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -426,6 +426,9 @@ void MCObjectStreamer::EmitCVFileChecksumsDirective() {
getContext().getCVContext().emitFileChecksums(*this);
}
+void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
+ getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
+}
void MCObjectStreamer::EmitBytes(StringRef Data) {
MCCVLineEntry::Make(this);
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index ee3cc8d80a6..6e4f8e26b53 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -501,6 +501,7 @@ private:
DK_CV_DEF_RANGE,
DK_CV_STRINGTABLE,
DK_CV_FILECHECKSUMS,
+ DK_CV_FILECHECKSUM_OFFSET,
DK_CFI_SECTIONS,
DK_CFI_STARTPROC,
DK_CFI_ENDPROC,
@@ -576,6 +577,7 @@ private:
bool parseDirectiveCVDefRange();
bool parseDirectiveCVStringTable();
bool parseDirectiveCVFileChecksums();
+ bool parseDirectiveCVFileChecksumOffset();
// .cfi directives
bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
@@ -2030,6 +2032,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveCVStringTable();
case DK_CV_FILECHECKSUMS:
return parseDirectiveCVFileChecksums();
+ case DK_CV_FILECHECKSUM_OFFSET:
+ return parseDirectiveCVFileChecksumOffset();
case DK_CFI_SECTIONS:
return parseDirectiveCFISections();
case DK_CFI_STARTPROC:
@@ -3457,25 +3461,34 @@ bool AsmParser::parseDirectiveStabs() {
}
/// parseDirectiveCVFile
-/// ::= .cv_file number filename
+/// ::= .cv_file number filename [checksum] [checksumkind]
bool AsmParser::parseDirectiveCVFile() {
SMLoc FileNumberLoc = getTok().getLoc();
int64_t FileNumber;
std::string Filename;
+ std::string Checksum;
+ int64_t ChecksumKind = 0;
if (parseIntToken(FileNumber,
"expected file number in '.cv_file' directive") ||
check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
check(getTok().isNot(AsmToken::String),
"unexpected token in '.cv_file' directive") ||
- // Usually directory and filename are together, otherwise just
- // directory. Allow the strings to have escaped octal character sequence.
- parseEscapedString(Filename) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cv_file' directive"))
+ parseEscapedString(Filename))
return true;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.cv_file' directive") ||
+ parseEscapedString(Checksum) ||
+ parseIntToken(ChecksumKind,
+ "expected checksum kind in '.cv_file' directive") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_file' directive"))
+ return true;
+ }
- if (!getStreamer().EmitCVFileDirective(FileNumber, Filename))
+ if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, Checksum,
+ static_cast<uint8_t>(ChecksumKind)))
return Error(FileNumberLoc, "file number already allocated");
return false;
@@ -3754,6 +3767,18 @@ bool AsmParser::parseDirectiveCVFileChecksums() {
return false;
}
+/// parseDirectiveCVFileChecksumOffset
+/// ::= .cv_filechecksumoffset fileno
+bool AsmParser::parseDirectiveCVFileChecksumOffset() {
+ int64_t FileNo;
+ if (parseIntToken(FileNo, "expected identifier in directive"))
+ return true;
+ if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
+ return true;
+ getStreamer().EmitCVFileChecksumOffsetDirective(FileNo);
+ return false;
+}
+
/// parseDirectiveCFISections
/// ::= .cfi_sections section [, section]
bool AsmParser::parseDirectiveCFISections() {
@@ -5136,6 +5161,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
+ DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
DirectiveKindMap[".sleb128"] = DK_SLEB128;
DirectiveKindMap[".uleb128"] = DK_ULEB128;
DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index e35907f77e1..a3756c97a1e 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -224,8 +224,11 @@ void MCStreamer::EnsureValidDwarfFrame() {
report_fatal_error("No open frame");
}
-bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
- return getContext().getCVContext().addFile(FileNo, Filename);
+bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
+ StringRef Checksum,
+ unsigned ChecksumKind) {
+ return getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
+ ChecksumKind);
}
bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) {
OpenPOWER on IntegriCloud