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 24*01186359SAshok Thirumurthi // that will construct the static g_log_sp the first time this function is 259ed5b49cSJohnny Chen // called. 26*01186359SAshok Thirumurthi static bool g_log_enabled = false; 27*01186359SAshok Thirumurthi static Log * g_log = NULL; 28*01186359SAshok Thirumurthi static Log * 299ed5b49cSJohnny Chen GetLog () 309ed5b49cSJohnny Chen { 31*01186359SAshok Thirumurthi if (!g_log_enabled) 32*01186359SAshok Thirumurthi return NULL; 33*01186359SAshok Thirumurthi return g_log; 349ed5b49cSJohnny Chen } 359ed5b49cSJohnny Chen 36*01186359SAshok Thirumurthi 37*01186359SAshok Thirumurthi Log * 389ed5b49cSJohnny Chen ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask) 399ed5b49cSJohnny Chen { 40*01186359SAshok 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) 45*01186359SAshok Thirumurthi return NULL; 469ed5b49cSJohnny Chen } 479ed5b49cSJohnny Chen return log; 489ed5b49cSJohnny Chen } 499ed5b49cSJohnny Chen 509ed5b49cSJohnny Chen void 510c90ef47SGreg Clayton ProcessPOSIXLog::DisableLog (const char **args, Stream *feedback_strm) 529ed5b49cSJohnny Chen { 53*01186359SAshok Thirumurthi Log *log (GetLog ()); 549ed5b49cSJohnny Chen if (log) 559ed5b49cSJohnny Chen { 569ed5b49cSJohnny Chen uint32_t flag_bits = 0; 579ed5b49cSJohnny Chen 589ed5b49cSJohnny Chen flag_bits = log->GetMask().Get(); 590c90ef47SGreg Clayton for (; args[0]; args++) 609ed5b49cSJohnny Chen { 610c90ef47SGreg Clayton const char *arg = args[0]; 629ed5b49cSJohnny Chen 639ed5b49cSJohnny Chen if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~POSIX_LOG_ALL; 649ed5b49cSJohnny Chen else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~POSIX_LOG_ASYNC; 659ed5b49cSJohnny Chen else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~POSIX_LOG_BREAKPOINTS; 669ed5b49cSJohnny Chen else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~POSIX_LOG_COMM; 679ed5b49cSJohnny Chen else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~POSIX_LOG_DEFAULT; 689ed5b49cSJohnny Chen else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~POSIX_LOG_PACKETS; 699ed5b49cSJohnny Chen else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY; 709ed5b49cSJohnny Chen else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_SHORT; 719ed5b49cSJohnny Chen else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_LONG; 729ed5b49cSJohnny Chen else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~POSIX_LOG_PROCESS; 739ed5b49cSJohnny Chen else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~POSIX_LOG_PTRACE; 749ed5b49cSJohnny Chen else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~POSIX_LOG_REGISTERS; 759ed5b49cSJohnny Chen else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~POSIX_LOG_STEP; 769ed5b49cSJohnny Chen else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~POSIX_LOG_THREAD; 779ed5b49cSJohnny Chen else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~POSIX_LOG_VERBOSE; 789ed5b49cSJohnny Chen else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~POSIX_LOG_WATCHPOINTS; 799ed5b49cSJohnny Chen else 809ed5b49cSJohnny Chen { 819ed5b49cSJohnny Chen feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 829ed5b49cSJohnny Chen ListLogCategories (feedback_strm); 839ed5b49cSJohnny Chen } 849ed5b49cSJohnny Chen } 859ed5b49cSJohnny Chen 869ed5b49cSJohnny Chen log->GetMask().Reset (flag_bits); 87*01186359SAshok Thirumurthi if (flag_bits == 0) 88*01186359SAshok Thirumurthi g_log_enabled = false; 899ed5b49cSJohnny Chen } 909ed5b49cSJohnny Chen 919ed5b49cSJohnny Chen return; 929ed5b49cSJohnny Chen } 939ed5b49cSJohnny Chen 94*01186359SAshok Thirumurthi Log * 950c90ef47SGreg Clayton ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm) 969ed5b49cSJohnny Chen { 979ed5b49cSJohnny Chen // Try see if there already is a log - that way we can reuse its settings. 989ed5b49cSJohnny Chen // We could reuse the log in toto, but we don't know that the stream is the same. 999ed5b49cSJohnny Chen uint32_t flag_bits = 0; 100*01186359SAshok Thirumurthi if (g_log) 101*01186359SAshok Thirumurthi flag_bits = g_log->GetMask().Get(); 1029ed5b49cSJohnny Chen 1039ed5b49cSJohnny Chen // Now make a new log with this stream if one was provided 1049ed5b49cSJohnny Chen if (log_stream_sp) 1059ed5b49cSJohnny Chen { 106*01186359SAshok Thirumurthi if (g_log) 107*01186359SAshok Thirumurthi g_log->SetStream(log_stream_sp); 108*01186359SAshok Thirumurthi else 109*01186359SAshok Thirumurthi g_log = new Log(log_stream_sp); 1109ed5b49cSJohnny Chen } 1119ed5b49cSJohnny Chen 112*01186359SAshok Thirumurthi if (g_log) 1139ed5b49cSJohnny Chen { 1149ed5b49cSJohnny Chen bool got_unknown_category = false; 1150c90ef47SGreg Clayton for (; args[0]; args++) 1169ed5b49cSJohnny Chen { 1170c90ef47SGreg Clayton const char *arg = args[0]; 1189ed5b49cSJohnny Chen 1199ed5b49cSJohnny Chen if (::strcasecmp (arg, "all") == 0 ) flag_bits |= POSIX_LOG_ALL; 1209ed5b49cSJohnny Chen else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= POSIX_LOG_ASYNC; 1219ed5b49cSJohnny Chen else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= POSIX_LOG_BREAKPOINTS; 1229ed5b49cSJohnny Chen else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= POSIX_LOG_COMM; 1239ed5b49cSJohnny Chen else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= POSIX_LOG_DEFAULT; 1249ed5b49cSJohnny Chen else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= POSIX_LOG_PACKETS; 1259ed5b49cSJohnny Chen else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= POSIX_LOG_MEMORY; 1269ed5b49cSJohnny Chen else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_SHORT; 1279ed5b49cSJohnny Chen else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_LONG; 1289ed5b49cSJohnny Chen else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= POSIX_LOG_PROCESS; 1299ed5b49cSJohnny Chen else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits |= POSIX_LOG_PTRACE; 1309ed5b49cSJohnny Chen else if (::strcasecmp (arg, "registers") == 0 ) flag_bits |= POSIX_LOG_REGISTERS; 1319ed5b49cSJohnny Chen else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= POSIX_LOG_STEP; 1329ed5b49cSJohnny Chen else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= POSIX_LOG_THREAD; 1339ed5b49cSJohnny Chen else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= POSIX_LOG_VERBOSE; 1349ed5b49cSJohnny Chen else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= POSIX_LOG_WATCHPOINTS; 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; 147*01186359SAshok Thirumurthi g_log->GetMask().Reset(flag_bits); 148*01186359SAshok Thirumurthi g_log->GetOptions().Reset(log_options); 149*01186359SAshok Thirumurthi g_log_enabled = true; 1509ed5b49cSJohnny Chen } 151*01186359SAshok 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 { 182*01186359SAshok 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