arlosi created this revision.
Herald added subscribers: jansvoboda11, dexonsmith, dang.
arlosi requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Adds clang-cl support for the /ZH: option used to select MD5, SHA1,
or SHA_256 hashing algorithms in debug info.

Previously only the MD5 algorithm was supported.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D98438

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Basic/CodeGenOptions.h
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/CGDebugInfo.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp

Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -1928,6 +1928,20 @@
   else if (Args.hasArg(options::OPT_fno_finite_loops))
     Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;
 
+  if (Arg *A = Args.getLastArg(OPT_gsrc_hash_algorithm_EQ)) {
+    unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
+                       .Case("md5", CodeGenOptions::CSK_MD5)
+                       .Case("sha1", CodeGenOptions::CSK_SHA1)
+                       .Case("sha256", CodeGenOptions::CSK_SHA256)
+                       .Default(~0U);
+    if (Val == ~0U)
+      Diags.Report(diag::err_drv_invalid_value)
+          << A->getAsString(Args) << A->getValue();
+    else
+      Opts.setDebugSrcHashAlgorithm(
+          static_cast<CodeGenOptions::SrcHashAlgorithm>(Val));
+  }
+
   return Success && Diags.getNumErrors() == NumErrorsBefore;
 }
 
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ 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,
Index: clang/lib/CodeGen/CGDebugInfo.h
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.h
+++ clang/lib/CodeGen/CGDebugInfo.h
@@ -572,8 +572,9 @@
   void CreateCompileUnit();
 
   /// Compute the file checksum debug info for input file ID.
-  Optional<llvm::DIFile::ChecksumKind>
-  computeChecksum(FileID FID, SmallString<32> &Checksum) const;
+  /// Storage of the checksum string is owned by the caller.
+  Optional<llvm::DIFile::ChecksumInfo<StringRef>>
+  computeChecksum(FileID FID, SmallString<64> &Checksum) const;
 
   /// Get the source of the given file ID.
   Optional<StringRef> getSource(const SourceManager &SM, FileID FID);
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ 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<llvm::DIFile::ChecksumKind>
-CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const {
+Optional<llvm::DIFile::ChecksumInfo<StringRef>>
+CGDebugInfo::computeChecksum(FileID FID, SmallString<64> &Checksum) const {
   Checksum.clear();
 
+  llvm::DIFile::ChecksumKind CSKind;
+  Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;
   if (!CGM.getCodeGenOpts().EmitCodeView &&
       CGM.getCodeGenOpts().DwarfVersion < 5)
     return None;
@@ -374,14 +380,42 @@
   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<uint8_t>(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<uint8_t>(Result[i]));
+    break;
+  }
+  default:
+    return None;
+  }
 
-  Hash.stringifyResult(Result, Checksum);
-  return llvm::DIFile::CSK_MD5;
+  CSInfo.emplace(CSKind, Checksum);
+  return CSInfo;
 }
 
 Optional<StringRef> CGDebugInfo::getSource(const SourceManager &SM,
@@ -428,12 +462,10 @@
       return cast<llvm::DIFile>(V);
   }
 
-  SmallString<32> Checksum;
+  SmallString<64> Checksum;
+  Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo =
+      computeChecksum(FID, Checksum);
 
-  Optional<llvm::DIFile::ChecksumKind> CSKind = computeChecksum(FID, Checksum);
-  Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;
-  if (CSKind)
-    CSInfo.emplace(*CSKind, Checksum);
   return createFile(FileName, CSInfo, getSource(SM, SM.getFileID(Loc)));
 }
 
@@ -519,8 +551,7 @@
 }
 
 void CGDebugInfo::CreateCompileUnit() {
-  SmallString<32> Checksum;
-  Optional<llvm::DIFile::ChecksumKind> CSKind;
+  SmallString<64> Checksum;
   Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;
 
   // Should we be asking the SourceManager for the main file name, instead of
@@ -558,8 +589,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 +646,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()));
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2772,6 +2772,9 @@
   HelpText<"Set DWARF fission mode to either 'split' or 'single'">,
   Values<"split,single">;
 def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group<g_flags_Group>;
+def gsrc_hash_algorithm_EQ : Joined<["-"], "gsrc-hash-algorithm=">, Group<g_flags_Group>, Flags<[CC1Option]>,
+  HelpText<"Hashing algorithm for file checksum in debug info 'md5', 'sha1', or 'sha256'">,
+  Values<"md5,sha1,sha256">;
 def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
 def gno_gnu_pubnames : Flag<["-"], "gno-gnu-pubnames">, Group<g_flags_Group>;
 def gpubnames : Flag<["-"], "gpubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
@@ -5835,6 +5838,9 @@
   Alias<fdelayed_template_parsing>;
 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 +6012,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-">;
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ 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=<file>", "none"}.
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ 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.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to