Skip to content

Commit 8c436ce

Browse files
committed
[Reproducers] Add more logging to reproducer instrumentation
Debugging issues with instrumentation capture and replay can be particularly tricky, especially because part of the process takes places even before the debugger is initialized. This patch adds more logging capabilities to these classes, hidden behind a macro define. Differential revision: https://reviews.llvm.org/D58566 llvm-svn: 355002
1 parent d78164a commit 8c436ce

File tree

2 files changed

+87
-16
lines changed

2 files changed

+87
-16
lines changed

lldb/include/lldb/Utility/ReproducerInstrumentation.h

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,24 @@
1818

1919
#include <map>
2020

21+
// Define LLDB_REPRO_INSTR_TRACE to trace to stderr instead of LLDB's log
22+
// infrastructure. This is useful when you need to see traces before the logger
23+
// is initialized or enabled.
24+
#define LLDB_REPRO_INSTR_TRACE
25+
2126
#define LLDB_REGISTER_CONSTRUCTOR(Class, Signature) \
22-
Register<Class * Signature>(&construct<Class Signature>::doit)
27+
Register<Class * Signature>(&construct<Class Signature>::doit, "", #Class, \
28+
#Class, #Signature)
2329
#define LLDB_REGISTER_METHOD(Result, Class, Method, Signature) \
24-
Register(&invoke<Result(Class::*) Signature>::method<&Class::Method>::doit)
30+
Register(&invoke<Result(Class::*) Signature>::method<&Class::Method>::doit, \
31+
#Result, #Class, #Method, #Signature)
2532
#define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature) \
2633
Register(&invoke<Result(Class::*) \
27-
Signature const>::method_const<&Class::Method>::doit)
34+
Signature const>::method_const<&Class::Method>::doit, \
35+
#Result, #Class, #Method, #Signature)
2836
#define LLDB_REGISTER_STATIC_METHOD(Result, Class, Method, Signature) \
29-
Register<Result Signature>(static_cast<Result(*) Signature>(&Class::Method))
37+
Register<Result Signature>(static_cast<Result(*) Signature>(&Class::Method), \
38+
#Result, #Class, #Method, #Signature)
3039

3140
#define LLDB_RECORD_CONSTRUCTOR(Class, Signature, ...) \
3241
LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "{0}", \
@@ -224,6 +233,9 @@ class Deserializer {
224233
225234
/// Deserialize and interpret value as T.
226235
template <typename T> T Deserialize() {
236+
#ifdef LLDB_REPRO_INSTR_TRACE
237+
llvm::errs() << "Deserializing with " << LLVM_PRETTY_FUNCTION << "\n";
238+
#endif
227239
return Read<T>(typename serializer_tag<T>::type());
228240
}
229241
@@ -371,19 +383,41 @@ struct DefaultReplayer<void(Args...)> : public Replayer {
371383
/// IDs can be serialized and deserialized to replay a function. Functions need
372384
/// to be registered with the registry for this to work.
373385
class Registry {
386+
private:
387+
struct SignatureStr {
388+
SignatureStr(llvm::StringRef result = {}, llvm::StringRef scope = {},
389+
llvm::StringRef name = {}, llvm::StringRef args = {})
390+
: result(result), scope(scope), name(name), args(args) {}
391+
392+
std::string ToString() const;
393+
394+
llvm::StringRef result;
395+
llvm::StringRef scope;
396+
llvm::StringRef name;
397+
llvm::StringRef args;
398+
};
399+
374400
public:
375401
Registry() = default;
376402
virtual ~Registry() = default;
377403
378404
/// Register a default replayer for a function.
379-
template <typename Signature> void Register(Signature *f) {
380-
DoRegister(uintptr_t(f), llvm::make_unique<DefaultReplayer<Signature>>(f));
405+
template <typename Signature>
406+
void Register(Signature *f, llvm::StringRef result = {},
407+
llvm::StringRef scope = {}, llvm::StringRef name = {},
408+
llvm::StringRef args = {}) {
409+
DoRegister(uintptr_t(f), llvm::make_unique<DefaultReplayer<Signature>>(f),
410+
SignatureStr(result, scope, name, args));
381411
}
382412
383413
/// Register a replayer that invokes a custom function with the same
384414
/// signature as the replayed function.
385-
template <typename Signature> void Register(Signature *f, Signature *g) {
386-
DoRegister(uintptr_t(f), llvm::make_unique<DefaultReplayer<Signature>>(g));
415+
template <typename Signature>
416+
void Register(Signature *f, Signature *g, llvm::StringRef result = {},
417+
llvm::StringRef scope = {}, llvm::StringRef name = {},
418+
llvm::StringRef args = {}) {
419+
DoRegister(uintptr_t(f), llvm::make_unique<DefaultReplayer<Signature>>(g),
420+
SignatureStr(result, scope, name, args));
387421
}
388422
389423
/// Replay functions from a file.
@@ -397,15 +431,19 @@ class Registry {
397431
398432
protected:
399433
/// Register the given replayer for a function (and the ID mapping).
400-
void DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer);
434+
void DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer,
435+
SignatureStr signature);
401436
402437
private:
438+
std::string GetSignature(unsigned id);
439+
Replayer *GetReplayer(unsigned id);
440+
403441
/// Mapping of function addresses to replayers and their ID.
404442
std::map<uintptr_t, std::pair<std::unique_ptr<Replayer>, unsigned>>
405443
m_replayers;
406444
407445
/// Mapping of IDs to replayer instances.
408-
std::map<unsigned, Replayer *> m_ids;
446+
std::map<unsigned, std::pair<Replayer *, SignatureStr>> m_ids;
409447
};
410448
411449
/// To be used as the "Runtime ID" of a constructor. It also invokes the
@@ -551,8 +589,12 @@ class Recorder {
551589
552590
unsigned id = m_registry.GetID(uintptr_t(f));
553591
554-
LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "Recording ({0}) '{1}'",
592+
#ifndef LLDB_REPRO_INSTR_TRACE
593+
LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "Recording {0}: {1}",
555594
id, m_pretty_func);
595+
#else
596+
llvm::errs() << "Recording " << id << ": " << m_pretty_func << "\n";
597+
#endif
556598
557599
m_serializer.SerializeAll(id);
558600
m_serializer.SerializeAll(args...);
@@ -574,8 +616,12 @@ class Recorder {
574616
575617
unsigned id = m_registry.GetID(uintptr_t(f));
576618
577-
LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "Recording ({0}) '{1}'",
619+
#ifndef LLDB_REPRO_INSTR_TRACE
620+
LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), "Recording {0}: {1}",
578621
id, m_pretty_func);
622+
#else
623+
llvm::errs() << "Recording " << id << ": " << m_pretty_func << "\n";
624+
#endif
579625
580626
m_serializer.SerializeAll(id);
581627
m_serializer.SerializeAll(args...);

lldb/source/Utility/ReproducerInstrumentation.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,33 @@ bool Registry::Replay(const FileSpec &file) {
4343
}
4444

4545
bool Registry::Replay(llvm::StringRef buffer) {
46+
#ifndef LLDB_REPRO_INSTR_TRACE
4647
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_API);
48+
#endif
4749

4850
Deserializer deserializer(buffer);
4951
while (deserializer.HasData(1)) {
5052
unsigned id = deserializer.Deserialize<unsigned>();
51-
LLDB_LOG(log, "Replaying function #{0}", id);
52-
m_ids[id]->operator()(deserializer);
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);
5361
}
5462

5563
return true;
5664
}
5765

58-
void Registry::DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer) {
66+
void Registry::DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer,
67+
SignatureStr signature) {
5968
const unsigned id = m_replayers.size() + 1;
6069
assert(m_replayers.find(RunID) == m_replayers.end());
6170
m_replayers[RunID] = std::make_pair(std::move(replayer), id);
62-
m_ids[id] = m_replayers[RunID].first.get();
71+
m_ids[id] =
72+
std::make_pair(m_replayers[RunID].first.get(), std::move(signature));
6373
}
6474

6575
unsigned Registry::GetID(uintptr_t addr) {
@@ -68,6 +78,21 @@ unsigned Registry::GetID(uintptr_t addr) {
6878
return id;
6979
}
7080

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+
7196
unsigned ObjectToIndex::GetIndexForObjectImpl(const void *object) {
7297
unsigned index = m_mapping.size() + 1;
7398
auto it = m_mapping.find(object);

0 commit comments

Comments
 (0)