brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · 0c1d3f9 Raw
111 lines · cpp
1//===- Reproducer.cpp -----------------------------------------------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Reproducer.h"10#include "llvm/Support/Path.h"11#include "llvm/Support/Process.h"12 13using namespace llvm;14using namespace llvm::dsymutil;15 16static std::string createReproducerDir(std::error_code &EC) {17  SmallString<128> Root;18  if (const char *Path = getenv("DSYMUTIL_REPRODUCER_PATH")) {19    Root.assign(Path);20    EC = sys::fs::create_directories(Root);21  } else if (const char *Path = getenv("LLVM_DIAGNOSTIC_DIR")) {22    Root.assign(Path);23    llvm::sys::path::append(24        Root, "dsymutil-" + llvm::Twine(llvm::sys::Process::getProcessId()));25    EC = sys::fs::create_directories(Root);26  } else {27    EC = sys::fs::createUniqueDirectory("dsymutil", Root);28  }29  sys::fs::make_absolute(Root);30  return EC ? "" : std::string(Root);31}32 33Reproducer::Reproducer() : VFS(vfs::getRealFileSystem()) {}34Reproducer::~Reproducer() = default;35 36ReproducerGenerate::ReproducerGenerate(std::error_code &EC, int Argc,37                                       char **Argv, bool GenerateOnExit)38    : Root(createReproducerDir(EC)), GenerateOnExit(GenerateOnExit) {39  llvm::append_range(Args, ArrayRef(Argv, Argc));40  auto RealFS = vfs::getRealFileSystem();41  if (!Root.empty())42    FC = std::make_shared<FileCollector>(Root, Root, RealFS);43  VFS = FileCollector::createCollectorVFS(std::move(RealFS), FC);44}45 46ReproducerGenerate::~ReproducerGenerate() {47  if (GenerateOnExit && !Generated)48    generate();49  else if (!Generated && !Root.empty())50    sys::fs::remove_directories(Root, /* IgnoreErrors */ true);51}52 53void ReproducerGenerate::generate() {54  if (!FC)55    return;56  Generated = true;57  FC->copyFiles(false);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 "64            "your bug report:\n";65  for (llvm::StringRef Arg : Args)66    errs() << Arg << ' ';67  errs() << "--use-reproducer " << Root << '\n';68  errs() << "********************\n";69}70 71ReproducerUse::~ReproducerUse() = default;72 73ReproducerUse::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());78 79  if (!Buffer) {80    EC = Buffer.getError();81    return;82  }83 84  VFS = llvm::vfs::getVFSFromYAML(std::move(Buffer.get()), nullptr, Mapping);85}86 87llvm::Expected<std::unique_ptr<Reproducer>>88Reproducer::createReproducer(ReproducerMode Mode, StringRef Root, int Argc,89                             char **Argv) {90 91  std::error_code EC;92  std::unique_ptr<Reproducer> Repro;93  switch (Mode) {94  case ReproducerMode::GenerateOnExit:95    Repro = std::make_unique<ReproducerGenerate>(EC, Argc, Argv, true);96    break;97  case ReproducerMode::GenerateOnCrash:98    Repro = std::make_unique<ReproducerGenerate>(EC, Argc, Argv, false);99    break;100  case ReproducerMode::Use:101    Repro = std::make_unique<ReproducerUse>(Root, EC);102    break;103  case ReproducerMode::Off:104    Repro = std::make_unique<Reproducer>();105    break;106  }107  if (EC)108    return errorCodeToError(EC);109  return {std::move(Repro)};110}111