diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
commit | 5f29bb8a675e8f96452b632e7129113f7dec850e (patch) | |
tree | 3d3f2a0d3ad10872a4dcaba8ec8d1d20c87ab147 /source/Utility/ReproducerInstrumentation.cpp | |
parent | 88c643b6fec27eec436c8d138fee6346e92337d6 (diff) |
Notes
Diffstat (limited to 'source/Utility/ReproducerInstrumentation.cpp')
-rw-r--r-- | source/Utility/ReproducerInstrumentation.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/source/Utility/ReproducerInstrumentation.cpp b/source/Utility/ReproducerInstrumentation.cpp new file mode 100644 index 000000000000..473786ef4d3e --- /dev/null +++ b/source/Utility/ReproducerInstrumentation.cpp @@ -0,0 +1,122 @@ +//===-- ReproducerInstrumentation.cpp ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/ReproducerInstrumentation.h" +#include "lldb/Utility/Reproducer.h" + +using namespace lldb_private; +using namespace lldb_private::repro; + +void *IndexToObject::GetObjectForIndexImpl(unsigned idx) { + return m_mapping.lookup(idx); +} + +void IndexToObject::AddObjectForIndexImpl(unsigned idx, void *object) { + assert(idx != 0 && "Cannot add object for sentinel"); + m_mapping[idx] = object; +} + +template <> char *Deserializer::Deserialize<char *>() { + return const_cast<char *>(Deserialize<const char *>()); +} + +template <> const char *Deserializer::Deserialize<const char *>() { + auto pos = m_buffer.find('\0'); + if (pos == llvm::StringRef::npos) + return nullptr; + const char *str = m_buffer.data(); + m_buffer = m_buffer.drop_front(pos + 1); + 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) { +#ifndef LLDB_REPRO_INSTR_TRACE + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_API); +#endif + + Deserializer deserializer(buffer); + while (deserializer.HasData(1)) { + unsigned id = deserializer.Deserialize<unsigned>(); + +#ifndef LLDB_REPRO_INSTR_TRACE + LLDB_LOG(log, "Replaying {0}: {1}", id, GetSignature(id)); +#else + llvm::errs() << "Replaying " << id << ": " << GetSignature(id) << "\n"; +#endif + + GetReplayer(id)->operator()(deserializer); + } + + return true; +} + +void Registry::DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer, + SignatureStr signature) { + 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] = + std::make_pair(m_replayers[RunID].first.get(), std::move(signature)); +} + +unsigned Registry::GetID(uintptr_t addr) { + unsigned id = m_replayers[addr].second; + assert(id != 0 && "Forgot to add function to registry?"); + return id; +} + +std::string Registry::GetSignature(unsigned id) { + assert(m_ids.count(id) != 0 && "ID not in registry"); + return m_ids[id].second.ToString(); +} + +Replayer *Registry::GetReplayer(unsigned id) { + assert(m_ids.count(id) != 0 && "ID not in registry"); + return m_ids[id].first; +} + +std::string Registry::SignatureStr::ToString() const { + return (result + (result.empty() ? "" : " ") + scope + "::" + name + args) + .str(); +} + +unsigned ObjectToIndex::GetIndexForObjectImpl(const void *object) { + 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(llvm::StringRef pretty_func, std::string &&pretty_args) + : m_serializer(nullptr), m_pretty_func(pretty_func), + m_pretty_args(pretty_args), m_local_boundary(false), + m_result_recorded(true) { + if (!g_global_boundary) { + g_global_boundary = true; + m_local_boundary = true; + + LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "{0} ({1})", + m_pretty_func, m_pretty_args); + } +} + +Recorder::~Recorder() { + assert(m_result_recorded && "Did you forget LLDB_RECORD_RESULT?"); + UpdateBoundary(); +} + +bool lldb_private::repro::Recorder::g_global_boundary; |