Skip to content

Commit

Permalink
[DWARFv5] MC support for MD5 file checksums
Browse files Browse the repository at this point in the history
Extend .file directive syntax to allow specifying an MD5 checksum for
the source file.  Emit the checksums in DWARF v5 line tables.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@322134 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
pogo59 committed Jan 9, 2018
1 parent 38e8da8 commit e1e7096
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 39 deletions.
4 changes: 3 additions & 1 deletion include/llvm/MC/MCContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
Expand Down Expand Up @@ -489,7 +490,8 @@ namespace llvm {

/// Creates an entry in the dwarf file and directory tables.
unsigned getDwarfFile(StringRef Directory, StringRef FileName,
unsigned FileNumber, unsigned CUID);
unsigned FileNumber, MD5::MD5Result *Checksum,
unsigned CUID);

bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0);

Expand Down
15 changes: 11 additions & 4 deletions include/llvm/MC/MCDwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCSection.h"
#include "llvm/Support/MD5.h"
#include <cassert>
#include <cstdint>
#include <string>
Expand Down Expand Up @@ -50,6 +51,10 @@ struct MCDwarfFile {

// \brief The index into the list of directory names for this file name.
unsigned DirIndex;

/// The MD5 checksum, if there is one. Non-owning pointer to data allocated
/// in MCContext.
MD5::MD5Result *Checksum = nullptr;
};

/// \brief Instances of this class represent the information from a
Expand Down Expand Up @@ -203,11 +208,12 @@ struct MCDwarfLineTableHeader {
SmallVector<MCDwarfFile, 3> MCDwarfFiles;
StringMap<unsigned> SourceIdMap;
StringRef CompilationDir;
bool HasMD5 = false;

MCDwarfLineTableHeader() = default;

unsigned getFile(StringRef &Directory, StringRef &FileName,
unsigned FileNumber = 0);
MD5::MD5Result *Checksum, unsigned FileNumber = 0);
std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS,
MCDwarfLineTableParams Params) const;
std::pair<MCSymbol *, MCSymbol *>
Expand All @@ -223,8 +229,9 @@ class MCDwarfDwoLineTable {
Header.CompilationDir = CompilationDir;
}

unsigned getFile(StringRef Directory, StringRef FileName) {
return Header.getFile(Directory, FileName);
unsigned getFile(StringRef Directory, StringRef FileName,
MD5::MD5Result *Checksum) {
return Header.getFile(Directory, FileName, Checksum);
}

void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const;
Expand All @@ -242,7 +249,7 @@ class MCDwarfLineTable {
void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params) const;

unsigned getFile(StringRef &Directory, StringRef &FileName,
unsigned FileNumber = 0);
MD5::MD5Result *Checksum, unsigned FileNumber = 0);

MCSymbol *getLabel() const {
return Header.Label;
Expand Down
2 changes: 2 additions & 0 deletions include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCWinEH.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/TargetParser.h"
#include <cassert>
Expand Down Expand Up @@ -754,6 +755,7 @@ class MCStreamer {
/// implements the DWARF2 '.file 4 "foo.c"' assembler directive.
virtual unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename,
MD5::MD5Result *Checksum = nullptr,
unsigned CUID = 0);

/// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler
Expand Down
7 changes: 4 additions & 3 deletions lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,15 @@ void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,
}

unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName,
StringRef DirName) {
StringRef DirName,
MD5::MD5Result *Checksum) {
// If we print assembly, we can't separate .file entries according to
// compile units. Thus all files will belong to the default compile unit.

// FIXME: add a better feature test than hasRawTextSupport. Even better,
// extend .file to support this.
return Asm->OutStreamer->EmitDwarfFileDirective(
0, DirName, FileName,
0, DirName, FileName, Checksum,
Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID());
}

Expand Down Expand Up @@ -443,7 +444,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {
// Add the call site information to the DIE.
const DILocation *IA = Scope->getInlinedAt();
addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None,
getOrCreateSourceID(IA->getFilename(), IA->getDirectory()));
getOrCreateSourceID(IA->getFilename(), IA->getDirectory(), nullptr));
addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, IA->getLine());
if (IA->getDiscriminator() && DD->getDwarfVersion() >= 4)
addUInt(*ScopeDIE, dwarf::DW_AT_GNU_discriminator, None,
Expand Down
3 changes: 2 additions & 1 deletion lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ class DwarfCompileUnit final : public DwarfUnit {

DwarfCompileUnit &getCU() override { return *this; }

unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override;
unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName,
MD5::MD5Result *Checksum) override;

void addImportedEntity(const DIImportedEntity* IE) {
DIScope *Scope = IE->getScope();
Expand Down
5 changes: 3 additions & 2 deletions lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1378,7 +1378,7 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,

unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
.getOrCreateSourceID(Fn, Dir);
.getOrCreateSourceID(Fn, Dir, nullptr);
}
Asm->OutStreamer->EmitDwarfLocDirective(Src, Line, Col, Flags, 0,
Discriminator, Fn);
Expand Down Expand Up @@ -1975,7 +1975,8 @@ void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) {
Asm->EmitULEB128(F.getLine());
DIFile *File = F.getFile();
unsigned FID =
U.getOrCreateSourceID(File->getFilename(), File->getDirectory());
U.getOrCreateSourceID(File->getFilename(), File->getDirectory(),
nullptr); // FIXME: MD5?
Asm->EmitULEB128(FID);
handleMacroNodes(F.getElements(), U);
Asm->EmitULEB128(dwarf::DW_MACINFO_end_file);
Expand Down
18 changes: 11 additions & 7 deletions lib/CodeGen/AsmPrinter/DwarfUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,12 @@ void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute,
addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);
}

unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) {
return SplitLineTable ? SplitLineTable->getFile(DirName, FileName)
: getCU().getOrCreateSourceID(FileName, DirName);
unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName,
StringRef DirName,
MD5::MD5Result *Checksum) {
return SplitLineTable
? SplitLineTable->getFile(DirName, FileName, Checksum)
: getCU().getOrCreateSourceID(FileName, DirName, Checksum);
}

void DwarfUnit::addOpAddress(DIELoc &Die, const MCSymbol *Sym) {
Expand Down Expand Up @@ -340,7 +343,7 @@ void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, StringRef File,
if (Line == 0)
return;

unsigned FileID = getOrCreateSourceID(File, Directory);
unsigned FileID = getOrCreateSourceID(File, Directory, nullptr);
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
Expand Down Expand Up @@ -1161,9 +1164,10 @@ bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP,
// Look at the Decl's linkage name only if we emitted it.
if (DD->useAllLinkageNames())
DeclLinkageName = SPDecl->getLinkageName();
unsigned DeclID =
getOrCreateSourceID(SPDecl->getFilename(), SPDecl->getDirectory());
unsigned DefID = getOrCreateSourceID(SP->getFilename(), SP->getDirectory());
unsigned DeclID = getOrCreateSourceID(SPDecl->getFilename(),
SPDecl->getDirectory(), nullptr);
unsigned DefID =
getOrCreateSourceID(SP->getFilename(), SP->getDirectory(), nullptr);
if (DeclID != DefID)
addUInt(SPDie, dwarf::DW_AT_decl_file, None, DefID);

Expand Down
6 changes: 4 additions & 2 deletions lib/CodeGen/AsmPrinter/DwarfUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ class DwarfUnit : public DIEUnit {

/// Look up the source ID with the given directory and source file names. If
/// none currently exists, create a new ID and insert it in the line table.
virtual unsigned getOrCreateSourceID(StringRef File, StringRef Directory) = 0;
virtual unsigned getOrCreateSourceID(StringRef File, StringRef Directory,
MD5::MD5Result *Checksum) = 0;

/// Look in the DwarfDebug map for the MDNode that corresponds to the
/// reference.
Expand Down Expand Up @@ -358,7 +359,8 @@ class DwarfTypeUnit final : public DwarfUnit {
DwarfCompileUnit &CU;
MCDwarfDwoLineTable *SplitLineTable;

unsigned getOrCreateSourceID(StringRef File, StringRef Directory) override;
unsigned getOrCreateSourceID(StringRef File, StringRef Directory,
MD5::MD5Result *Checksum) override;
bool isDwoUnit() const override;

public:
Expand Down
4 changes: 3 additions & 1 deletion lib/MC/MCAsmStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ class MCAsmStreamer final : public MCStreamer {
void EmitFileDirective(StringRef Filename) override;
unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename,
MD5::MD5Result *Checksum = 0,
unsigned CUID = 0) override;
void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
Expand Down Expand Up @@ -1068,12 +1069,13 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo,
StringRef Directory,
StringRef Filename,
MD5::MD5Result *Checksum,
unsigned CUID) {
assert(CUID == 0);

MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
unsigned NumFiles = Table.getMCDwarfFiles().size();
FileNo = Table.getFile(Directory, Filename, FileNo);
FileNo = Table.getFile(Directory, Filename, Checksum, FileNo);
if (FileNo == 0)
return 0;
if (NumFiles == Table.getMCDwarfFiles().size())
Expand Down
5 changes: 3 additions & 2 deletions lib/MC/MCContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,10 @@ MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
/// error and zero is returned and the client reports the error, else the
/// allocated file number is returned. The file numbers may be in any order.
unsigned MCContext::getDwarfFile(StringRef Directory, StringRef FileName,
unsigned FileNumber, unsigned CUID) {
unsigned FileNumber, MD5::MD5Result *Checksum,
unsigned CUID) {
MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID];
return Table.getFile(Directory, FileName, FileNumber);
return Table.getFile(Directory, FileName, Checksum, FileNumber);
}

/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it
Expand Down
33 changes: 26 additions & 7 deletions lib/MC/MCDwarf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ static void
emitV5FileDirTables(MCStreamer *MCOS,
const SmallVectorImpl<std::string> &MCDwarfDirs,
const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles,
StringRef CompilationDir) {
StringRef CompilationDir, bool HasMD5) {
// The directory format, which is just inline null-terminated strings.
MCOS->EmitIntValue(1, 1);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
Expand All @@ -300,20 +300,29 @@ emitV5FileDirTables(MCStreamer *MCOS,

// The file format, which is the inline null-terminated filename and a
// directory index. We don't track file size/timestamp so don't emit them
// in the v5 table.
// FIXME: Arrange to emit MD5 signatures for the source files.
MCOS->EmitIntValue(2, 1);
// in the v5 table. Emit MD5 checksums if we have them.
MCOS->EmitIntValue(HasMD5 ? 3 : 2, 1);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index);
MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata);
// Then the list of file names. These start at 1 for some reason.
if (HasMD5) {
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5);
MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16);
}
// Then the list of file names. These start at 1.
MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1);
for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) {
assert(!MCDwarfFiles[i].Name.empty());
MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and...
MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
if (HasMD5) {
MD5::MD5Result *Cksum = MCDwarfFiles[i].Checksum;
MCOS->EmitBinaryData(
StringRef(reinterpret_cast<const char *>(Cksum->Bytes.data()),
Cksum->Bytes.size()));
}
}
}

