Fix a assertion in dsymutil coming from the Reproducer/FileCollector. When TMPDIR is empty, the root becomes a relative path, triggering an assertion when adding a relative path to the VFS mapping. This patch fixes the issue by resolving the relative path and also moves the assertion up to make it easier to diagnose these issues in the future. rdar://102170986 Differential revision: https://reviews.llvm.org/D137959
103 lines
3.2 KiB
C++
103 lines
3.2 KiB
C++
//===- Reproducer.cpp -----------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Reproducer.h"
|
|
#include "llvm/Support/Path.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::dsymutil;
|
|
|
|
static std::string createReproducerDir(std::error_code &EC) {
|
|
SmallString<128> Root;
|
|
if (const char *Path = getenv("DSYMUTIL_REPRODUCER_PATH")) {
|
|
Root.assign(Path);
|
|
EC = sys::fs::create_directory(Root);
|
|
} else {
|
|
EC = sys::fs::createUniqueDirectory("dsymutil", Root);
|
|
}
|
|
sys::fs::make_absolute(Root);
|
|
return EC ? "" : std::string(Root);
|
|
}
|
|
|
|
Reproducer::Reproducer() : VFS(vfs::getRealFileSystem()) {}
|
|
Reproducer::~Reproducer() = default;
|
|
|
|
ReproducerGenerate::ReproducerGenerate(std::error_code &EC, int Argc,
|
|
char **Argv, bool GenerateOnExit)
|
|
: Root(createReproducerDir(EC)), GenerateOnExit(GenerateOnExit) {
|
|
for (int I = 0; I < Argc; ++I)
|
|
Args.push_back(Argv[I]);
|
|
if (!Root.empty())
|
|
FC = std::make_shared<FileCollector>(Root, Root);
|
|
VFS = FileCollector::createCollectorVFS(vfs::getRealFileSystem(), FC);
|
|
}
|
|
|
|
ReproducerGenerate::~ReproducerGenerate() {
|
|
if (GenerateOnExit && !Generated)
|
|
generate();
|
|
}
|
|
|
|
void ReproducerGenerate::generate() {
|
|
if (!FC)
|
|
return;
|
|
Generated = true;
|
|
FC->copyFiles(false);
|
|
SmallString<128> Mapping(Root);
|
|
sys::path::append(Mapping, "mapping.yaml");
|
|
FC->writeMapping(Mapping.str());
|
|
errs() << "********************\n";
|
|
errs() << "Reproducer written to " << Root << '\n';
|
|
errs() << "Please include the reproducer and the following invocation in "
|
|
"your bug report:\n";
|
|
for (llvm::StringRef Arg : Args)
|
|
errs() << Arg << ' ';
|
|
errs() << "--use-reproducer " << Root << '\n';
|
|
errs() << "********************\n";
|
|
}
|
|
|
|
ReproducerUse::~ReproducerUse() = default;
|
|
|
|
ReproducerUse::ReproducerUse(StringRef Root, std::error_code &EC) {
|
|
SmallString<128> Mapping(Root);
|
|
sys::path::append(Mapping, "mapping.yaml");
|
|
ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
|
|
vfs::getRealFileSystem()->getBufferForFile(Mapping.str());
|
|
|
|
if (!Buffer) {
|
|
EC = Buffer.getError();
|
|
return;
|
|
}
|
|
|
|
VFS = llvm::vfs::getVFSFromYAML(std::move(Buffer.get()), nullptr, Mapping);
|
|
}
|
|
|
|
llvm::Expected<std::unique_ptr<Reproducer>>
|
|
Reproducer::createReproducer(ReproducerMode Mode, StringRef Root, int Argc,
|
|
char **Argv) {
|
|
|
|
std::error_code EC;
|
|
std::unique_ptr<Reproducer> Repro;
|
|
switch (Mode) {
|
|
case ReproducerMode::GenerateOnExit:
|
|
Repro = std::make_unique<ReproducerGenerate>(EC, Argc, Argv, true);
|
|
break;
|
|
case ReproducerMode::GenerateOnCrash:
|
|
Repro = std::make_unique<ReproducerGenerate>(EC, Argc, Argv, false);
|
|
break;
|
|
case ReproducerMode::Use:
|
|
Repro = std::make_unique<ReproducerUse>(Root, EC);
|
|
break;
|
|
case ReproducerMode::Off:
|
|
Repro = std::make_unique<Reproducer>();
|
|
break;
|
|
}
|
|
if (EC)
|
|
return errorCodeToError(EC);
|
|
return {std::move(Repro)};
|
|
}
|