xref: /llvm-project/llvm/tools/dsymutil/Reproducer.cpp (revision bd206a363af392fc802e8f6e1dde282ca4490eaa)
192fd3971SJonas Devlieghere //===- Reproducer.cpp -----------------------------------------------------===//
292fd3971SJonas Devlieghere //
392fd3971SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
492fd3971SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information.
592fd3971SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
692fd3971SJonas Devlieghere //
792fd3971SJonas Devlieghere //===----------------------------------------------------------------------===//
892fd3971SJonas Devlieghere 
9d395eaccSJonas Devlieghere #include "Reproducer.h"
1007ffcef4SJonas Devlieghere #include "llvm/Support/Path.h"
11*bd206a36SJonas Devlieghere #include "llvm/Support/Process.h"
1292fd3971SJonas Devlieghere 
1392fd3971SJonas Devlieghere using namespace llvm;
1492fd3971SJonas Devlieghere using namespace llvm::dsymutil;
1592fd3971SJonas Devlieghere 
createReproducerDir(std::error_code & EC)1692fd3971SJonas Devlieghere static std::string createReproducerDir(std::error_code &EC) {
1792fd3971SJonas Devlieghere   SmallString<128> Root;
18*bd206a36SJonas Devlieghere   if (const char *Path = getenv("DSYMUTIL_REPRODUCER_PATH")) {
1992fd3971SJonas Devlieghere     Root.assign(Path);
20*bd206a36SJonas Devlieghere     EC = sys::fs::create_directories(Root);
21*bd206a36SJonas Devlieghere   } else if (const char *Path = getenv("LLVM_DIAGNOSTIC_DIR")) {
22*bd206a36SJonas Devlieghere     Root.assign(Path);
23*bd206a36SJonas Devlieghere     llvm::sys::path::append(
24*bd206a36SJonas Devlieghere         Root, "dsymutil-" + llvm::Twine(llvm::sys::Process::getProcessId()));
25*bd206a36SJonas Devlieghere     EC = sys::fs::create_directories(Root);
2692fd3971SJonas Devlieghere   } else {
2792fd3971SJonas Devlieghere     EC = sys::fs::createUniqueDirectory("dsymutil", Root);
2892fd3971SJonas Devlieghere   }
2917737437SJonas Devlieghere   sys::fs::make_absolute(Root);
3092fd3971SJonas Devlieghere   return EC ? "" : std::string(Root);
3192fd3971SJonas Devlieghere }
3292fd3971SJonas Devlieghere 
Reproducer()3392fd3971SJonas Devlieghere Reproducer::Reproducer() : VFS(vfs::getRealFileSystem()) {}
3492fd3971SJonas Devlieghere Reproducer::~Reproducer() = default;
3592fd3971SJonas Devlieghere 
ReproducerGenerate(std::error_code & EC,int Argc,char ** Argv,bool GenerateOnExit)3633b6891dSJonas Devlieghere ReproducerGenerate::ReproducerGenerate(std::error_code &EC, int Argc,
3733b6891dSJonas Devlieghere                                        char **Argv, bool GenerateOnExit)
3833b6891dSJonas Devlieghere     : Root(createReproducerDir(EC)), GenerateOnExit(GenerateOnExit) {
3933b6891dSJonas Devlieghere   for (int I = 0; I < Argc; ++I)
4033b6891dSJonas Devlieghere     Args.push_back(Argv[I]);
4192fd3971SJonas Devlieghere   if (!Root.empty())
4292fd3971SJonas Devlieghere     FC = std::make_shared<FileCollector>(Root, Root);
4392fd3971SJonas Devlieghere   VFS = FileCollector::createCollectorVFS(vfs::getRealFileSystem(), FC);
4492fd3971SJonas Devlieghere }
4592fd3971SJonas Devlieghere 
~ReproducerGenerate()4692fd3971SJonas Devlieghere ReproducerGenerate::~ReproducerGenerate() {
4733b6891dSJonas Devlieghere   if (GenerateOnExit && !Generated)
4833b6891dSJonas Devlieghere     generate();
498245f266SKeith Smiley   else if (!Generated && !Root.empty())
508245f266SKeith Smiley     sys::fs::remove_directories(Root, /* IgnoreErrors */ true);
5133b6891dSJonas Devlieghere }
5233b6891dSJonas Devlieghere 
generate()5333b6891dSJonas Devlieghere void ReproducerGenerate::generate() {
5492fd3971SJonas Devlieghere   if (!FC)
5592fd3971SJonas Devlieghere     return;
5633b6891dSJonas Devlieghere   Generated = true;
5792fd3971SJonas Devlieghere   FC->copyFiles(false);
5892fd3971SJonas Devlieghere   SmallString<128> Mapping(Root);
5992fd3971SJonas Devlieghere   sys::path::append(Mapping, "mapping.yaml");
6092fd3971SJonas Devlieghere   FC->writeMapping(Mapping.str());
6133b6891dSJonas Devlieghere   errs() << "********************\n";
6233b6891dSJonas Devlieghere   errs() << "Reproducer written to " << Root << '\n';
6333b6891dSJonas Devlieghere   errs() << "Please include the reproducer and the following invocation in "
6433b6891dSJonas Devlieghere             "your bug report:\n";
6533b6891dSJonas Devlieghere   for (llvm::StringRef Arg : Args)
6633b6891dSJonas Devlieghere     errs() << Arg << ' ';
6733b6891dSJonas Devlieghere   errs() << "--use-reproducer " << Root << '\n';
6833b6891dSJonas Devlieghere   errs() << "********************\n";
6992fd3971SJonas Devlieghere }
7092fd3971SJonas Devlieghere 
7192fd3971SJonas Devlieghere ReproducerUse::~ReproducerUse() = default;
7292fd3971SJonas Devlieghere 
ReproducerUse(StringRef Root,std::error_code & EC)7392fd3971SJonas Devlieghere ReproducerUse::ReproducerUse(StringRef Root, std::error_code &EC) {
7492fd3971SJonas Devlieghere   SmallString<128> Mapping(Root);
7592fd3971SJonas Devlieghere   sys::path::append(Mapping, "mapping.yaml");
7692fd3971SJonas Devlieghere   ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
7792fd3971SJonas Devlieghere       vfs::getRealFileSystem()->getBufferForFile(Mapping.str());
7892fd3971SJonas Devlieghere 
7992fd3971SJonas Devlieghere   if (!Buffer) {
8092fd3971SJonas Devlieghere     EC = Buffer.getError();
8192fd3971SJonas Devlieghere     return;
8292fd3971SJonas Devlieghere   }
8392fd3971SJonas Devlieghere 
8492fd3971SJonas Devlieghere   VFS = llvm::vfs::getVFSFromYAML(std::move(Buffer.get()), nullptr, Mapping);
8592fd3971SJonas Devlieghere }
8692fd3971SJonas Devlieghere 
8792fd3971SJonas Devlieghere llvm::Expected<std::unique_ptr<Reproducer>>
createReproducer(ReproducerMode Mode,StringRef Root,int Argc,char ** Argv)8833b6891dSJonas Devlieghere Reproducer::createReproducer(ReproducerMode Mode, StringRef Root, int Argc,
8933b6891dSJonas Devlieghere                              char **Argv) {
9033b6891dSJonas Devlieghere 
9133b6891dSJonas Devlieghere   std::error_code EC;
9233b6891dSJonas Devlieghere   std::unique_ptr<Reproducer> Repro;
9392fd3971SJonas Devlieghere   switch (Mode) {
9433b6891dSJonas Devlieghere   case ReproducerMode::GenerateOnExit:
9533b6891dSJonas Devlieghere     Repro = std::make_unique<ReproducerGenerate>(EC, Argc, Argv, true);
9633b6891dSJonas Devlieghere     break;
9733b6891dSJonas Devlieghere   case ReproducerMode::GenerateOnCrash:
9833b6891dSJonas Devlieghere     Repro = std::make_unique<ReproducerGenerate>(EC, Argc, Argv, false);
9933b6891dSJonas Devlieghere     break;
10033b6891dSJonas Devlieghere   case ReproducerMode::Use:
10133b6891dSJonas Devlieghere     Repro = std::make_unique<ReproducerUse>(Root, EC);
10233b6891dSJonas Devlieghere     break;
10392fd3971SJonas Devlieghere   case ReproducerMode::Off:
10433b6891dSJonas Devlieghere     Repro = std::make_unique<Reproducer>();
10533b6891dSJonas Devlieghere     break;
10692fd3971SJonas Devlieghere   }
10733b6891dSJonas Devlieghere   if (EC)
10833b6891dSJonas Devlieghere     return errorCodeToError(EC);
10998fe8693SJonas Devlieghere   return {std::move(Repro)};
11092fd3971SJonas Devlieghere }
111