summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/API/CMakeLists.txt1
-rw-r--r--lldb/source/API/SBReproducer.cpp51
-rw-r--r--lldb/source/API/SBReproducerPrivate.h72
-rw-r--r--lldb/source/Utility/ReproducerInstrumentation.cpp53
4 files changed, 176 insertions, 1 deletions
diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt
index e4ec64e537a..f5c33ed6ab5 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -50,6 +50,7 @@ add_lldb_library(liblldb SHARED
SBProcessInfo.cpp
SBQueue.cpp
SBQueueItem.cpp
+ SBReproducer.cpp
SBSection.cpp
SBSourceManager.cpp
SBStream.cpp
diff --git a/lldb/source/API/SBReproducer.cpp b/lldb/source/API/SBReproducer.cpp
new file mode 100644
index 00000000000..f453f8cdaa3
--- /dev/null
+++ b/lldb/source/API/SBReproducer.cpp
@@ -0,0 +1,51 @@
+//===-- SBReproducer.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SBReproducerPrivate.h"
+
+#include "lldb/API/LLDB.h"
+#include "lldb/API/SBAddress.h"
+#include "lldb/API/SBAttachInfo.h"
+#include "lldb/API/SBBlock.h"
+#include "lldb/API/SBBreakpoint.h"
+#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBData.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBDeclaration.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBHostOS.h"
+#include "lldb/API/SBReproducer.h"
+
+#include "lldb/Host/FileSystem.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::repro;
+
+SBRegistry::SBRegistry() {}
+
+bool SBReproducer::Replay() {
+ repro::Loader *loader = repro::Reproducer::Instance().GetLoader();
+ if (!loader)
+ return false;
+
+ FileSpec file = loader->GetFile<SBInfo>();
+ if (!file)
+ return false;
+
+ SBRegistry registry;
+ registry.Replay(file);
+
+ return true;
+}
+
+char lldb_private::repro::SBProvider::ID = 0;
+const char *SBInfo::name = "sbapi";
+const char *SBInfo::file = "sbapi.bin";
diff --git a/lldb/source/API/SBReproducerPrivate.h b/lldb/source/API/SBReproducerPrivate.h
new file mode 100644
index 00000000000..b550f5ed3da
--- /dev/null
+++ b/lldb/source/API/SBReproducerPrivate.h
@@ -0,0 +1,72 @@
+//===-- SBReproducerPrivate.h -----------------------------------*- C++ -*-===//
+//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_API_SBREPRODUCER_PRIVATE_H
+#define LLDB_API_SBREPRODUCER_PRIVATE_H
+
+#include "lldb/API/SBReproducer.h"
+
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Reproducer.h"
+#include "lldb/Utility/ReproducerInstrumentation.h"
+
+#include "llvm/ADT/DenseMap.h"
+
+#define LLDB_GET_INSTRUMENTATION_DATA() \
+ lldb_private::repro::GetInstrumentationData()
+
+namespace lldb_private {
+namespace repro {
+
+class SBRegistry : public Registry {
+public:
+ SBRegistry();
+};
+
+struct SBInfo {
+ static const char *name;
+ static const char *file;
+};
+
+class SBProvider : public Provider<SBProvider> {
+public:
+ typedef SBInfo info;
+
+ SBProvider(const FileSpec &directory)
+ : Provider(directory),
+ m_stream(directory.CopyByAppendingPathComponent("sbapi.bin").GetPath(),
+ m_ec, llvm::sys::fs::OpenFlags::F_None),
+ m_serializer(m_stream) {}
+
+ Serializer &GetSerializer() { return m_serializer; }
+ Registry &GetRegistry() { return m_registry; }
+
+ static char ID;
+
+private:
+ std::error_code m_ec;
+ llvm::raw_fd_ostream m_stream;
+ Serializer m_serializer;
+ SBRegistry m_registry;
+};
+
+inline InstrumentationData GetInstrumentationData() {
+ if (auto *g = lldb_private::repro::Reproducer::Instance().GetGenerator()) {
+ auto &p = g->GetOrCreate<SBProvider>();
+ return {p.GetSerializer(), p.GetRegistry()};
+ }
+ return {};
+}
+
+} // namespace repro
+} // namespace lldb_private
+
+#endif
diff --git a/lldb/source/Utility/ReproducerInstrumentation.cpp b/lldb/source/Utility/ReproducerInstrumentation.cpp
index 8b53c48872f..984540d1c0b 100644
--- a/lldb/source/Utility/ReproducerInstrumentation.cpp
+++ b/lldb/source/Utility/ReproducerInstrumentation.cpp
@@ -34,11 +34,62 @@ template <> const char *Deserializer::Deserialize<const char *>() {
return str;
}
+bool Registry::Replay(const FileSpec &file) {
+ auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath());
+ if (auto err = error_or_file.getError())
+ return false;
+
+ return Replay((*error_or_file)->getBuffer());
+}
+
+bool Registry::Replay(llvm::StringRef buffer) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_API);
+
+ Deserializer deserializer(buffer);
+ while (deserializer.HasData(1)) {
+ unsigned id = deserializer.Deserialize<unsigned>();
+ LLDB_LOG(log, "Replaying function #{0}", id);
+ m_ids[id]->operator()(deserializer);
+ }
+
+ return true;
+}
+
+void Registry::DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer) {
+ const unsigned id = m_replayers.size() + 1;
+ assert(m_replayers.find(RunID) == m_replayers.end());
+ m_replayers[RunID] = std::make_pair(std::move(replayer), id);
+ m_ids[id] = m_replayers[RunID].first.get();
+}
+
+unsigned Registry::GetID(uintptr_t addr) {
+ unsigned id = m_replayers[addr].second;
+ assert(id != 0 && "Forgot to add function to registry?");
+ return id;
+}
+
unsigned ObjectToIndex::GetIndexForObjectImpl(void *object) {
- std::lock_guard<std::mutex> guard(m_mutex);
unsigned index = m_mapping.size() + 1;
auto it = m_mapping.find(object);
if (it == m_mapping.end())
m_mapping[object] = index;
return m_mapping[object];
}
+
+Recorder::Recorder(Serializer &serializer, Registry &registry,
+ llvm::StringRef pretty_func)
+ : m_serializer(serializer), m_registry(registry),
+ m_pretty_func(pretty_func), m_local_boundary(false),
+ m_result_recorded(true) {
+ if (!g_global_boundary) {
+ g_global_boundary = true;
+ m_local_boundary = true;
+ }
+}
+
+Recorder::~Recorder() {
+ assert(m_result_recorded && "Did you forget LLDB_RECORD_RESULT?");
+ UpdateBoundary();
+}
+
+bool lldb_private::repro::Recorder::g_global_boundary;
OpenPOWER on IntegriCloud