Index: include/lldb/Utility/ReproducerInstrumentation.h =================================================================== --- include/lldb/Utility/ReproducerInstrumentation.h +++ include/lldb/Utility/ReproducerInstrumentation.h @@ -18,15 +18,24 @@ #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) + Register(&construct::doit, "", #Class, \ + #Class, #Signature) #define LLDB_REGISTER_METHOD(Result, Class, Method, Signature) \ - Register(&invoke::method<&Class::Method>::doit) + Register(&invoke::method<&Class::Method>::doit, \ + #Result, #Class, #Method, #Signature) #define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature) \ Register(&invoke::method_const<&Class::Method>::doit) + Signature const>::method_const<&Class::Method>::doit, \ + #Result, #Class, #Method, #Signature) #define LLDB_REGISTER_STATIC_METHOD(Result, Class, Method, Signature) \ - Register(static_cast(&Class::Method)) + Register(static_cast(&Class::Method), \ + #Result, #Class, #Method, #Signature) #define LLDB_RECORD_CONSTRUCTOR(Class, Signature, ...) \ LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "{0}", \ @@ -224,6 +233,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()); } @@ -371,19 +383,41 @@ /// IDs can be serialized and deserialized to replay a function. Functions need /// to be registered with the registry for this to work. class Registry { +private: + struct SignatureStr { + SignatureStr(llvm::StringRef result = {}, llvm::StringRef scope = {}, + llvm::StringRef name = {}, llvm::StringRef args = {}) + : result(result), scope(scope), name(name), args(args) {} + + std::string ToString() const; + + llvm::StringRef result; + llvm::StringRef scope; + llvm::StringRef name; + llvm::StringRef args; + }; + public: Registry() = default; virtual ~Registry() = default; /// Register a default replayer for a function. - template void Register(Signature *f) { - DoRegister(uintptr_t(f), llvm::make_unique>(f)); + template + void Register(Signature *f, llvm::StringRef result = {}, + llvm::StringRef scope = {}, llvm::StringRef name = {}, + llvm::StringRef args = {}) { + DoRegister(uintptr_t(f), llvm::make_unique>(f), + SignatureStr(result, scope, name, args)); } /// 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 + void Register(Signature *f, Signature *g, llvm::StringRef result = {}, + llvm::StringRef scope = {}, llvm::StringRef name = {}, + llvm::StringRef args = {}) { + DoRegister(uintptr_t(f), llvm::make_unique>(g), + SignatureStr(result, scope, name, args)); } /// Replay functions from a file. @@ -397,15 +431,19 @@ protected: /// Register the given replayer for a function (and the ID mapping). - void DoRegister(uintptr_t RunID, std::unique_ptr replayer); + void DoRegister(uintptr_t RunID, std::unique_ptr replayer, + SignatureStr signature); private: + std::string GetSignature(unsigned id); + Replayer *GetReplayer(unsigned id); + /// Mapping of function addresses to replayers and their ID. std::map, unsigned>> m_replayers; /// Mapping of IDs to replayer instances. - std::map m_ids; + std::map> m_ids; }; /// To be used as the "Runtime ID" of a constructor. It also invokes the @@ -551,8 +589,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 +616,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: source/Utility/ReproducerInstrumentation.cpp =================================================================== --- source/Utility/ReproducerInstrumentation.cpp +++ source/Utility/ReproducerInstrumentation.cpp @@ -43,23 +43,33 @@ } 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(); - LLDB_LOG(log, "Replaying function #{0}", id); - m_ids[id]->operator()(deserializer); + +#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) { +void Registry::DoRegister(uintptr_t RunID, std::unique_ptr 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] = m_replayers[RunID].first.get(); + m_ids[id] = + std::make_pair(m_replayers[RunID].first.get(), std::move(signature)); } unsigned Registry::GetID(uintptr_t addr) { @@ -68,6 +78,21 @@ 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);