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 249ed5b49cSJohnny Chen // that will construct the static g_lob_sp the first time this function is 259ed5b49cSJohnny Chen // called. 269ed5b49cSJohnny Chen static LogSP & 279ed5b49cSJohnny Chen GetLog () 289ed5b49cSJohnny Chen { 299ed5b49cSJohnny Chen static LogSP g_log_sp; 309ed5b49cSJohnny Chen return g_log_sp; 319ed5b49cSJohnny Chen } 329ed5b49cSJohnny Chen 339ed5b49cSJohnny Chen LogSP 349ed5b49cSJohnny Chen ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask) 359ed5b49cSJohnny Chen { 369ed5b49cSJohnny Chen LogSP log(GetLog ()); 379ed5b49cSJohnny Chen if (log && mask) 389ed5b49cSJohnny Chen { 399ed5b49cSJohnny Chen uint32_t log_mask = log->GetMask().Get(); 409ed5b49cSJohnny Chen if ((log_mask & mask) != mask) 419ed5b49cSJohnny Chen return LogSP(); 429ed5b49cSJohnny Chen } 439ed5b49cSJohnny Chen return log; 449ed5b49cSJohnny Chen } 459ed5b49cSJohnny Chen 469ed5b49cSJohnny Chen void 47*0c90ef47SGreg Clayton ProcessPOSIXLog::DisableLog (const char **args, Stream *feedback_strm) 489ed5b49cSJohnny Chen { 499ed5b49cSJohnny Chen LogSP log (GetLog ()); 509ed5b49cSJohnny Chen if (log) 519ed5b49cSJohnny Chen { 529ed5b49cSJohnny Chen uint32_t flag_bits = 0; 539ed5b49cSJohnny Chen 549ed5b49cSJohnny Chen flag_bits = log->GetMask().Get(); 55*0c90ef47SGreg Clayton for (; args[0]; args++) 569ed5b49cSJohnny Chen { 57*0c90ef47SGreg Clayton const char *arg = args[0]; 589ed5b49cSJohnny Chen 599ed5b49cSJohnny Chen if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~POSIX_LOG_ALL; 609ed5b49cSJohnny Chen else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~POSIX_LOG_ASYNC; 619ed5b49cSJohnny Chen else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~POSIX_LOG_BREAKPOINTS; 629ed5b49cSJohnny Chen else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~POSIX_LOG_COMM; 639ed5b49cSJohnny Chen else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~POSIX_LOG_DEFAULT; 649ed5b49cSJohnny Chen else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~POSIX_LOG_PACKETS; 659ed5b49cSJohnny Chen else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY; 669ed5b49cSJohnny Chen else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_SHORT; 679ed5b49cSJohnny Chen else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_LONG; 689ed5b49cSJohnny Chen else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~POSIX_LOG_PROCESS; 699ed5b49cSJohnny Chen else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~POSIX_LOG_PTRACE; 709ed5b49cSJohnny Chen else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~POSIX_LOG_REGISTERS; 719ed5b49cSJohnny Chen else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~POSIX_LOG_STEP; 729ed5b49cSJohnny Chen else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~POSIX_LOG_THREAD; 739ed5b49cSJohnny Chen else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~POSIX_LOG_VERBOSE; 749ed5b49cSJohnny Chen else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~POSIX_LOG_WATCHPOINTS; 759ed5b49cSJohnny Chen else 769ed5b49cSJohnny Chen { 779ed5b49cSJohnny Chen feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 789ed5b49cSJohnny Chen ListLogCategories (feedback_strm); 799ed5b49cSJohnny Chen } 809ed5b49cSJohnny Chen } 819ed5b49cSJohnny Chen 829ed5b49cSJohnny Chen if (flag_bits == 0) 839ed5b49cSJohnny Chen GetLog ().reset(); 849ed5b49cSJohnny Chen else 859ed5b49cSJohnny Chen log->GetMask().Reset (flag_bits); 869ed5b49cSJohnny Chen } 879ed5b49cSJohnny Chen 889ed5b49cSJohnny Chen return; 899ed5b49cSJohnny Chen } 909ed5b49cSJohnny Chen 919ed5b49cSJohnny Chen LogSP 92*0c90ef47SGreg Clayton ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm) 939ed5b49cSJohnny Chen { 949ed5b49cSJohnny Chen // Try see if there already is a log - that way we can reuse its settings. 959ed5b49cSJohnny Chen // We could reuse the log in toto, but we don't know that the stream is the same. 969ed5b49cSJohnny Chen uint32_t flag_bits = 0; 979ed5b49cSJohnny Chen LogSP log(GetLog ()); 989ed5b49cSJohnny Chen if (log) 999ed5b49cSJohnny Chen flag_bits = log->GetMask().Get(); 1009ed5b49cSJohnny Chen 1019ed5b49cSJohnny Chen // Now make a new log with this stream if one was provided 1029ed5b49cSJohnny Chen if (log_stream_sp) 1039ed5b49cSJohnny Chen { 104*0c90ef47SGreg Clayton log = LogSP(new Log(log_stream_sp)); 1059ed5b49cSJohnny Chen GetLog () = log; 1069ed5b49cSJohnny Chen } 1079ed5b49cSJohnny Chen 1089ed5b49cSJohnny Chen if (log) 1099ed5b49cSJohnny Chen { 1109ed5b49cSJohnny Chen bool got_unknown_category = false; 111*0c90ef47SGreg Clayton for (; args[0]; args++) 1129ed5b49cSJohnny Chen { 113*0c90ef47SGreg Clayton const char *arg = args[0]; 1149ed5b49cSJohnny Chen 1159ed5b49cSJohnny Chen if (::strcasecmp (arg, "all") == 0 ) flag_bits |= POSIX_LOG_ALL; 1169ed5b49cSJohnny Chen else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= POSIX_LOG_ASYNC; 1179ed5b49cSJohnny Chen else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= POSIX_LOG_BREAKPOINTS; 1189ed5b49cSJohnny Chen else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= POSIX_LOG_COMM; 1199ed5b49cSJohnny Chen else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= POSIX_LOG_DEFAULT; 1209ed5b49cSJohnny Chen else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= POSIX_LOG_PACKETS; 1219ed5b49cSJohnny Chen else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= POSIX_LOG_MEMORY; 1229ed5b49cSJohnny Chen else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_SHORT; 1239ed5b49cSJohnny Chen else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_LONG; 1249ed5b49cSJohnny Chen else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= POSIX_LOG_PROCESS; 1259ed5b49cSJohnny Chen else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits |= POSIX_LOG_PTRACE; 1269ed5b49cSJohnny Chen else if (::strcasecmp (arg, "registers") == 0 ) flag_bits |= POSIX_LOG_REGISTERS; 1279ed5b49cSJohnny Chen else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= POSIX_LOG_STEP; 1289ed5b49cSJohnny Chen else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= POSIX_LOG_THREAD; 1299ed5b49cSJohnny Chen else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= POSIX_LOG_VERBOSE; 1309ed5b49cSJohnny Chen else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= POSIX_LOG_WATCHPOINTS; 1319ed5b49cSJohnny Chen else 1329ed5b49cSJohnny Chen { 1339ed5b49cSJohnny Chen feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 1349ed5b49cSJohnny Chen if (got_unknown_category == false) 1359ed5b49cSJohnny Chen { 1369ed5b49cSJohnny Chen got_unknown_category = true; 1379ed5b49cSJohnny Chen ListLogCategories (feedback_strm); 1389ed5b49cSJohnny Chen } 1399ed5b49cSJohnny Chen } 1409ed5b49cSJohnny Chen } 1419ed5b49cSJohnny Chen if (flag_bits == 0) 1429ed5b49cSJohnny Chen flag_bits = POSIX_LOG_DEFAULT; 1439ed5b49cSJohnny Chen log->GetMask().Reset(flag_bits); 1449ed5b49cSJohnny Chen log->GetOptions().Reset(log_options); 1459ed5b49cSJohnny Chen } 1469ed5b49cSJohnny Chen return log; 1479ed5b49cSJohnny Chen } 1489ed5b49cSJohnny Chen 1499ed5b49cSJohnny Chen void 1509ed5b49cSJohnny Chen ProcessPOSIXLog::ListLogCategories (Stream *strm) 1519ed5b49cSJohnny Chen { 1529ed5b49cSJohnny Chen strm->Printf ("Logging categories for '%s':\n" 1539ed5b49cSJohnny Chen " all - turn on all available logging categories\n" 1549ed5b49cSJohnny Chen " async - log asynchronous activity\n" 1559ed5b49cSJohnny Chen " break - log breakpoints\n" 1569ed5b49cSJohnny Chen " communication - log communication activity\n" 1579ed5b49cSJohnny Chen " default - enable the default set of logging categories for liblldb\n" 1589ed5b49cSJohnny Chen " packets - log gdb remote packets\n" 1599ed5b49cSJohnny Chen " memory - log memory reads and writes\n" 1609ed5b49cSJohnny Chen " data-short - log memory bytes for memory reads and writes for short transactions only\n" 1619ed5b49cSJohnny Chen " data-long - log memory bytes for memory reads and writes for all transactions\n" 1629ed5b49cSJohnny Chen " process - log process events and activities\n" 1639ed5b49cSJohnny Chen #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION 1649ed5b49cSJohnny Chen " ptrace - log all calls to ptrace\n" 1659ed5b49cSJohnny Chen #endif 1669ed5b49cSJohnny Chen " registers - log register read/writes\n" 1679ed5b49cSJohnny Chen " thread - log thread events and activities\n" 1689ed5b49cSJohnny Chen " step - log step related activities\n" 1699ed5b49cSJohnny Chen " verbose - enable verbose logging\n" 1709ed5b49cSJohnny Chen " watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname); 1719ed5b49cSJohnny Chen } 1729ed5b49cSJohnny Chen 1739ed5b49cSJohnny Chen 1749ed5b49cSJohnny Chen void 1759ed5b49cSJohnny Chen ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...) 1769ed5b49cSJohnny Chen { 1779ed5b49cSJohnny Chen LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask)); 1789ed5b49cSJohnny Chen if (log) 1799ed5b49cSJohnny Chen { 1809ed5b49cSJohnny Chen va_list args; 1819ed5b49cSJohnny Chen va_start (args, format); 1829ed5b49cSJohnny Chen log->VAPrintf (format, args); 1839ed5b49cSJohnny Chen va_end (args); 1849ed5b49cSJohnny Chen } 1859ed5b49cSJohnny Chen } 1869ed5b49cSJohnny Chen 1879ed5b49cSJohnny Chen int ProcessPOSIXLog::m_nestinglevel; 1889ed5b49cSJohnny Chen const char *ProcessPOSIXLog::m_pluginname = ""; 189