diff --git a/llvm-project/clang/include/clang/Basic/CodeGenOptions.h b/llvm-project/clang/include/clang/Basic/CodeGenOptions.h index 269528461..796f834fe 100644 --- a/llvm-project/clang/include/clang/Basic/CodeGenOptions.h +++ b/llvm-project/clang/include/clang/Basic/CodeGenOptions.h @@ -183,6 +183,10 @@ class CodeGenOptions : public CodeGenOptionsBase { /// The string containing the gitoid of the omnibor file. std::string RecordOmniBor; + /// The string containing the commandline for the Omnibor metadata, + /// if non-empty. + std::string OmniborCommandLine; + /// List of dependent source/header files. /// This is shared with DependencyOuputOptions. /// This has same contents as Dependencies in DependencyCollector. diff --git a/llvm-project/clang/include/clang/Driver/Options.td b/llvm-project/clang/include/clang/Driver/Options.td index d9f0bf0b4..460132441 100644 --- a/llvm-project/clang/include/clang/Driver/Options.td +++ b/llvm-project/clang/include/clang/Driver/Options.td @@ -4991,6 +4991,9 @@ def record_command_line : Separate<["-"], "record-command-line">, def record_omnibor: Separate<["-"], "record-omnibor">, HelpText<"The string to embed in the .note.omnibor section.">, MarshallingInfoString>; +def omnibor_command_line : Separate<["-"], "omnibor-command-line">, + HelpText<"The command line string to be recorded in Omnibor metadata file.">, + MarshallingInfoString>; def compress_debug_sections_EQ : Joined<["-", "--"], "compress-debug-sections=">, HelpText<"DWARF debug sections compression type">, Values<"none,zlib">, NormalizedValuesScope<"llvm::DebugCompressionType">, NormalizedValues<["None", "Z"]>, diff --git a/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp index 237fae74c..6c7888394 100644 --- a/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp +++ b/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp @@ -6452,6 +6452,7 @@ static std::string ComputeSHA1OmniBorData(CodeGenModule &CGM, gitoid = Result.str(); SmallString<128> gitoidPath(CGM.getCodeGenOpts().RecordOmniBor); + llvm::sys::path::append(gitoidPath, "objects"); llvm::sys::path::append(gitoidPath, "gitoid_blob_sha1"); llvm::sys::path::append(gitoidPath, gitoidHex.substr(0, 2)); std::error_code EC; @@ -6496,6 +6497,7 @@ static std::string ComputeSHA256OmniBorData(CodeGenModule &CGM, gitoid = Result.str(); SmallString<128> gitoidPath(CGM.getCodeGenOpts().RecordOmniBor); + llvm::sys::path::append(gitoidPath, "objects"); llvm::sys::path::append(gitoidPath, "gitoid_blob_sha256"); llvm::sys::path::append(gitoidPath, gitoidHex.substr(0, 2)); std::error_code EC; diff --git a/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp b/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp index 8acca72cd..1498e5c16 100644 --- a/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp +++ b/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp @@ -6822,10 +6822,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, OutputPath = env; } if (!OutputPath.str().empty()) { - llvm::sys::path::append(OutputPath, "objects"); CmdArgs.push_back("-record-omnibor"); CmdArgs.push_back(Args.MakeArgString(OutputPath)); - // Create the .bom/objects directory + + // Collect command line arguments as metadata + ArgStringList OriginalArgs; + for (const auto &Arg : Args) + Arg->render(Args, OriginalArgs); + + SmallString<256> Flags; + EscapeSpacesAndBackslashes(Exec, Flags); + for (const char *OriginalArg : OriginalArgs) { + SmallString<128> EscapedArg; + EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); + Flags += " "; + Flags += EscapedArg; + } + auto FlagsArgString = Args.MakeArgString(Flags); + CmdArgs.push_back("-omnibor-command-line"); + CmdArgs.push_back(FlagsArgString); + auto EC = llvm::sys::fs::create_directories(OutputPath, /*IgnoreExisting=*/true); if (EC) diff --git a/llvm-project/clang/test/CodeGen/omnibor_test.c b/llvm-project/clang/test/CodeGen/omnibor_test.c index fb74dd69e..8454e3727 100644 --- a/llvm-project/clang/test/CodeGen/omnibor_test.c +++ b/llvm-project/clang/test/CodeGen/omnibor_test.c @@ -1,5 +1,12 @@ // RUN: rm -rf %t && mkdir %t +// RUN: rm -f objects/gitoid_blob_sha1/0b/e9b91c3e456c910b32afc862ffd073b7c61d5f +// RUN: env OMNIBOR_DIR= %clang -c -frecord-omnibor=%t %S/Inputs/omnibor.c -I%S/Inputs/omnibor.h +// RUN: llvm-readelf -n omnibor.o | FileCheck --check-prefix=BOM_NOTE_SECTION %s +// RUN: cat %t/objects/gitoid_blob_sha1/0b/e9b91c3e456c910b32afc862ffd073b7c61d5f | FileCheck --check-prefix=BOM_FILE_SHA1_CONTENTS %s +// RUN: cat %t/objects/gitoid_blob_sha256/58/ed318e337ad6260f471c086e9c9985543c5fbd507c3b44924f5af37bd0ea96 | FileCheck --check-prefix=BOM_FILE_SHA256_CONTENTS %s +// RUN: cat %t/metadata/llvm/17274786fd44c95cae7ccb2d0b29ca1738c3cbb1 | FileCheck --check-prefix=METADATA_CONTENTS %s + // RUN: %clang -c -frecord-omnibor=%t -o %t/omnibor_1.o %S/Inputs/omnibor.c -I%S/Inputs/omnibor.h // RUN: llvm-readelf -n %t/omnibor_1.o | FileCheck --check-prefix=BOM_NOTE_SECTION %s // RUN: cat %t/objects/gitoid_blob_sha1/0b/e9b91c3e456c910b32afc862ffd073b7c61d5f | FileCheck --check-prefix=BOM_FILE_SHA1_CONTENTS %s @@ -27,12 +34,6 @@ // RUN: cat %t/objects/gitoid_blob_sha1/0b/e9b91c3e456c910b32afc862ffd073b7c61d5f | FileCheck --check-prefix=BOM_FILE_SHA1_CONTENTS %s // RUN: cat %t/objects/gitoid_blob_sha256/58/ed318e337ad6260f471c086e9c9985543c5fbd507c3b44924f5af37bd0ea96 | FileCheck --check-prefix=BOM_FILE_SHA256_CONTENTS %s -// RUN: rm -f objects/gitoid_blob_sha1/0b/e9b91c3e456c910b32afc862ffd073b7c61d5f -// RUN: env OMNIBOR_DIR= %clang -c -frecord-omnibor=%t %S/Inputs/omnibor.c -I%S/Inputs/omnibor.h -// RUN: llvm-readelf -n omnibor.o | FileCheck --check-prefix=BOM_NOTE_SECTION %s -// RUN: cat %t/objects/gitoid_blob_sha1/0b/e9b91c3e456c910b32afc862ffd073b7c61d5f | FileCheck --check-prefix=BOM_FILE_SHA1_CONTENTS %s -// RUN: cat %t/objects/gitoid_blob_sha256/58/ed318e337ad6260f471c086e9c9985543c5fbd507c3b44924f5af37bd0ea96 | FileCheck --check-prefix=BOM_FILE_SHA256_CONTENTS %s - // BOM_NOTE_SECTION: Displaying notes found in: .note.omnibor // BOM_NOTE_SECTION: Owner Data size Description // BOM_NOTE_SECTION: OMNIBOR 0x00000014 NT_GITOID_SHA1 @@ -47,3 +48,7 @@ // BOM_FILE_SHA256_CONTENTS: gitoid:blob:sha256 // BOM_FILE_SHA256_CONTENTS: blob 465be75836446b37f31c5db1f29a8689f37cd5625d4b30237877703fc1070f5e // BOM_FILE_SHA256_CONTENTS: blob 8ad020236bd23736a75699ba4e83f52593d61c4c9f8d5932b57fce011f832bf8 + +// METADATA_CONTENTS: output: omnibor.o +// METADATA_CONTENTS_NEXT: input {{.*}}/omnibor.c +// METADATA_CONTENTS_NEXT: input {{.*}}/omnibor.h diff --git a/llvm-project/clang/tools/driver/cc1_main.cpp b/llvm-project/clang/tools/driver/cc1_main.cpp index f648adeba..aee5741ba 100644 --- a/llvm-project/clang/tools/driver/cc1_main.cpp +++ b/llvm-project/clang/tools/driver/cc1_main.cpp @@ -38,6 +38,8 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" +#include "llvm/Support/SHA1.h" +#include "llvm/Support/SHA256.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/TimeProfiler.h" @@ -181,6 +183,38 @@ static int PrintSupportedCPUs(std::string TargetStr) { return 0; } +static std::string convertToHex(StringRef Input) { + static const char *const LUT = "0123456789abcdef"; + size_t Length = Input.size(); + + std::string Output; + Output.reserve(2 * Length); + for (size_t i = 0; i < Length; ++i) { + const unsigned char c = Input[i]; + Output.push_back(LUT[c >> 4]); + Output.push_back(LUT[c & 15]); + } + return Output; +} + +static std::string getSHA1Hash(std::string Filename) { + llvm::ErrorOr> fileBuf = + llvm::MemoryBuffer::getFile(Filename, /*IsText=*/true); + if (!fileBuf) { + // Diags.Report(diag::err_fe_error_opening) << Filename; + llvm::errs() << "\n error opening " << Filename; + return std::string(); + } + + llvm::SHA1 Hash; + std::string initData = + "blob " + std::to_string(fileBuf.get()->getBufferSize()) + '\0'; + Hash.update(StringRef(initData)); + Hash.update(fileBuf.get()->getBuffer()); + auto Result = Hash.final(); + return convertToHex(Result); +} + int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { ensureSufficientStack(); @@ -272,6 +306,50 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { // later errors use the default handling behavior instead. llvm::remove_fatal_error_handler(); + if (!Clang->getCodeGenOpts().RecordOmniBor.empty()) { + SmallString<128> gitoidPath(Clang->getCodeGenOpts().RecordOmniBor); + llvm::sys::path::append(gitoidPath, "metadata/llvm"); + auto EC = + llvm::sys::fs::create_directories(gitoidPath, /*IgnoreExisting=*/true); + if (EC) + llvm::errs() << "\nCannot create metadata file "; + + std::vector MetadataLines; + std::string outLine("\noutput: "); + outLine.append(Clang->getFrontendOpts().OutputFile); + MetadataLines.push_back(outLine); + + if (Clang->getCodeGenOpts().BomDependencies->size()) { + std::vector &Deps = + *(Clang->getCodeGenOpts().BomDependencies); + for (auto file : Deps) { + std::string Line = "\ninput " + file; + MetadataLines.push_back(Line); + } + } + + // Metadata contents + std::string MetadataContents; + for (auto line : MetadataLines) + MetadataContents.append(line); + + // Write command line + if (!Clang->getCodeGenOpts().OmniborCommandLine.empty()) { + MetadataContents.append("\nbuild_cmd: "); + MetadataContents.append(Clang->getCodeGenOpts().OmniborCommandLine); + } + + // Write metadata + std::string artifact_id = getSHA1Hash(Clang->getFrontendOpts().OutputFile); + llvm::sys::path::append(gitoidPath, artifact_id); + std::string MetadataFile(gitoidPath); + llvm::raw_fd_ostream OSM(MetadataFile, EC, llvm::sys::fs::OF_TextWithCRLF); + if (EC) { + llvm::errs() << MetadataFile << EC.message(); + } + OSM << MetadataContents; + } + // When running with -disable-free, don't do any destruction or shutdown. if (Clang->getFrontendOpts().DisableFree) { llvm::BuryPointer(std::move(Clang));