Index: lldb/include/lldb/Utility/ReproducerInstrumentation.h =================================================================== --- lldb/include/lldb/Utility/ReproducerInstrumentation.h +++ lldb/include/lldb/Utility/ReproducerInstrumentation.h @@ -18,15 +18,37 @@ #include +// Define LLDB_REPRO_INSTR_TRACE to trace to stderr instead of LLDB's log +// infrastructure. This is useful when you need to see traces before the logger +// is initialized or enabled. +// #define LLDB_REPRO_INSTR_TRACE + #define LLDB_REGISTER_CONSTRUCTOR(Class, Signature) \ - Register(&construct::doit) + { \ + unsigned id = \ + Register(&construct::doit); \ + RegisterSignature(id, "", #Class, #Class, #Signature); \ + } + #define LLDB_REGISTER_METHOD(Result, Class, Method, Signature) \ - Register(&invoke::method<&Class::Method>::doit) + { \ + unsigned id = Register( \ + &invoke::method<&Class::Method>::doit); \ + RegisterSignature(id, #Result, #Class, #Method, #Signature); \ + } #define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature) \ - Register(&invoke::method_const<&Class::Method>::doit) + { \ + unsigned id = Register( \ + &invoke::method_const<&Class::Method>::doit); \ + RegisterSignature(id, #Result, #Class, #Method, #Signature); \ + } #define LLDB_REGISTER_STATIC_METHOD(Result, Class, Method, Signature) \ - Register(static_cast(&Class::Method)) + { \ + unsigned id = Register( \ + static_cast(&Class::Method)); \ + RegisterSignature(id, #Result, #Class, #Method, #Signature); \ + } #define LLDB_RECORD_CONSTRUCTOR(Class, Signature, ...) \ LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "{0}", \ @@ -224,6 +246,9 @@ /// Deserialize and interpret value as T. template T Deserialize() { +#ifdef LLDB_REPRO_INSTR_TRACE + llvm::errs() << "Deserializing with " << LLVM_PRETTY_FUNCTION << "\n"; +#endif return Read(typename serializer_tag::type()); } @@ -376,14 +401,16 @@ virtual ~Registry() = default; /// Register a default replayer for a function. - template void Register(Signature *f) { - DoRegister(uintptr_t(f), llvm::make_unique>(f)); + template unsigned Register(Signature *f) { + return DoRegister(uintptr_t(f), + llvm::make_unique>(f)); } /// Register a replayer that invokes a custom function with the same /// signature as the replayed function. - template void Register(Signature *f, Signature *g) { - DoRegister(uintptr_t(f), llvm::make_unique>(g)); + template unsigned Register(Signature *f, Signature *g) { + return DoRegister(uintptr_t(f), + llvm::make_unique>(g)); } /// Replay functions from a file. @@ -395,9 +422,16 @@ /// Returns the ID for a given function address. unsigned GetID(uintptr_t addr); + /// Return the signature for the given id. + llvm::StringRef GetSignature(unsigned id) { return m_signatures[id]; } + protected: /// Register the given replayer for a function (and the ID mapping). - void DoRegister(uintptr_t RunID, std::unique_ptr replayer); + unsigned DoRegister(uintptr_t RunID, std::unique_ptr replayer); + + void RegisterSignature(unsigned id, llvm::StringRef result, + llvm::StringRef theclass, llvm::StringRef method, + llvm::StringRef signature); private: /// Mapping of function addresses to replayers and their ID. @@ -406,6 +440,9 @@ /// Mapping of IDs to replayer instances. std::map m_ids; + + /// Mapping of IDs to string for debugging. + std::map m_signatures; }; /// To be used as the "Runtime ID" of a constructor. It also invokes the @@ -551,8 +588,12 @@ unsigned id = m_registry.GetID(uintptr_t(f)); - LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "Recording ({0}) '{1}'", +#ifndef LLDB_REPRO_INSTR_TRACE + LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "Recording {0}: {1}", id, m_pretty_func); +#else + llvm::errs() << "Recording " << id << ": " << m_pretty_func << "\n"; +#endif m_serializer.SerializeAll(id); m_serializer.SerializeAll(args...); @@ -574,8 +615,12 @@ unsigned id = m_registry.GetID(uintptr_t(f)); - LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "Recording ({0}) '{1}'", +#ifndef LLDB_REPRO_INSTR_TRACE + LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "Recording {0}: {1}", id, m_pretty_func); +#else + llvm::errs() << "Recording " << id << ": " << m_pretty_func << "\n"; +#endif m_serializer.SerializeAll(id); m_serializer.SerializeAll(args...); Index: lldb/source/Utility/ReproducerInstrumentation.cpp =================================================================== --- lldb/source/Utility/ReproducerInstrumentation.cpp +++ lldb/source/Utility/ReproducerInstrumentation.cpp @@ -44,22 +44,38 @@ bool Registry::Replay(llvm::StringRef buffer) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_API); - Deserializer deserializer(buffer); while (deserializer.HasData(1)) { unsigned id = deserializer.Deserialize(); - LLDB_LOG(log, "Replaying function #{0}", id); +#ifndef LLDB_REPRO_INSTR_TRACE + LLDB_LOG(log, "Replaying {0}: {1}", id, GetSignature(id)); +#else + (void)log; + llvm::errs() << "Replaying " << id << ": " << GetSignature(id) << "\n"; +#endif + assert(m_ids.count(id) != 0 && "Invalid id?"); m_ids[id]->operator()(deserializer); } return true; } -void Registry::DoRegister(uintptr_t RunID, std::unique_ptr replayer) { +unsigned Registry::DoRegister(uintptr_t RunID, + std::unique_ptr 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(); + return id; +} + +void Registry::RegisterSignature(unsigned id, llvm::StringRef result, + llvm::StringRef theclass, + llvm::StringRef method, + llvm::StringRef signature) { + m_signatures[id] = (result + (result.empty() ? "" : " ") + theclass + + "::" + method + signature) + .str(); } unsigned Registry::GetID(uintptr_t addr) {