Home | History | Annotate | Download | only in POSIX
      1 //===-- ProcessPOSIXLog.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 "ProcessPOSIXLog.h"
     11 
     12 #include "lldb/Interpreter/Args.h"
     13 #include "lldb/Core/StreamFile.h"
     14 
     15 #include "ProcessPOSIX.h"
     16 #include "ProcessPOSIXLog.h"
     17 
     18 using namespace lldb;
     19 using namespace lldb_private;
     20 
     21 
     22 // We want to avoid global constructors where code needs to be run so here we
     23 // control access to our static g_log_sp by hiding it in a singleton function
     24 // that will construct the static g_log_sp the first time this function is
     25 // called.
     26 static bool g_log_enabled = false;
     27 static Log * g_log = NULL;
     28 static Log *
     29 GetLog ()
     30 {
     31     if (!g_log_enabled)
     32         return NULL;
     33     return g_log;
     34 }
     35 
     36 
     37 Log *
     38 ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask)
     39 {
     40     Log *log(GetLog ());
     41     if (log && mask)
     42     {
     43         uint32_t log_mask = log->GetMask().Get();
     44         if ((log_mask & mask) != mask)
     45             return NULL;
     46     }
     47     return log;
     48 }
     49 
     50 static uint32_t
     51 GetFlagBits (const char *arg)
     52 {
     53     if      (::strcasecmp (arg, "all")        == 0 ) return POSIX_LOG_ALL;
     54     else if (::strcasecmp (arg, "async")      == 0 ) return POSIX_LOG_ASYNC;
     55     else if (::strncasecmp (arg, "break", 5)  == 0 ) return POSIX_LOG_BREAKPOINTS;
     56     else if (::strncasecmp (arg, "comm", 4)   == 0 ) return POSIX_LOG_COMM;
     57     else if (::strcasecmp (arg, "default")    == 0 ) return POSIX_LOG_DEFAULT;
     58     else if (::strcasecmp (arg, "packets")    == 0 ) return POSIX_LOG_PACKETS;
     59     else if (::strcasecmp (arg, "memory")     == 0 ) return POSIX_LOG_MEMORY;
     60     else if (::strcasecmp (arg, "data-short") == 0 ) return POSIX_LOG_MEMORY_DATA_SHORT;
     61     else if (::strcasecmp (arg, "data-long")  == 0 ) return POSIX_LOG_MEMORY_DATA_LONG;
     62     else if (::strcasecmp (arg, "process")    == 0 ) return POSIX_LOG_PROCESS;
     63     else if (::strcasecmp (arg, "ptrace")     == 0 ) return POSIX_LOG_PTRACE;
     64     else if (::strcasecmp (arg, "registers")  == 0 ) return POSIX_LOG_REGISTERS;
     65     else if (::strcasecmp (arg, "step")       == 0 ) return POSIX_LOG_STEP;
     66     else if (::strcasecmp (arg, "thread")     == 0 ) return POSIX_LOG_THREAD;
     67     else if (::strcasecmp (arg, "verbose")    == 0 ) return POSIX_LOG_VERBOSE;
     68     else if (::strncasecmp (arg, "watch", 5)  == 0 ) return POSIX_LOG_WATCHPOINTS;
     69     return 0;
     70 }
     71 
     72 void
     73 ProcessPOSIXLog::DisableLog (const char **args, Stream *feedback_strm)
     74 {
     75     Log *log (GetLog ());
     76     if (log)
     77     {
     78         uint32_t flag_bits = 0;
     79 
     80         flag_bits = log->GetMask().Get();
     81         for (; args[0]; args++)
     82         {
     83             const char *arg = args[0];
     84             uint32_t bits = GetFlagBits(arg);
     85 
     86             if (bits)
     87             {
     88                 flag_bits &= ~bits;
     89             }
     90             else
     91             {
     92                 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
     93                 ListLogCategories (feedback_strm);
     94             }
     95         }
     96 
     97         log->GetMask().Reset (flag_bits);
     98         if (flag_bits == 0)
     99             g_log_enabled = false;
    100     }
    101 
    102     return;
    103 }
    104 
    105 Log *
    106 ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm)
    107 {
    108     // Try see if there already is a log - that way we can reuse its settings.
    109     // We could reuse the log in toto, but we don't know that the stream is the same.
    110     uint32_t flag_bits = 0;
    111     if (g_log)
    112         flag_bits = g_log->GetMask().Get();
    113 
    114     // Now make a new log with this stream if one was provided
    115     if (log_stream_sp)
    116     {
    117         if (g_log)
    118             g_log->SetStream(log_stream_sp);
    119         else
    120             g_log = new Log(log_stream_sp);
    121     }
    122 
    123     if (g_log)
    124     {
    125         bool got_unknown_category = false;
    126         for (; args[0]; args++)
    127         {
    128             const char *arg = args[0];
    129             uint32_t bits = GetFlagBits(arg);
    130 
    131             if (bits)
    132             {
    133                 flag_bits |= bits;
    134             }
    135             else
    136             {
    137                 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
    138                 if (got_unknown_category == false)
    139                 {
    140                     got_unknown_category = true;
    141                     ListLogCategories (feedback_strm);
    142                 }
    143             }
    144         }
    145         if (flag_bits == 0)
    146             flag_bits = POSIX_LOG_DEFAULT;
    147         g_log->GetMask().Reset(flag_bits);
    148         g_log->GetOptions().Reset(log_options);
    149         g_log_enabled = true;
    150     }
    151     return g_log;
    152 }
    153 
    154 void
    155 ProcessPOSIXLog::ListLogCategories (Stream *strm)
    156 {
    157     strm->Printf ("Logging categories for '%s':\n"
    158                   "  all - turn on all available logging categories\n"
    159                   "  async - log asynchronous activity\n"
    160                   "  break - log breakpoints\n"
    161                   "  communication - log communication activity\n"
    162                   "  default - enable the default set of logging categories for liblldb\n"
    163                   "  packets - log gdb remote packets\n"
    164                   "  memory - log memory reads and writes\n"
    165                   "  data-short - log memory bytes for memory reads and writes for short transactions only\n"
    166                   "  data-long - log memory bytes for memory reads and writes for all transactions\n"
    167                   "  process - log process events and activities\n"
    168 #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
    169                   "  ptrace - log all calls to ptrace\n"
    170 #endif
    171                   "  registers - log register read/writes\n"
    172                   "  thread - log thread events and activities\n"
    173                   "  step - log step related activities\n"
    174                   "  verbose - enable verbose logging\n"
    175                   "  watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname);
    176 }
    177 
    178 
    179 void
    180 ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...)
    181 {
    182     Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask));
    183     if (log)
    184     {
    185         va_list args;
    186         va_start (args, format);
    187         log->VAPrintf (format, args);
    188         va_end (args);
    189     }
    190 }
    191 
    192 int ProcessPOSIXLog::m_nestinglevel;
    193 const char *ProcessPOSIXLog::m_pluginname = "";
    194