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 12 using namespace lldb_private; 13 using namespace lldb_private::repro; 14 15 void *IndexToObject::GetObjectForIndexImpl(unsigned idx) { 16 return m_mapping.lookup(idx); 17 } 18 19 void IndexToObject::AddObjectForIndexImpl(unsigned idx, void *object) { 20 assert(idx != 0 && "Cannot add object for sentinel"); 21 m_mapping[idx] = object; 22 } 23 24 template <> char *Deserializer::Deserialize<char *>() { 25 return const_cast<char *>(Deserialize<const char *>()); 26 } 27 28 template <> 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 37 bool 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 45 bool 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 66 void 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 75 unsigned 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 81 std::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 86 Replayer *Registry::GetReplayer(unsigned id) { 87 assert(m_ids.count(id) != 0 && "ID not in registry"); 88 return m_ids[id].first; 89 } 90 91 std::string Registry::SignatureStr::ToString() const { 92 return (result + (result.empty() ? "" : " ") + scope + "::" + name + args) 93 .str(); 94 } 95 96 unsigned 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 104 Recorder::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 117 Recorder::~Recorder() { 118 assert(m_result_recorded && "Did you forget LLDB_RECORD_RESULT?"); 119 UpdateBoundary(); 120 } 121 122 bool lldb_private::repro::Recorder::g_global_boundary; 123