Skip to content

Commit 97e7a7e

Browse files
authored
Merge pull request #2042 from JDevlieghere/🍒/bastille/73811d3
[lldb] Move copying of files into reproducer out of process
2 parents d224f08 + b5be4df commit 97e7a7e

File tree

14 files changed

+217
-53
lines changed

14 files changed

+217
-53
lines changed

lldb/include/lldb/API/SBReproducer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class LLDB_API SBReproducer {
4848
static const char *Replay(const char *path, bool skip_version_check);
4949
static const char *Replay(const char *path, const SBReplayOptions &options);
5050
static const char *PassiveReplay(const char *path);
51+
static const char *Finalize(const char *path);
5152
static const char *GetPath();
5253
static bool SetAutoGenerate(bool b);
5354
static bool Generate();

lldb/include/lldb/Host/FileSystem.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class FileSystem {
3434
FileSystem()
3535
: m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr),
3636
m_home_directory(), m_mapped(false) {}
37-
FileSystem(std::shared_ptr<llvm::FileCollector> collector)
37+
FileSystem(std::shared_ptr<llvm::FileCollectorBase> collector)
3838
: m_fs(llvm::vfs::getRealFileSystem()), m_collector(std::move(collector)),
3939
m_home_directory(), m_mapped(false) {}
4040
FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
@@ -48,7 +48,7 @@ class FileSystem {
4848
static FileSystem &Instance();
4949

5050
static void Initialize();
51-
static void Initialize(std::shared_ptr<llvm::FileCollector> collector);
51+
static void Initialize(std::shared_ptr<llvm::FileCollectorBase> collector);
5252
static llvm::Error Initialize(const FileSpec &mapping);
5353
static void Initialize(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs);
5454
static void Terminate();
@@ -199,7 +199,7 @@ class FileSystem {
199199
private:
200200
static llvm::Optional<FileSystem> &InstanceImpl();
201201
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
202-
std::shared_ptr<llvm::FileCollector> m_collector;
202+
std::shared_ptr<llvm::FileCollectorBase> m_collector;
203203
std::string m_home_directory;
204204
bool m_mapped;
205205
};

lldb/include/lldb/Utility/Reproducer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ struct ReplayOptions {
243243
bool check_version = true;
244244
};
245245

246+
llvm::Error Finalize(Loader *loader);
247+
llvm::Error Finalize(const FileSpec &root);
248+
246249
} // namespace repro
247250
} // namespace lldb_private
248251

lldb/include/lldb/Utility/ReproducerProvider.h

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,38 +90,50 @@ class YamlRecorder : public AbstractRecorder {
9090
}
9191
};
9292

