Home | History | Annotate | Download | only in source
      1 //===-- lldb-log.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 "lldb/lldb-private-log.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 // Project includes
     16 #include "lldb/Interpreter/Args.h"
     17 #include "lldb/Core/Log.h"
     18 #include "lldb/Core/StreamFile.h"
     19 #include <string.h>
     20 
     21 using namespace lldb;
     22 using namespace lldb_private;
     23 
     24 
     25 // We want to avoid global constructors where code needs to be run so here we
     26 // control access to our static g_log_sp by hiding it in a singleton function
     27 // that will construct the static g_lob_sp the first time this function is
     28 // called.
     29 
     30 static bool g_log_enabled = false;
     31 static Log * g_log = NULL;
     32 static Log *
     33 GetLog ()
     34 {
     35     if (!g_log_enabled)
     36         return NULL;
     37     return g_log;
     38 }
     39 
     40 uint32_t
     41 lldb_private::GetLogMask ()
     42 {
     43     Log *log(GetLog ());
     44     if (log)
     45         return log->GetMask().Get();
     46     return 0;
     47 }
     48 
     49 bool
     50 lldb_private::IsLogVerbose ()
     51 {
     52     uint32_t mask = GetLogMask();
     53     return (mask & LIBLLDB_LOG_VERBOSE);
     54 }
     55 
     56 Log *
     57 lldb_private::GetLogIfAllCategoriesSet (uint32_t mask)
     58 {
     59     Log *log(GetLog ());
     60     if (log && mask)
     61     {
     62         uint32_t log_mask = log->GetMask().Get();
     63         if ((log_mask & mask) != mask)
     64             return NULL;
     65     }
     66     return log;
     67 }
     68 
     69 void
     70 lldb_private::LogIfAllCategoriesSet (uint32_t mask, const char *format, ...)
     71 {
     72     Log *log(GetLogIfAllCategoriesSet (mask));
     73     if (log)
     74     {
     75         va_list args;
     76         va_start (args, format);
     77         log->VAPrintf (format, args);
     78         va_end (args);
     79     }
     80 }
     81 
     82 void
     83 lldb_private::LogIfAnyCategoriesSet (uint32_t mask, const char *format, ...)
     84 {
     85     Log *log(GetLogIfAnyCategoriesSet (mask));
     86     if (log)
     87     {
     88         va_list args;
     89         va_start (args, format);
     90         log->VAPrintf (format, args);
     91         va_end (args);
     92     }
     93 }
     94 
     95 Log *
     96 lldb_private::GetLogIfAnyCategoriesSet (uint32_t mask)
     97 {
     98     Log *log(GetLog ());
     99     if (log && mask && (mask & log->GetMask().Get()))
    100         return log;
    101     return NULL;
    102 }
    103 
    104 void
    105 lldb_private::DisableLog (const char **categories, Stream *feedback_strm)
    106 {
    107     Log *log(GetLog ());
    108 
    109     if (log)
    110     {
    111         uint32_t flag_bits = 0;
    112         if (categories[0] != NULL)
    113         {
    114             flag_bits = log->GetMask().Get();
    115             for (size_t i = 0; categories[i] != NULL; ++i)
    116             {
    117                 const char *arg = categories[i];
    118 
    119                 if      (0 == ::strcasecmp(arg, "all"))         flag_bits &= ~LIBLLDB_LOG_ALL;
    120                 else if (0 == ::strcasecmp(arg, "api"))         flag_bits &= ~LIBLLDB_LOG_API;
    121                 else if (0 == ::strncasecmp(arg, "break", 5))   flag_bits &= ~LIBLLDB_LOG_BREAKPOINTS;
    122                 else if (0 == ::strcasecmp(arg, "commands"))    flag_bits &= ~LIBLLDB_LOG_COMMANDS;
    123                 else if (0 == ::strcasecmp(arg, "default"))     flag_bits &= ~LIBLLDB_LOG_DEFAULT;
    124                 else if (0 == ::strcasecmp(arg, "dyld"))        flag_bits &= ~LIBLLDB_LOG_DYNAMIC_LOADER;
    125                 else if (0 == ::strncasecmp(arg, "event", 5))   flag_bits &= ~LIBLLDB_LOG_EVENTS;
    126                 else if (0 == ::strncasecmp(arg, "expr", 4))    flag_bits &= ~LIBLLDB_LOG_EXPRESSIONS;
    127                 else if (0 == ::strncasecmp(arg, "object", 6))  flag_bits &= ~LIBLLDB_LOG_OBJECT;
    128                 else if (0 == ::strcasecmp(arg, "process"))     flag_bits &= ~LIBLLDB_LOG_PROCESS;
    129                 else if (0 == ::strcasecmp(arg, "script"))      flag_bits &= ~LIBLLDB_LOG_SCRIPT;
    130                 else if (0 == ::strcasecmp(arg, "state"))       flag_bits &= ~LIBLLDB_LOG_STATE;
    131                 else if (0 == ::strcasecmp(arg, "step"))        flag_bits &= ~LIBLLDB_LOG_STEP;
    132                 else if (0 == ::strcasecmp(arg, "thread"))      flag_bits &= ~LIBLLDB_LOG_THREAD;
    133                 else if (0 == ::strcasecmp(arg, "target"))      flag_bits &= ~LIBLLDB_LOG_TARGET;
    134                 else if (0 == ::strcasecmp(arg, "verbose"))     flag_bits &= ~LIBLLDB_LOG_VERBOSE;
    135                 else if (0 == ::strncasecmp(arg, "watch", 5))   flag_bits &= ~LIBLLDB_LOG_WATCHPOINTS;
    136                 else if (0 == ::strncasecmp(arg, "temp", 4))    flag_bits &= ~LIBLLDB_LOG_TEMPORARY;
    137                 else if (0 == ::strncasecmp(arg, "comm", 4))    flag_bits &= ~LIBLLDB_LOG_COMMUNICATION;
    138                 else if (0 == ::strncasecmp(arg, "conn", 4))    flag_bits &= ~LIBLLDB_LOG_CONNECTION;
    139                 else if (0 == ::strncasecmp(arg, "host", 4))    flag_bits &= ~LIBLLDB_LOG_HOST;
    140                 else if (0 == ::strncasecmp(arg, "unwind", 6))  flag_bits &= ~LIBLLDB_LOG_UNWIND;
    141                 else if (0 == ::strncasecmp(arg, "types", 5))   flag_bits &= ~LIBLLDB_LOG_TYPES;
    142                 else if (0 == ::strncasecmp(arg, "symbol", 6))  flag_bits &= ~LIBLLDB_LOG_SYMBOLS;
    143                 else if (0 == ::strncasecmp(arg, "module", 6))  flag_bits &= ~LIBLLDB_LOG_MODULES;
    144                 else if (0 == ::strncasecmp(arg, "mmap", 4))    flag_bits &= ~LIBLLDB_LOG_MMAP;
    145                 else if (0 == ::strcasecmp(arg, "os"))          flag_bits &= ~LIBLLDB_LOG_OS;
    146                 else
    147                 {
    148                     feedback_strm->Printf ("error:  unrecognized log category '%s'\n", arg);
    149                     ListLogCategories (feedback_strm);
    150                     return;
    151                 }
    152 
    153             }
    154         }
    155         log->GetMask().Reset (flag_bits);
    156         if (flag_bits == 0)
    157             g_log_enabled = false;
    158     }
    159 
    160     return;
    161 }
    162 
    163 Log *
    164 lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm)
    165 {
    166     // Try see if there already is a log - that way we can reuse its settings.
    167     // We could reuse the log in toto, but we don't know that the stream is the same.
    168     uint32_t flag_bits;
    169     if (g_log)
    170         flag_bits = g_log->GetMask().Get();
    171     else
    172         flag_bits = 0;
    173 
    174     // Now make a new log with this stream if one was provided
    175     if (log_stream_sp)
    176     {
    177         if (g_log)
    178             g_log->SetStream(log_stream_sp);
    179         else
    180             g_log = new Log(log_stream_sp);
    181     }
    182 
    183     if (g_log)
    184     {
    185         for (size_t i=0; categories[i] != NULL; ++i)
    186         {
    187             const char *arg = categories[i];
    188 
    189             if      (0 == ::strcasecmp(arg, "all"))         flag_bits |= LIBLLDB_LOG_ALL;
    190             else if (0 == ::strcasecmp(arg, "api"))         flag_bits |= LIBLLDB_LOG_API;
    191             else if (0 == ::strncasecmp(arg, "break", 5))   flag_bits |= LIBLLDB_LOG_BREAKPOINTS;
    192             else if (0 == ::strcasecmp(arg, "commands"))    flag_bits |= LIBLLDB_LOG_COMMANDS;
    193             else if (0 == ::strcasecmp(arg, "default"))     flag_bits |= LIBLLDB_LOG_DEFAULT;
    194             else if (0 == ::strcasecmp(arg, "dyld"))        flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER;
    195             else if (0 == ::strncasecmp(arg, "event", 5))   flag_bits |= LIBLLDB_LOG_EVENTS;
    196             else if (0 == ::strncasecmp(arg, "expr", 4))    flag_bits |= LIBLLDB_LOG_EXPRESSIONS;
    197             else if (0 == ::strncasecmp(arg, "object", 6))  flag_bits |= LIBLLDB_LOG_OBJECT;
    198             else if (0 == ::strcasecmp(arg, "process"))     flag_bits |= LIBLLDB_LOG_PROCESS;
    199             else if (0 == ::strcasecmp(arg, "script"))      flag_bits |= LIBLLDB_LOG_SCRIPT;
    200             else if (0 == ::strcasecmp(arg, "state"))       flag_bits |= LIBLLDB_LOG_STATE;
    201             else if (0 == ::strcasecmp(arg, "step"))        flag_bits |= LIBLLDB_LOG_STEP;
    202             else if (0 == ::strcasecmp(arg, "thread"))      flag_bits |= LIBLLDB_LOG_THREAD;
    203             else if (0 == ::strcasecmp(arg, "target"))      flag_bits |= LIBLLDB_LOG_TARGET;
    204             else if (0 == ::strcasecmp(arg, "verbose"))     flag_bits |= LIBLLDB_LOG_VERBOSE;
    205             else if (0 == ::strncasecmp(arg, "watch", 5))   flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
    206             else if (0 == ::strncasecmp(arg, "temp", 4))    flag_bits |= LIBLLDB_LOG_TEMPORARY;
    207             else if (0 == ::strncasecmp(arg, "comm", 4))    flag_bits |= LIBLLDB_LOG_COMMUNICATION;
    208             else if (0 == ::strncasecmp(arg, "conn", 4))    flag_bits |= LIBLLDB_LOG_CONNECTION;
    209             else if (0 == ::strncasecmp(arg, "host", 4))    flag_bits |= LIBLLDB_LOG_HOST;
    210             else if (0 == ::strncasecmp(arg, "unwind", 6))  flag_bits |= LIBLLDB_LOG_UNWIND;
    211             else if (0 == ::strncasecmp(arg, "types", 5))   flag_bits |= LIBLLDB_LOG_TYPES;
    212             else if (0 == ::strncasecmp(arg, "symbol", 6))  flag_bits |= LIBLLDB_LOG_SYMBOLS;
    213             else if (0 == ::strncasecmp(arg, "module", 6))  flag_bits |= LIBLLDB_LOG_MODULES;
    214             else if (0 == ::strncasecmp(arg, "mmap", 4))    flag_bits |= LIBLLDB_LOG_MMAP;
    215             else if (0 == ::strcasecmp(arg, "os"))          flag_bits |= LIBLLDB_LOG_OS;
    216             else
    217             {
    218                 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
    219                 ListLogCategories (feedback_strm);
    220                 return g_log;
    221             }
    222         }
    223 
    224         g_log->GetMask().Reset(flag_bits);
    225         g_log->GetOptions().Reset(log_options);
    226     }
    227     g_log_enabled = true;
    228     return g_log;
    229 }
    230 
    231 
    232 void
    233 lldb_private::ListLogCategories (Stream *strm)
    234 {
    235     strm->Printf("Logging categories for 'lldb':\n"
    236                  "  all - turn on all available logging categories\n"
    237                  "  api - enable logging of API calls and return values\n"
    238                  "  break - log breakpoints\n"
    239                  "  commands - log command argument parsing\n"
    240                  "  default - enable the default set of logging categories for liblldb\n"
    241                  "  dyld - log shared library related activities\n"
    242                  "  events - log broadcaster, listener and event queue activities\n"
    243                  "  expr - log expressions\n"
    244                  "  object - log object construction/destruction for important objects\n"
    245                  "  module - log module activities such as when modules are created, detroyed, replaced, and more\n"
    246                  "  process - log process events and activities\n"
    247                  "  script - log events about the script interpreter\n"
    248                  "  state - log private and public process state changes\n"
    249                  "  step - log step related activities\n"
    250                  "  symbol - log symbol related issues and warnings\n"
    251                  "  target - log target events and activities\n"
    252                  "  thread - log thread events and activities\n"
    253                  "  types - log type system related activities\n"
    254                  "  unwind - log stack unwind activities\n"
    255                  "  verbose - enable verbose logging\n"
    256                  "  watch - log watchpoint related activities\n");
    257 }
    258