1 //===- Reproducer.cpp -----------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "Reproducer.h"
10 #include "llvm/Support/Path.h"
11 #include "llvm/Support/Process.h"
14 using namespace llvm::dsymutil
;
16 static std::string
createReproducerDir(std::error_code
&EC
) {
17 SmallString
<128> Root
;
18 if (const char *Path
= getenv("DSYMUTIL_REPRODUCER_PATH")) {
20 EC
= sys::fs::create_directories(Root
);
21 } else if (const char *Path
= getenv("LLVM_DIAGNOSTIC_DIR")) {
23 llvm::sys::path::append(
24 Root
, "dsymutil-" + llvm::Twine(llvm::sys::Process::getProcessId()));
25 EC
= sys::fs::create_directories(Root
);
27 EC
= sys::fs::createUniqueDirectory("dsymutil", Root
);
29 sys::fs::make_absolute(Root
);
30 return EC
? "" : std::string(Root
);
33 Reproducer::Reproducer() : VFS(vfs::getRealFileSystem()) {}
34 Reproducer::~Reproducer() = default;
36 ReproducerGenerate::ReproducerGenerate(std::error_code
&EC
, int Argc
,
37 char **Argv
, bool GenerateOnExit
)
38 : Root(createReproducerDir(EC
)), GenerateOnExit(GenerateOnExit
) {
39 for (int I
= 0; I
< Argc
; ++I
)
40 Args
.push_back(Argv
[I
]);
42 FC
= std::make_shared
<FileCollector
>(Root
, Root
);
43 VFS
= FileCollector::createCollectorVFS(vfs::getRealFileSystem(), FC
);
46 ReproducerGenerate::~ReproducerGenerate() {
47 if (GenerateOnExit
&& !Generated
)
49 else if (!Generated
&& !Root
.empty())
50 sys::fs::remove_directories(Root
, /* IgnoreErrors */ true);
53 void ReproducerGenerate::generate() {
58 SmallString
<128> Mapping(Root
);
59 sys::path::append(Mapping
, "mapping.yaml");
60 FC
->writeMapping(Mapping
.str());
61 errs() << "********************\n";
62 errs() << "Reproducer written to " << Root
<< '\n';
63 errs() << "Please include the reproducer and the following invocation in "
65 for (llvm::StringRef Arg
: Args
)
67 errs() << "--use-reproducer " << Root
<< '\n';
68 errs() << "********************\n";
71 ReproducerUse::~ReproducerUse() = default;
73 ReproducerUse::ReproducerUse(StringRef Root
, std::error_code
&EC
) {
74 SmallString
<128> Mapping(Root
);
75 sys::path::append(Mapping
, "mapping.yaml");
76 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> Buffer
=
77 vfs::getRealFileSystem()->getBufferForFile(Mapping
.str());
80 EC
= Buffer
.getError();
84 VFS
= llvm::vfs::getVFSFromYAML(std::move(Buffer
.get()), nullptr, Mapping
);
87 llvm::Expected
<std::unique_ptr
<Reproducer
>>
88 Reproducer::createReproducer(ReproducerMode Mode
, StringRef Root
, int Argc
,
92 std::unique_ptr
<Reproducer
> Repro
;
94 case ReproducerMode::GenerateOnExit
:
95 Repro
= std::make_unique
<ReproducerGenerate
>(EC
, Argc
, Argv
, true);
97 case ReproducerMode::GenerateOnCrash
:
98 Repro
= std::make_unique
<ReproducerGenerate
>(EC
, Argc
, Argv
, false);
100 case ReproducerMode::Use
:
101 Repro
= std::make_unique
<ReproducerUse
>(Root
, EC
);
103 case ReproducerMode::Off
:
104 Repro
= std::make_unique
<Reproducer
>();
108 return errorCodeToError(EC
);
109 return {std::move(Repro
)};