Expand Down Expand Up @@ -384,7 +393,8 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
// Put out the directory and file tables. The formats vary depending on
// the version.
if (LineTableVersion >= 5)
emitV5FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles, CompilationDir);
emitV5FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles, CompilationDir,
HasMD5);
else
emitV2FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles);

Expand All @@ -409,12 +419,14 @@ void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS,
}

unsigned MCDwarfLineTable::getFile(StringRef &Directory, StringRef &FileName,
MD5::MD5Result *Checksum,
unsigned FileNumber) {
return Header.getFile(Directory, FileName, FileNumber);
return Header.getFile(Directory, FileName, Checksum, FileNumber);
}

unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
StringRef &FileName,
MD5::MD5Result *Checksum,
unsigned FileNumber) {
if (Directory == CompilationDir)
Directory = "";
Expand Down Expand Up @@ -445,6 +457,10 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
if (!File.Name.empty())
return 0;

// If any files have an MD5 checksum, they all must.
if (FileNumber > 1)
assert(HasMD5 == (Checksum != nullptr));

if (Directory.empty()) {
// Separate the directory part from the basename of the FileName.
StringRef tFileName = sys::path::filename(FileName);
Expand Down Expand Up @@ -478,6 +494,9 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,

File.Name = FileName;
File.DirIndex = DirIndex;
File.Checksum = Checksum;
if (Checksum)
HasMD5 = true;

// return the allocated FileNumber.
return FileNumber;
Expand Down
39 changes: 32 additions & 7 deletions lib/MC/MCParser/AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
Expand Down Expand Up @@ -3294,8 +3295,8 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
}

/// parseDirectiveFile
/// ::= .file [number] filename
/// ::= .file number directory filename
/// ::= .file filename
/// ::= .file number [directory] filename [md5 checksum]
bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
// FIXME: I'm not sure what this is.
int64_t FileNumber = -1;
Expand Down Expand Up @@ -3331,19 +3332,43 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
Filename = Path;
}

if (parseToken(AsmToken::EndOfStatement,
"unexpected token in '.file' directive"))
return true;
std::string Checksum;
if (!parseOptionalToken(AsmToken::EndOfStatement)) {
StringRef Keyword;
if (check(getTok().isNot(AsmToken::Identifier),
"unexpected token in '.file' directive") ||
parseIdentifier(Keyword) ||
check(Keyword != "md5", "unexpected token in '.file' directive"))
return true;
if (getLexer().is(AsmToken::String) &&
check(FileNumber == -1, "MD5 checksum specified, but no file number"))
return true;
if (check(getTok().isNot(AsmToken::String),
"unexpected token in '.file' directive") ||
parseEscapedString(Checksum) ||
check(Checksum.size() != 32, "invalid MD5 checksum specified") ||
parseToken(AsmToken::EndOfStatement,
"unexpected token in '.file' directive"))
return true;
}

if (FileNumber == -1)
getStreamer().EmitFileDirective(Filename);
else {
MD5::MD5Result *CKMem = nullptr;
if (!Checksum.empty()) {
Checksum = fromHex(Checksum);
if (check(Checksum.size() != 16, "invalid MD5 checksum specified"))
return true;
CKMem = (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1);
memcpy(&CKMem->Bytes, Checksum.data(), 16);
}
// If there is -g option as well as debug info from directive file,
// we turn off -g option, directly use the existing debug info instead.
if (getContext().getGenDwarfForAssembly())
getContext().setGenDwarfForAssembly(false);
else if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) ==
0)
else if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory,
Filename, CKMem) == 0)
return Error(FileNumberLoc, "file number already allocated");
}

Expand Down
Loading

0 comments on commit e1e7096

Please sign in to comment.