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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Reproducer.h" 10 #include "llvm/Support/Path.h" 11 12 using namespace llvm; 13 using namespace llvm::dsymutil; 14 15 static std::string createReproducerDir(std::error_code &EC) { 16 SmallString<128> Root; 17 if (const char *Path = getenv("DSYMUTIL_REPRODUCER_PATH")) { 18 Root.assign(Path); 19 EC = sys::fs::create_directory(Root); 20 } else { 21 EC = sys::fs::createUniqueDirectory("dsymutil", Root); 22 } 23 return EC ? "" : std::string(Root); 24 } 25 26 Reproducer::Reproducer() : VFS(vfs::getRealFileSystem()) {} 27 Reproducer::~Reproducer() = default; 28 29 ReproducerGenerate::ReproducerGenerate(std::error_code &EC) 30 : Root(createReproducerDir(EC)) { 31 if (!Root.empty()) 32 FC = std::make_shared<FileCollector>(Root, Root); 33 VFS = FileCollector::createCollectorVFS(vfs::getRealFileSystem(), FC); 34 } 35 36 ReproducerGenerate::~ReproducerGenerate() { 37 if (!FC) 38 return; 39 FC->copyFiles(false); 40 SmallString<128> Mapping(Root); 41 sys::path::append(Mapping, "mapping.yaml"); 42 FC->writeMapping(Mapping.str()); 43 outs() << "reproducer written to " << Root << '\n'; 44 } 45 46 ReproducerUse::~ReproducerUse() = default; 47 48 ReproducerUse::ReproducerUse(StringRef Root, std::error_code &EC) { 49 SmallString<128> Mapping(Root); 50 sys::path::append(Mapping, "mapping.yaml"); 51 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = 52 vfs::getRealFileSystem()->getBufferForFile(Mapping.str()); 53 54 if (!Buffer) { 55 EC = Buffer.getError(); 56 return; 57 } 58 59 VFS = llvm::vfs::getVFSFromYAML(std::move(Buffer.get()), nullptr, Mapping); 60 } 61 62 llvm::Expected<std::unique_ptr<Reproducer>> 63 Reproducer::createReproducer(ReproducerMode Mode, StringRef Root) { 64 switch (Mode) { 65 case ReproducerMode::Generate: { 66 std::error_code EC; 67 std::unique_ptr<Reproducer> Repro = 68 std::make_unique<ReproducerGenerate>(EC); 69 if (EC) 70 return errorCodeToError(EC); 71 return std::move(Repro); 72 } 73 case ReproducerMode::Use: { 74 std::error_code EC; 75 std::unique_ptr<Reproducer> Repro = 76 std::make_unique<ReproducerUse>(Root, EC); 77 if (EC) 78 return errorCodeToError(EC); 79 return std::move(Repro); 80 } 81 case ReproducerMode::Off: 82 return std::make_unique<Reproducer>(); 83 } 84 llvm_unreachable("All cases handled above."); 85 } 86