93+
class FlushingFileCollector : public llvm::FileCollectorBase {
94+
public:
95+
FlushingFileCollector(llvm::StringRef files_path, llvm::StringRef dirs_path,
96+
std::error_code &ec);
97+
98+
protected:
99+
void addFileImpl(llvm::StringRef file) override;
100+
101+
llvm::vfs::directory_iterator
102+
addDirectoryImpl(const llvm::Twine &dir,
103+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
104+
std::error_code &dir_ec) override;
105+
106+
llvm::Optional<llvm::raw_fd_ostream> m_files_os;
107+
llvm::Optional<llvm::raw_fd_ostream> m_dirs_os;
108+
};
109+
93110
class FileProvider : public Provider<FileProvider> {
94111
public:
95112
struct Info {
96113
static const char *name;
97114
static const char *file;
98115
};
99116

100-
FileProvider(const FileSpec &directory)
101-
: Provider(directory),
102-
m_collector(std::make_shared<llvm::FileCollector>(
103-
directory.CopyByAppendingPathComponent("root").GetPath(),
104-
directory.GetPath())) {}
117+
FileProvider(const FileSpec &directory) : Provider(directory) {
118+
std::error_code ec;
119+
m_collector = std::make_shared<FlushingFileCollector>(
120+
directory.CopyByAppendingPathComponent("files.txt").GetPath(),
121+
directory.CopyByAppendingPathComponent("dirs.txt").GetPath(), ec);
122+
if (ec)
123+
m_collector.reset();
124+
}
105125

106-
std::shared_ptr<llvm::FileCollector> GetFileCollector() {
126+
std::shared_ptr<llvm::FileCollectorBase> GetFileCollector() {
107127
return m_collector;
108128
}
109129

110130
void RecordInterestingDirectory(const llvm::Twine &dir);
111131
void RecordInterestingDirectoryRecursive(const llvm::Twine &dir);
112132

113-
void Keep() override {
114-
auto mapping = GetRoot().CopyByAppendingPathComponent(Info::file);
115-
// Temporary files that are removed during execution can cause copy errors.
116-
if (auto ec = m_collector->copyFiles(/*stop_on_error=*/false))
117-
return;
118-
m_collector->writeMapping(mapping.GetPath());
119-
}
120-
121133
static char ID;
122134

123135
private:
124-
std::shared_ptr<llvm::FileCollector> m_collector;
136+
std::shared_ptr<FlushingFileCollector> m_collector;
125137
};
126138

127139
/// Provider for the LLDB version number.

lldb/source/API/SBReproducer.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
#include "SBReproducerPrivate.h"
1010

11-
#include "SBReproducerPrivate.h"
1211
#include "lldb/API/LLDB.h"
1312
#include "lldb/API/SBAddress.h"
1413
#include "lldb/API/SBAttachInfo.h"
@@ -266,6 +265,27 @@ const char *SBReproducer::Replay(const char *path,
266265
return nullptr;
267266
}
268267

268+
const char *SBReproducer::Finalize(const char *path) {
269+
static std::string error;
270+
if (auto e = Reproducer::Initialize(ReproducerMode::Replay, FileSpec(path))) {
271+
error = llvm::toString(std::move(e));
272+
return error.c_str();
273+
}
274+
275+
repro::Loader *loader = repro::Reproducer::Instance().GetLoader();
276+
if (!loader) {
277+
error = "unable to get replay loader.";
278+
return error.c_str();
279+
}
280+
281+
if (auto e = repro::Finalize(loader)) {
282+
error = llvm::toString(std::move(e));
283+
return error.c_str();
284+
}
285+
286+
return nullptr;
287+
}
288+
269289
bool SBReproducer::Generate() {
270290
auto &r = Reproducer::Instance();
271291
if (auto generator = r.GetGenerator()) {
@@ -285,10 +305,11 @@ bool SBReproducer::SetAutoGenerate(bool b) {
285305
}
286306

287307
const char *SBReproducer::GetPath() {
288-
static std::string path;
308+
ConstString path;
289309
auto &r = Reproducer::Instance();
290-
path = r.GetReproducerPath().GetCString();
291-
return path.c_str();
310+
if (FileSpec reproducer_path = Reproducer::Instance().GetReproducerPath())
311+
path = ConstString(r.GetReproducerPath().GetCString());
312+
return path.GetCString();
292313
}
293314

294315
void SBReproducer::SetWorkingDirectory(const char *path) {

lldb/source/Commands/CommandObjectReproducer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ class CommandObjectReproducerGenerate : public CommandObjectParsed {
192192
auto &r = Reproducer::Instance();
193193
if (auto generator = r.GetGenerator()) {
194194
generator->Keep();
195+
if (llvm::Error e = repro::Finalize(r.GetReproducerPath())) {
196+
SetError(result, std::move(e));
197+
return result.Succeeded();
198+
}
195199
} else if (r.IsReplaying()) {
196200
// Make this operation a NO-OP in replay mode.
197201
result.SetStatus(eReturnStatusSuccessFinishNoResult);

lldb/source/Host/common/FileSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void FileSystem::Initialize() {
4949
InstanceImpl().emplace();
5050
}
5151

52-
void FileSystem::Initialize(std::shared_ptr<FileCollector> collector) {
52+
void FileSystem::Initialize(std::shared_ptr<FileCollectorBase> collector) {
5353
lldbassert(!InstanceImpl() && "Already initialized.");
5454
InstanceImpl().emplace(collector);
5555
}

lldb/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ModuleDependencyCollectorAdaptor
1818
: public clang::ModuleDependencyCollector {
1919
public:
2020
ModuleDependencyCollectorAdaptor(
21-
std::shared_ptr<llvm::FileCollector> file_collector)
21+
std::shared_ptr<llvm::FileCollectorBase> file_collector)
2222
: clang::ModuleDependencyCollector(""), m_file_collector(file_collector) {
2323
}
2424

@@ -33,7 +33,7 @@ class ModuleDependencyCollectorAdaptor
3333
void writeFileMap() override {}
3434

3535
private:
36-
std::shared_ptr<llvm::FileCollector> m_file_collector;
36+
std::shared_ptr<llvm::FileCollectorBase> m_file_collector;
3737
};
3838
} // namespace lldb_private
3939

lldb/source/Utility/Reproducer.cpp

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,12 @@ Generator::Generator(FileSpec root) : m_root(MakeAbsolute(std::move(root))) {
176176

177177
Generator::~Generator() {
178178
if (!m_done) {
179-
if (m_auto_generate)
179+
if (m_auto_generate) {
180180
Keep();
181-
else
181+
llvm::cantFail(Finalize(GetRoot()));
182+
} else {
182183
Discard();
184+
}
183185
}
184186
}
185187

@@ -359,3 +361,58 @@ void Verifier::Verify(
359361
}
360362
}
361363
}
364+
365+
static llvm::Error addPaths(StringRef path,
366+
function_ref<void(StringRef)> callback) {
367+
auto buffer = llvm::MemoryBuffer::getFile(path);
368+
if (!buffer)
369+
return errorCodeToError(buffer.getError());
370+
371+
SmallVector<StringRef, 0> paths;
372+
(*buffer)->getBuffer().split(paths, '\0');
373+
for (StringRef p : paths) {
374+
if (!p.empty())
375+
callback(p);
376+
}
377+
378+
return errorCodeToError(llvm::sys::fs::remove(path));
379+
}
380+
381+
llvm::Error repro::Finalize(Loader *loader) {
382+
if (!loader)
383+
return make_error<StringError>("invalid loader",
384+
llvm::inconvertibleErrorCode());
385+
386+
FileSpec reproducer_root = loader->GetRoot();
387+
std::string files_path =
388+
reproducer_root.CopyByAppendingPathComponent("files.txt").GetPath();
389+
std::string dirs_path =
390+
reproducer_root.CopyByAppendingPathComponent("dirs.txt").GetPath();
391+
392+
FileCollector collector(
393+
reproducer_root.CopyByAppendingPathComponent("root").GetPath(),
394+
reproducer_root.GetPath());
395+
396+
if (Error e =
397+
addPaths(files_path, [&](StringRef p) { collector.addFile(p); }))
398+
return e;
399+
400+
if (Error e =
401+
addPaths(dirs_path, [&](StringRef p) { collector.addDirectory(p); }))
402+
return e;
403+
404+
FileSpec mapping =
405+
reproducer_root.CopyByAppendingPathComponent(FileProvider::Info::file);
406+
if (auto ec = collector.copyFiles(/*stop_on_error=*/false))
407+
return errorCodeToError(ec);
408+
collector.writeMapping(mapping.GetPath());
409+
410+
return llvm::Error::success();
411+
}
412+
413+
llvm::Error repro::Finalize(const FileSpec &root) {
414+
Loader loader(root);
415+
if (Error e = loader.LoadIndex())
416+
return e;
417+
return Finalize(&loader);
418+
}

lldb/source/Utility/ReproducerProvider.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "lldb/Utility/ReproducerProvider.h"
1010
#include "lldb/Utility/ProcessInfo.h"
11+
#include "llvm/ADT/ScopeExit.h"
1112
#include "llvm/Support/FileSystem.h"
1213
#include "llvm/Support/WithColor.h"
1314
#include "llvm/Support/raw_ostream.h"
@@ -44,6 +45,40 @@ void VersionProvider::Keep() {
4445
os << m_version << "\n";
4546
}
4647

48+
FlushingFileCollector::FlushingFileCollector(llvm::StringRef files_path,
49+
llvm::StringRef dirs_path,
50+
std::error_code &ec) {
51+
auto clear = llvm::make_scope_exit([this]() {
52+
m_files_os.reset();
53+
m_dirs_os.reset();
54+
});
55+
m_files_os.emplace(files_path, ec, llvm::sys::fs::OF_Append);
56+
if (ec)
57+
return;
58+
m_dirs_os.emplace(dirs_path, ec, llvm::sys::fs::OF_Append);
59+
if (ec)
60+
return;
61+
clear.release();
62+
}
63+
64+
void FlushingFileCollector::addFileImpl(StringRef file) {
65+
if (m_files_os) {
66+
*m_files_os << file << '\0';
67+
m_files_os->flush();
68+
}
69+
}
70+
71+
llvm::vfs::directory_iterator
72+
FlushingFileCollector::addDirectoryImpl(const Twine &dir,
73+
IntrusiveRefCntPtr<vfs::FileSystem> vfs,
74+
std::error_code &dir_ec) {
75+
if (m_dirs_os) {
76+
*m_dirs_os << dir << '\0';
77+
m_dirs_os->flush();
78+
}
79+
return vfs->dir_begin(dir, dir_ec);
80+
}
81+
4782
void FileProvider::RecordInterestingDirectory(const llvm::Twine &dir) {
4883
if (m_collector)
4984
m_collector->addFile(dir);

lldb/test/Shell/Reproducer/TestCaptureEnvOverride.test

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
# RUN: LLDB_CAPTURE_REPRODUCER=0 %lldb -b -o 'reproducer status' --capture --capture-path %t.repro | FileCheck %s --check-prefix OFF
1111
# RUN: LLDB_CAPTURE_REPRODUCER=0 %lldb -b -o 'reproducer status' --capture | FileCheck %s --check-prefix OFF
12-
# RUN: LLDB_CAPTURE_REPRODUCER=OFF %lldb -b -o 'reproducer status' --capture --capture-path %t.repro | FileCheck %s --check-prefix OFF
13-
# RUN: LLDB_CAPTURE_REPRODUCER=off %lldb -b -o 'reproducer status' --capture | FileCheck %s --check-prefix OFF
1412

1513
# RUN: LLDB_CAPTURE_REPRODUCER=bogus %lldb -b -o 'reproducer status' --capture | FileCheck %s --check-prefix CAPTURE
1614
# RUN: LLDB_CAPTURE_REPRODUCER=bogus %lldb -b -o 'reproducer status' | FileCheck %s --check-prefix OFF
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# RUN: mkdir -p %t.repro
2+
# RUN: touch %t.known.file
3+
# RUN: mkdir -p %t.known.dir
4+
# RUN: touch %t.repro/index.yaml
5+
# RUN: echo -n "%t.known.file" > %t.repro/files.txt
6+
# RUN: echo -n "%t.known.dir" > %t.repro/dirs.txt
7+
8+
# RUN: %lldb --reproducer-finalize %t.repro 2>&1 | FileCheck %s
9+
# CHECK-NOT: error
10+
# CHECK: Reproducer written to
11+
12+
# RUN: echo "CHECK-DAG: %t.known.file" > %t.filecheck
13+
# RUN: echo "CHECK-DAG %t.known.dir" >> %t.filecheck
14+
# RUN: cat %t.repro/files.yaml | FileCheck %t.filecheck

0 commit comments

Comments
 (0)