xref: /llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp (revision 1a65ae11bd65d007391473f8bde3d06f4abad740)
1 //===-- ProcessGDBRemoteLog.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "ProcessGDBRemoteLog.h"
11 
12 #include "lldb/Interpreter/Args.h"
13 #include "lldb/Core/StreamFile.h"
14 
15 #include "ProcessGDBRemote.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 
21 // We want to avoid global constructors where code needs to be run so here we
22 // control access to our static g_log_sp by hiding it in a singleton function
23 // that will construct the static g_lob_sp the first time this function is
24 // called.
25 static LogSP &
26 GetLog ()
27 {
28     static LogSP g_log_sp;
29     return g_log_sp;
30 }
31 
32 LogSP
33 ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (uint32_t mask)
34 {
35     LogSP log(GetLog ());
36     if (log && mask)
37     {
38         uint32_t log_mask = log->GetMask().Get();
39         if ((log_mask & mask) != mask)
40             return LogSP();
41     }
42     return log;
43 }
44 
45 void
46 ProcessGDBRemoteLog::DisableLog (Args &args, Stream *feedback_strm)
47 {
48     LogSP log (GetLog ());
49     if (log)
50     {
51         uint32_t flag_bits = 0;
52 
53         const size_t argc = args.GetArgumentCount ();
54         if (argc > 0)
55         {
56             flag_bits = log->GetMask().Get();
57             for (size_t i = 0; i < argc; ++i)
58             {
59                 const char *arg = args.GetArgumentAtIndex (i);
60 
61 
62                 if      (::strcasecmp (arg, "all")        == 0   ) flag_bits &= ~GDBR_LOG_ALL;
63                 else if (::strcasecmp (arg, "async")      == 0   ) flag_bits &= ~GDBR_LOG_ASYNC;
64                 else if (::strcasestr (arg, "break")      == arg ) flag_bits &= ~GDBR_LOG_BREAKPOINTS;
65                 else if (::strcasestr (arg, "comm")       == arg ) flag_bits &= ~GDBR_LOG_COMM;
66                 else if (::strcasecmp (arg, "default")    == 0   ) flag_bits &= ~GDBR_LOG_DEFAULT;
67                 else if (::strcasecmp (arg, "packets")    == 0   ) flag_bits &= ~GDBR_LOG_PACKETS;
68                 else if (::strcasecmp (arg, "memory")     == 0   ) flag_bits &= ~GDBR_LOG_MEMORY;
69                 else if (::strcasecmp (arg, "data-short") == 0   ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT;
70                 else if (::strcasecmp (arg, "data-long")  == 0   ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG;
71                 else if (::strcasecmp (arg, "process")    == 0   ) flag_bits &= ~GDBR_LOG_PROCESS;
72                 else if (::strcasecmp (arg, "step")       == 0   ) flag_bits &= ~GDBR_LOG_STEP;
73                 else if (::strcasecmp (arg, "thread")     == 0   ) flag_bits &= ~GDBR_LOG_THREAD;
74                 else if (::strcasecmp (arg, "verbose")    == 0   ) flag_bits &= ~GDBR_LOG_VERBOSE;
75                 else if (::strcasestr (arg, "watch")      == arg ) flag_bits &= ~GDBR_LOG_WATCHPOINTS;
76                 else
77                 {
78                     feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
79                     ListLogCategories (feedback_strm);
80                 }
81 
82             }
83         }
84 
85         if (flag_bits == 0)
86             GetLog ().reset();
87         else
88             log->GetMask().Reset (flag_bits);
89     }
90 
91     return;
92 }
93 
94 LogSP
95 ProcessGDBRemoteLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
96 {
97     // Try see if there already is a log - that way we can reuse its settings.
98     // We could reuse the log in toto, but we don't know that the stream is the same.
99     uint32_t flag_bits = 0;
100     LogSP log(GetLog ());
101     if (log)
102         flag_bits = log->GetMask().Get();
103 
104     // Now make a new log with this stream if one was provided
105     if (log_stream_sp)
106     {
107         log = make_shared<Log>(log_stream_sp);
108         GetLog () = log;
109     }
110 
111     if (log)
112     {
113         bool got_unknown_category = false;
114         const size_t argc = args.GetArgumentCount();
115         for (size_t i=0; i<argc; ++i)
116         {
117             const char *arg = args.GetArgumentAtIndex(i);
118 
119             if      (::strcasecmp (arg, "all")        == 0   ) flag_bits |= GDBR_LOG_ALL;
120             else if (::strcasecmp (arg, "async")      == 0   ) flag_bits |= GDBR_LOG_ASYNC;
121             else if (::strcasestr (arg, "break")      == arg ) flag_bits |= GDBR_LOG_BREAKPOINTS;
122             else if (::strcasestr (arg, "comm")       == arg ) flag_bits |= GDBR_LOG_COMM;
123             else if (::strcasecmp (arg, "default")    == 0   ) flag_bits |= GDBR_LOG_DEFAULT;
124             else if (::strcasecmp (arg, "packets")    == 0   ) flag_bits |= GDBR_LOG_PACKETS;
125             else if (::strcasecmp (arg, "memory")     == 0   ) flag_bits |= GDBR_LOG_MEMORY;
126             else if (::strcasecmp (arg, "data-short") == 0   ) flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT;
127             else if (::strcasecmp (arg, "data-long")  == 0   ) flag_bits |= GDBR_LOG_MEMORY_DATA_LONG;
128             else if (::strcasecmp (arg, "process")    == 0   ) flag_bits |= GDBR_LOG_PROCESS;
129             else if (::strcasecmp (arg, "step")       == 0   ) flag_bits |= GDBR_LOG_STEP;
130             else if (::strcasecmp (arg, "thread")     == 0   ) flag_bits |= GDBR_LOG_THREAD;
131             else if (::strcasecmp (arg, "verbose")    == 0   ) flag_bits |= GDBR_LOG_VERBOSE;
132             else if (::strcasestr (arg, "watch")      == arg ) flag_bits |= GDBR_LOG_WATCHPOINTS;
133             else
134             {
135                 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
136                 if (got_unknown_category == false)
137                 {
138                     got_unknown_category = true;
139                     ListLogCategories (feedback_strm);
140                 }
141             }
142         }
143         if (flag_bits == 0)
144             flag_bits = GDBR_LOG_DEFAULT;
145         log->GetMask().Reset(flag_bits);
146         log->GetOptions().Reset(log_options);
147     }
148     return log;
149 }
150 
151 void
152 ProcessGDBRemoteLog::ListLogCategories (Stream *strm)
153 {
154     strm->Printf("Logging categories for '%s':\n"
155         "\tall - turn on all available logging categories\n"
156         "\tasync - log asynchronous activity\n"
157         "\tbreak - log breakpoints\n"
158         "\tcommunication - log communication activity\n"
159         "\tdefault - enable the default set of logging categories for liblldb\n"
160         "\tpackets - log gdb remote packets\n"
161         "\tmemory - log memory reads and writes\n"
162         "\tdata-short - log memory bytes for memory reads and writes for short transactions only\n"
163         "\tdata-long - log memory bytes for memory reads and writes for all transactions\n"
164         "\tprocess - log process events and activities\n"
165         "\tthread - log thread events and activities\n"
166         "\tstep - log step related activities\n"
167         "\tverbose - enable verbose logging\n"
168         "\twatch - log watchpoint related activities\n", ProcessGDBRemote::GetPluginNameStatic());
169 }
170 
171 
172 void
173 ProcessGDBRemoteLog::LogIf (uint32_t mask, const char *format, ...)
174 {
175     LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (mask));
176     if (log)
177     {
178         va_list args;
179         va_start (args, format);
180         log->VAPrintf (format, args);
181         va_end (args);
182     }
183 }
184