| //===-- 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) { |
| 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(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(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; |