19ed5b49cSJohnny Chen //===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===// 29ed5b49cSJohnny Chen // 39ed5b49cSJohnny Chen // The LLVM Compiler Infrastructure 49ed5b49cSJohnny Chen // 59ed5b49cSJohnny Chen // This file is distributed under the University of Illinois Open Source 69ed5b49cSJohnny Chen // License. See LICENSE.TXT for details. 79ed5b49cSJohnny Chen // 89ed5b49cSJohnny Chen //===----------------------------------------------------------------------===// 99ed5b49cSJohnny Chen 109ed5b49cSJohnny Chen #include "ProcessPOSIXLog.h" 119ed5b49cSJohnny Chen 129ed5b49cSJohnny Chen #include "lldb/Interpreter/Args.h" 139ed5b49cSJohnny Chen #include "lldb/Core/StreamFile.h" 149ed5b49cSJohnny Chen 159ed5b49cSJohnny Chen #include "ProcessPOSIX.h" 169ed5b49cSJohnny Chen #include "ProcessPOSIXLog.h" 179ed5b49cSJohnny Chen 189ed5b49cSJohnny Chen using namespace lldb; 199ed5b49cSJohnny Chen using namespace lldb_private; 209ed5b49cSJohnny Chen 219ed5b49cSJohnny Chen 229ed5b49cSJohnny Chen // We want to avoid global constructors where code needs to be run so here we 239ed5b49cSJohnny Chen // control access to our static g_log_sp by hiding it in a singleton function 2401186359SAshok Thirumurthi // that will construct the static g_log_sp the first time this function is 259ed5b49cSJohnny Chen // called. 2601186359SAshok Thirumurthi static bool g_log_enabled = false; 2701186359SAshok Thirumurthi static Log * g_log = NULL; 2801186359SAshok Thirumurthi static Log * 299ed5b49cSJohnny Chen GetLog () 309ed5b49cSJohnny Chen { 3101186359SAshok Thirumurthi if (!g_log_enabled) 3201186359SAshok Thirumurthi return NULL; 3301186359SAshok Thirumurthi return g_log; 349ed5b49cSJohnny Chen } 359ed5b49cSJohnny Chen 3601186359SAshok Thirumurthi 3701186359SAshok Thirumurthi Log * 389ed5b49cSJohnny Chen ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask) 399ed5b49cSJohnny Chen { 4001186359SAshok Thirumurthi Log *log(GetLog ()); 419ed5b49cSJohnny Chen if (log && mask) 429ed5b49cSJohnny Chen { 439ed5b49cSJohnny Chen uint32_t log_mask = log->GetMask().Get(); 449ed5b49cSJohnny Chen if ((log_mask & mask) != mask) 4501186359SAshok Thirumurthi return NULL; 469ed5b49cSJohnny Chen } 479ed5b49cSJohnny Chen return log; 489ed5b49cSJohnny Chen } 499ed5b49cSJohnny Chen 50*76ad5d75SEd Maste static uint32_t 51*76ad5d75SEd Maste GetFlagBits (const char *arg) 52*76ad5d75SEd Maste { 53*76ad5d75SEd Maste if (::strcasecmp (arg, "all") == 0 ) return POSIX_LOG_ALL; 54*76ad5d75SEd Maste else if (::strcasecmp (arg, "async") == 0 ) return POSIX_LOG_ASYNC; 55*76ad5d75SEd Maste else if (::strncasecmp (arg, "break", 5) == 0 ) return POSIX_LOG_BREAKPOINTS; 56*76ad5d75SEd Maste else if (::strncasecmp (arg, "comm", 4) == 0 ) return POSIX_LOG_COMM; 57*76ad5d75SEd Maste else if (::strcasecmp (arg, "default") == 0 ) return POSIX_LOG_DEFAULT; 58*76ad5d75SEd Maste else if (::strcasecmp (arg, "packets") == 0 ) return POSIX_LOG_PACKETS; 59*76ad5d75SEd Maste else if (::strcasecmp (arg, "memory") == 0 ) return POSIX_LOG_MEMORY; 60*76ad5d75SEd Maste else if (::strcasecmp (arg, "data-short") == 0 ) return POSIX_LOG_MEMORY_DATA_SHORT; 61*76ad5d75SEd Maste else if (::strcasecmp (arg, "data-long") == 0 ) return POSIX_LOG_MEMORY_DATA_LONG; 62*76ad5d75SEd Maste else if (::strcasecmp (arg, "process") == 0 ) return POSIX_LOG_PROCESS; 63*76ad5d75SEd Maste else if (::strcasecmp (arg, "ptrace") == 0 ) return POSIX_LOG_PTRACE; 64*76ad5d75SEd Maste else if (::strcasecmp (arg, "registers") == 0 ) return POSIX_LOG_REGISTERS; 65*76ad5d75SEd Maste else if (::strcasecmp (arg, "step") == 0 ) return POSIX_LOG_STEP; 66*76ad5d75SEd Maste else if (::strcasecmp (arg, "thread") == 0 ) return POSIX_LOG_THREAD; 67*76ad5d75SEd Maste else if (::strcasecmp (arg, "verbose") == 0 ) return POSIX_LOG_VERBOSE; 68*76ad5d75SEd Maste else if (::strncasecmp (arg, "watch", 5) == 0 ) return POSIX_LOG_WATCHPOINTS; 69*76ad5d75SEd Maste return 0; 70*76ad5d75SEd Maste } 71*76ad5d75SEd Maste 729ed5b49cSJohnny Chen void 730c90ef47SGreg Clayton ProcessPOSIXLog::DisableLog (const char **args, Stream *feedback_strm) 749ed5b49cSJohnny Chen { 7501186359SAshok Thirumurthi Log *log (GetLog ()); 769ed5b49cSJohnny Chen if (log) 779ed5b49cSJohnny Chen { 789ed5b49cSJohnny Chen uint32_t flag_bits = 0; 799ed5b49cSJohnny Chen 809ed5b49cSJohnny Chen flag_bits = log->GetMask().Get(); 810c90ef47SGreg Clayton for (; args[0]; args++) 829ed5b49cSJohnny Chen { 830c90ef47SGreg Clayton const char *arg = args[0]; 84*76ad5d75SEd Maste uint32_t bits = GetFlagBits(arg); 859ed5b49cSJohnny Chen 86*76ad5d75SEd Maste if (bits) 87*76ad5d75SEd Maste { 88*76ad5d75SEd Maste flag_bits &= ~bits; 89*76ad5d75SEd Maste } 909ed5b49cSJohnny Chen else 919ed5b49cSJohnny Chen { 929ed5b49cSJohnny Chen feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 939ed5b49cSJohnny Chen ListLogCategories (feedback_strm); 949ed5b49cSJohnny Chen } 959ed5b49cSJohnny Chen } 969ed5b49cSJohnny Chen 979ed5b49cSJohnny Chen log->GetMask().Reset (flag_bits); 9801186359SAshok Thirumurthi if (flag_bits == 0) 9901186359SAshok Thirumurthi g_log_enabled = false; 1009ed5b49cSJohnny Chen } 1019ed5b49cSJohnny Chen 1029ed5b49cSJohnny Chen return; 1039ed5b49cSJohnny Chen } 1049ed5b49cSJohnny Chen 10501186359SAshok Thirumurthi Log * 1060c90ef47SGreg Clayton ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm) 1079ed5b49cSJohnny Chen { 1089ed5b49cSJohnny Chen // Try see if there already is a log - that way we can reuse its settings. 1099ed5b49cSJohnny Chen // We could reuse the log in toto, but we don't know that the stream is the same. 1109ed5b49cSJohnny Chen uint32_t flag_bits = 0; 11101186359SAshok Thirumurthi if (g_log) 11201186359SAshok Thirumurthi flag_bits = g_log->GetMask().Get(); 1139ed5b49cSJohnny Chen 1149ed5b49cSJohnny Chen // Now make a new log with this stream if one was provided 1159ed5b49cSJohnny Chen if (log_stream_sp) 1169ed5b49cSJohnny Chen { 11701186359SAshok Thirumurthi if (g_log) 11801186359SAshok Thirumurthi g_log->SetStream(log_stream_sp); 11901186359SAshok Thirumurthi else 12001186359SAshok Thirumurthi g_log = new Log(log_stream_sp); 1219ed5b49cSJohnny Chen } 1229ed5b49cSJohnny Chen 12301186359SAshok Thirumurthi if (g_log) 1249ed5b49cSJohnny Chen { 1259ed5b49cSJohnny Chen bool got_unknown_category = false; 1260c90ef47SGreg Clayton for (; args[0]; args++) 1279ed5b49cSJohnny Chen { 1280c90ef47SGreg Clayton const char *arg = args[0]; 129*76ad5d75SEd Maste uint32_t bits = GetFlagBits(arg); 1309ed5b49cSJohnny Chen 131*76ad5d75SEd Maste if (bits) 132*76ad5d75SEd Maste { 133*76ad5d75SEd Maste flag_bits |= bits; 134*76ad5d75SEd Maste } 1359ed5b49cSJohnny Chen else 1369ed5b49cSJohnny Chen { 1379ed5b49cSJohnny Chen feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 1389ed5b49cSJohnny Chen if (got_unknown_category == false) 1399ed5b49cSJohnny Chen { 1409ed5b49cSJohnny Chen got_unknown_category = true; 1419ed5b49cSJohnny Chen ListLogCategories (feedback_strm); 1429ed5b49cSJohnny Chen } 1439ed5b49cSJohnny Chen } 1449ed5b49cSJohnny Chen } 1459ed5b49cSJohnny Chen if (flag_bits == 0) 1469ed5b49cSJohnny Chen flag_bits = POSIX_LOG_DEFAULT; 14701186359SAshok Thirumurthi g_log->GetMask().Reset(flag_bits); 14801186359SAshok Thirumurthi g_log->GetOptions().Reset(log_options); 14901186359SAshok Thirumurthi g_log_enabled = true; 1509ed5b49cSJohnny Chen } 15101186359SAshok Thirumurthi return g_log; 1529ed5b49cSJohnny Chen } 1539ed5b49cSJohnny Chen 1549ed5b49cSJohnny Chen void 1559ed5b49cSJohnny Chen ProcessPOSIXLog::ListLogCategories (Stream *strm) 1569ed5b49cSJohnny Chen { 1579ed5b49cSJohnny Chen strm->Printf ("Logging categories for '%s':\n" 1589ed5b49cSJohnny Chen " all - turn on all available logging categories\n" 1599ed5b49cSJohnny Chen " async - log asynchronous activity\n" 1609ed5b49cSJohnny Chen " break - log breakpoints\n" 1619ed5b49cSJohnny Chen " communication - log communication activity\n" 1629ed5b49cSJohnny Chen " default - enable the default set of logging categories for liblldb\n" 1639ed5b49cSJohnny Chen " packets - log gdb remote packets\n" 1649ed5b49cSJohnny Chen " memory - log memory reads and writes\n" 1659ed5b49cSJohnny Chen " data-short - log memory bytes for memory reads and writes for short transactions only\n" 1669ed5b49cSJohnny Chen " data-long - log memory bytes for memory reads and writes for all transactions\n" 1679ed5b49cSJohnny Chen " process - log process events and activities\n" 1689ed5b49cSJohnny Chen #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION 1699ed5b49cSJohnny Chen " ptrace - log all calls to ptrace\n" 1709ed5b49cSJohnny Chen #endif 1719ed5b49cSJohnny Chen " registers - log register read/writes\n" 1729ed5b49cSJohnny Chen " thread - log thread events and activities\n" 1739ed5b49cSJohnny Chen " step - log step related activities\n" 1749ed5b49cSJohnny Chen " verbose - enable verbose logging\n" 1759ed5b49cSJohnny Chen " watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname); 1769ed5b49cSJohnny Chen } 1779ed5b49cSJohnny Chen 1789ed5b49cSJohnny Chen 1799ed5b49cSJohnny Chen void 1809ed5b49cSJohnny Chen ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...) 1819ed5b49cSJohnny Chen { 18201186359SAshok Thirumurthi Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask)); 1839ed5b49cSJohnny Chen if (log) 1849ed5b49cSJohnny Chen { 1859ed5b49cSJohnny Chen va_list args; 1869ed5b49cSJohnny Chen va_start (args, format); 1879ed5b49cSJohnny Chen log->VAPrintf (format, args); 1889ed5b49cSJohnny Chen va_end (args); 1899ed5b49cSJohnny Chen } 1909ed5b49cSJohnny Chen } 1919ed5b49cSJohnny Chen 1929ed5b49cSJohnny Chen int ProcessPOSIXLog::m_nestinglevel; 1939ed5b49cSJohnny Chen const char *ProcessPOSIXLog::m_pluginname = ""; 194