diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lldb/source/API/SBReproducer.cpp | 51 | ||||
-rw-r--r-- | lldb/source/API/SBReproducerPrivate.h | 72 | ||||
-rw-r--r-- | lldb/source/Utility/ReproducerInstrumentation.cpp | 53 |
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 ®istry, + 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; |