diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -113,6 +113,12 @@ Embed_Marker // Embed a marker as a placeholder for bitcode. }; + enum SrcHashAlgorithm { + CSK_MD5, + CSK_SHA1, + CSK_SHA256, + }; + // This field stores one of the allowed values for the option // -fbasic-block-sections=. The allowed values with this option are: // {"labels", "all", "list=", "none"}. diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -299,6 +299,9 @@ ///< contain explicit imports for ///< anonymous namespaces +/// Set debug info source file hashing algorithm +ENUM_CODEGENOPT(DebugSrcHashAlgorithm, SrcHashAlgorithm, 4, CSK_MD5) + CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the ///< skeleton CU to allow for symbolication ///< of inline stack frames without .dwo files. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2772,6 +2772,11 @@ HelpText<"Set DWARF fission mode to either 'split' or 'single'">, Values<"split,single">; def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group; +def gsrc_hash_algorithm_EQ : Joined<["-"], "gsrc-hash-algorithm=">, Group, Flags<[CC1Option]>, + HelpText<"Hashing algorithm for file checksum in debug info 'md5', 'sha1', or 'sha256'">, + Values<"md5,sha1,sha256">, NormalizedValues<["CSK_MD5", "CSK_SHA1", "CSK_SHA256"]>, + NormalizedValuesScope<"CodeGenOptions">, + MarshallingInfoEnum, "CSK_MD5">; def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group, Flags<[CC1Option]>; def gno_gnu_pubnames : Flag<["-"], "gno-gnu-pubnames">, Group; def gpubnames : Flag<["-"], "gpubnames">, Group, Flags<[CC1Option]>; @@ -5835,6 +5840,9 @@ Alias; def _SLASH_Z7 : CLFlag<"Z7">, HelpText<"Enable CodeView debug information in object files">; +def _SLASH_ZH : CLCompileJoined<"ZH:">, + HelpText<"Hash algorithm for file checksum in debug info (MD5, SHA1, or SHA_256)">, + Values<"MD5,SHA1,SHA_256">; def _SLASH_Zi : CLFlag<"Zi">, Alias<_SLASH_Z7>, HelpText<"Like /Z7">; def _SLASH_Zp : CLJoined<"Zp">, @@ -6006,9 +6014,6 @@ def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">; def _SLASH_Zc_ternary : CLIgnoredFlag<"Zc:ternary">; def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">; -def _SLASH_ZH_MD5 : CLIgnoredFlag<"ZH:MD5">; -def _SLASH_ZH_SHA1 : CLIgnoredFlag<"ZH:SHA1">; -def _SLASH_ZH_SHA_256 : CLIgnoredFlag<"ZH:SHA_256">; def _SLASH_Zm : CLIgnoredJoined<"Zm">; def _SLASH_Zo : CLIgnoredFlag<"Zo">; def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">; diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -572,8 +572,9 @@ void CreateCompileUnit(); /// Compute the file checksum debug info for input file ID. - Optional - computeChecksum(FileID FID, SmallString<32> &Checksum) const; + /// Storage of the checksum string is owned by the caller. + Optional> + computeChecksum(FileID FID, SmallString<64> &Checksum) const; /// Get the source of the given file ID. Optional getSource(const SourceManager &SM, FileID FID); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -44,9 +44,13 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" #include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" +#include "llvm/Support/SHA1.h" +#include "llvm/Support/SHA256.h" #include "llvm/Support/TimeProfiler.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; using namespace clang::CodeGen; @@ -361,10 +365,12 @@ return StringRef(); } -Optional -CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const { +Optional> +CGDebugInfo::computeChecksum(FileID FID, SmallString<64> &Checksum) const { Checksum.clear(); + llvm::DIFile::ChecksumKind CSKind; + Optional> CSInfo; if (!CGM.getCodeGenOpts().EmitCodeView && CGM.getCodeGenOpts().DwarfVersion < 5) return None; @@ -374,14 +380,40 @@ if (!MemBuffer) return None; - llvm::MD5 Hash; - llvm::MD5::MD5Result Result; - - Hash.update(MemBuffer->getBuffer()); - Hash.final(Result); + switch (CGM.getCodeGenOpts().getDebugSrcHashAlgorithm()) { + case clang::CodeGenOptions::CSK_MD5: { + CSKind = llvm::DIFile::CSK_MD5; + llvm::MD5 Hash; + llvm::MD5::MD5Result Result; + Hash.update(MemBuffer->getBuffer()); + Hash.final(Result); + Checksum = Result.digest(); + break; + } + case clang::CodeGenOptions::CSK_SHA1: { + CSKind = llvm::DIFile::CSK_SHA1; + llvm::SHA1 Hash; + Hash.update(MemBuffer->getBuffer()); + StringRef Result = Hash.final(); + llvm::raw_svector_ostream Res(Checksum); + for (int i = 0; i < 20; ++i) + Res << llvm::format("%.2x", static_cast(Result[i])); + break; + } + case clang::CodeGenOptions::CSK_SHA256: { + CSKind = llvm::DIFile::CSK_SHA256; + llvm::SHA256 Hash; + Hash.update(MemBuffer->getBuffer()); + StringRef Result = Hash.final(); + llvm::raw_svector_ostream Res(Checksum); + for (int i = 0; i < 32; ++i) + Res << llvm::format("%.2x", static_cast(Result[i])); + break; + } + } - Hash.stringifyResult(Result, Checksum); - return llvm::DIFile::CSK_MD5; + CSInfo.emplace(CSKind, Checksum); + return CSInfo; } Optional CGDebugInfo::getSource(const SourceManager &SM, @@ -428,12 +460,10 @@ return cast(V); } - SmallString<32> Checksum; + SmallString<64> Checksum; + Optional> CSInfo = + computeChecksum(FID, Checksum); - Optional CSKind = computeChecksum(FID, Checksum); - Optional> CSInfo; - if (CSKind) - CSInfo.emplace(*CSKind, Checksum); return createFile(FileName, CSInfo, getSource(SM, SM.getFileID(Loc))); } @@ -519,8 +549,7 @@ } void CGDebugInfo::CreateCompileUnit() { - SmallString<32> Checksum; - Optional CSKind; + SmallString<64> Checksum; Optional> CSInfo; // Should we be asking the SourceManager for the main file name, instead of @@ -558,8 +587,7 @@ MainFile->getName().rsplit('.').second) .isPreprocessed()) MainFileName = CGM.getModule().getName().str(); - - CSKind = computeChecksum(SM.getMainFileID(), Checksum); + CSInfo = computeChecksum(SM.getMainFileID(), Checksum); } llvm::dwarf::SourceLanguage LangTag; @@ -616,8 +644,6 @@ // file. Its directory part specifies what becomes the // DW_AT_comp_dir (the compilation directory), even if the source // file was specified with an absolute path. - if (CSKind) - CSInfo.emplace(*CSKind, Checksum); llvm::DIFile *CUFile = DBuilder.createFile( remapDIPath(MainFileName), remapDIPath(getCurrentDirname()), CSInfo, getSource(SM, SM.getMainFileID())); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7107,6 +7107,19 @@ D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << GuardArgs; } } + + if (Arg *A = Args.getLastArg(options::OPT__SLASH_ZH)) { + StringRef Val = A->getValue(); + if (Val.equals("MD5")) { + CmdArgs.push_back("-gsrc-hash-algorithm=md5"); + } else if (Val.equals("SHA1")) { + CmdArgs.push_back("-gsrc-hash-algorithm=sha1"); + } else if (Val.equals("SHA_256")) { + CmdArgs.push_back("-gsrc-hash-algorithm=sha256"); + } else { + D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; + } + } } const char *Clang::getBaseInputName(const ArgList &Args,