1//===-- ReproducerInstrumentation.cpp ---------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "lldb/Utility/ReproducerInstrumentation.h" 10#include "lldb/Utility/Reproducer.h" 11 12using namespace lldb_private; 13using namespace lldb_private::repro; 14 15void *IndexToObject::GetObjectForIndexImpl(unsigned idx) { 16 return m_mapping.lookup(idx); 17} 18 19void IndexToObject::AddObjectForIndexImpl(unsigned idx, void *object) { 20 assert(idx != 0 && "Cannot add object for sentinel"); 21 m_mapping[idx] = object; 22} 23 24template <> char *Deserializer::Deserialize<char *>() { 25 return const_cast<char *>(Deserialize<const char *>()); 26} 27 28template <> const char *Deserializer::Deserialize<const char *>() { 29 auto pos = m_buffer.find('\0'); 30 if (pos == llvm::StringRef::npos) 31 return nullptr; 32 const char *str = m_buffer.data(); 33 m_buffer = m_buffer.drop_front(pos + 1); 34 return str; 35} 36 37bool Registry::Replay(const FileSpec &file) { 38 auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); 39 if (auto err = error_or_file.getError()) 40 return false; 41 42 return Replay((*error_or_file)->getBuffer()); 43} 44 45bool Registry::Replay(llvm::StringRef buffer) { 46#ifndef LLDB_REPRO_INSTR_TRACE 47 Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_API); 48#endif 49 50 Deserializer deserializer(buffer); 51 while (deserializer.HasData(1)) { 52 unsigned id = deserializer.Deserialize<unsigned>(); 53 54#ifndef LLDB_REPRO_INSTR_TRACE 55 LLDB_LOG(log, "Replaying {0}: {1}", id, GetSignature(id)); 56#else 57 llvm::errs() << "Replaying " << id << ": " << GetSignature(id) << "\n"; 58#endif 59 60 GetReplayer(id)->operator()(deserializer); 61 } 62 63 return true; 64} 65 66void Registry::DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer, 67 SignatureStr signature) { 68 const unsigned id = m_replayers.size() + 1; 69 assert(m_replayers.find(RunID) == m_replayers.end()); 70 m_replayers[RunID] = std::make_pair(std::move(replayer), id); 71 m_ids[id] = 72 std::make_pair(m_replayers[RunID].first.get(), std::move(signature)); 73} 74 75unsigned Registry::GetID(uintptr_t addr) { 76 unsigned id = m_replayers[addr].second; 77 assert(id != 0 && "Forgot to add function to registry?"); 78 return id; 79} 80 81std::string Registry::GetSignature(unsigned id) { 82 assert(m_ids.count(id) != 0 && "ID not in registry"); 83 return m_ids[id].second.ToString(); 84} 85 86Replayer *Registry::GetReplayer(unsigned id) { 87 assert(m_ids.count(id) != 0 && "ID not in registry"); 88 return m_ids[id].first; 89} 90 91std::string Registry::SignatureStr::ToString() const { 92 return (result + (result.empty() ? "" : " ") + scope + "::" + name + args) 93 .str(); 94} 95 96unsigned ObjectToIndex::GetIndexForObjectImpl(const void *object) { 97 unsigned index = m_mapping.size() + 1; 98 auto it = m_mapping.find(object); 99 if (it == m_mapping.end()) 100 m_mapping[object] = index; 101 return m_mapping[object]; 102} 103 104Recorder::Recorder(llvm::StringRef pretty_func, std::string &&pretty_args) 105 : m_serializer(nullptr), m_pretty_func(pretty_func), 106 m_pretty_args(pretty_args), m_local_boundary(false), 107 m_result_recorded(true) { 108 if (!g_global_boundary) { 109 g_global_boundary = true; 110 m_local_boundary = true; 111 112 LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "{0} ({1})", 113 m_pretty_func, m_pretty_args); 114 } 115} 116 117Recorder::~Recorder() { 118 assert(m_result_recorded && "Did you forget LLDB_RECORD_RESULT?"); 119 UpdateBoundary(); 120} 121 122bool lldb_private::repro::Recorder::g_global_boundary; 123