diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2025-08-01 19:03:16 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2025-08-01 20:56:38 -0400 |
| commit | be8c0c03e5d784ff7d2909d120cda6566ac2cea6 (patch) | |
| tree | 8e463b2dd62f2478529ea25e3f6599f12007d394 | |
| parent | 15c635b873105eda2861430d062ea3f6bdfe9d9b (diff) | |
Add log functions for logging the current stack trace without an active exception
| -rw-r--r-- | binaryninjaapi.h | 440 | ||||
| -rw-r--r-- | log.cpp | 232 | ||||
| -rw-r--r-- | python/log.py | 101 |
3 files changed, 648 insertions, 125 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 2173dd19..344fb03e 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -813,21 +813,104 @@ namespace BinaryNinja { BN_PRINTF_ATTRIBUTE(2, 3) void LogAlertForException(const std::exception& e, const char* fmt, ...); + /*! Logs to the error console with the given BNLogLevel. + + @threadsafe + + \ingroup logging + + \param level BNLogLevel debug log level + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + BN_PRINTF_ATTRIBUTE(2, 3) + void LogWithStackTrace(BNLogLevel level, const char* fmt, ...); + + /*! LogTraceWithStackTrace only writes text to the error console if the console is set to log level: DebugLog + Log level and the build is not a DEBUG build (i.e. the preprocessor directive _DEBUG is defined) + + @threadsafe + + \ingroup logging + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + BN_PRINTF_ATTRIBUTE(1, 2) + void LogTraceWithStackTrace(const char* fmt, ...); + + /*! LogDebugWithStackTrace only writes text to the error console if the console is set to log level: DebugLog + Log level DebugLog is the most verbose logging level in release builds. + + @threadsafe + + \ingroup logging + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + BN_PRINTF_ATTRIBUTE(1, 2) + void LogDebugWithStackTrace(const char* fmt, ...); + + /*! LogInfoWithStackTrace always writes text to the error console, and corresponds to the log level: InfoLog. + Log level InfoLog is the second most verbose logging level. + + @threadsafe + + \ingroup logging + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + BN_PRINTF_ATTRIBUTE(1, 2) + void LogInfoWithStackTrace(const char* fmt, ...); + + /*! LogWarnWithStackTrace writes text to the error console including a warning icon, + and also shows a warning icon in the bottom pane. LogWarn corresponds to the log level: WarningLog. + + @threadsafe + + \ingroup logging + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + BN_PRINTF_ATTRIBUTE(1, 2) + void LogWarnWithStackTrace(const char* fmt, ...); + + /*! LogErrorWithStackTrace writes text to the error console and pops up the error console. Additionally, + Errors in the console log include a error icon. LogError corresponds to the log level: ErrorLog. + + @threadsafe + + \ingroup logging + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + BN_PRINTF_ATTRIBUTE(1, 2) + void LogErrorWithStackTrace(const char* fmt, ...); + + /*! LogAlertWithStackTrace pops up a message box displaying the alert message and logs to the error console. + LogAlert corresponds to the log level: AlertLog. + + @threadsafe + + \ingroup logging + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + BN_PRINTF_ATTRIBUTE(1, 2) + void LogAlertWithStackTrace(const char* fmt, ...); + // Implementation detail void LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args); void LogTraceFV(fmt::string_view format, fmt::format_args args); - void LogDebugFV(fmt::string_view format, fmt::format_args args); - void LogInfoFV(fmt::string_view format, fmt::format_args args); - void LogWarnFV(fmt::string_view format, fmt::format_args args); - void LogErrorFV(fmt::string_view format, fmt::format_args args); - void LogAlertFV(fmt::string_view format, fmt::format_args args); void LogForExceptionFV(BNLogLevel level, const std::exception& e, fmt::string_view format, fmt::format_args args); void LogTraceForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogDebugForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogInfoForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogWarnForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogErrorForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogAlertForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); + void LogWithStackTraceFV(BNLogLevel level, fmt::string_view format, fmt::format_args args); + void LogTraceWithStackTraceFV(fmt::string_view format, fmt::format_args args); /*! Logs to the error console with the given BNLogLevel. @@ -874,7 +957,7 @@ namespace BinaryNinja { template<typename... T> void LogDebugF(fmt::format_string<T...> format, T&&... args) { - LogDebugFV(format, fmt::make_format_args(args...)); + LogFV(DebugLog, format, fmt::make_format_args(args...)); } /*! LogInfo always writes text to the error console, and corresponds to the log level: InfoLog. @@ -890,7 +973,7 @@ namespace BinaryNinja { template<typename... T> void LogInfoF(fmt::format_string<T...> format, T&&... args) { - LogInfoFV(format, fmt::make_format_args(args...)); + LogFV(InfoLog, format, fmt::make_format_args(args...)); } /*! LogWarn writes text to the error console including a warning icon, @@ -906,7 +989,7 @@ namespace BinaryNinja { template<typename... T> void LogWarnF(fmt::format_string<T...> format, T&&... args) { - LogWarnFV(format, fmt::make_format_args(args...)); + LogFV(WarningLog, format, fmt::make_format_args(args...)); } /*! LogError writes text to the error console and pops up the error console. Additionally, @@ -922,7 +1005,7 @@ namespace BinaryNinja { template<typename... T> void LogErrorF(fmt::format_string<T...> format, T&&... args) { - LogErrorFV(format, fmt::make_format_args(args...)); + LogFV(ErrorLog, format, fmt::make_format_args(args...)); } /*! LogAlert pops up a message box displaying the alert message and logs to the error console. @@ -938,7 +1021,7 @@ namespace BinaryNinja { template<typename... T> void LogAlertF(fmt::format_string<T...> format, T&&... args) { - LogAlertFV(format, fmt::make_format_args(args...)); + LogFV(AlertLog, format, fmt::make_format_args(args...)); } /*! Logs to the error console with the given BNLogLevel. @@ -955,7 +1038,7 @@ namespace BinaryNinja { template <typename... T> void LogForExceptionF(BNLogLevel level, const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogWithForExceptionFV(level, e, format, fmt::make_format_args(args...)); + LogForExceptionFV(level, e, format, fmt::make_format_args(args...)); } /*! LogTraceForExceptionF only writes text to the error console if the console is set to log level: DebugLog @@ -989,7 +1072,7 @@ namespace BinaryNinja { template <typename... T> void LogDebugForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogDebugForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(DebugLog, e, format, fmt::make_format_args(args...)); } /*! LogInfoForExceptionF always writes text to the error console, and corresponds to the log level: InfoLog. @@ -1006,7 +1089,7 @@ namespace BinaryNinja { template <typename... T> void LogInfoForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogInfoForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(InfoLog, e, format, fmt::make_format_args(args...)); } /*! LogWarnForExceptionF writes text to the error console including a warning icon, @@ -1023,7 +1106,7 @@ namespace BinaryNinja { template <typename... T> void LogWarnForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogWarnForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(WarningLog, e, format, fmt::make_format_args(args...)); } /*! LogErrorForExceptionF writes text to the error console and pops up the error console. Additionally, @@ -1040,7 +1123,7 @@ namespace BinaryNinja { template <typename... T> void LogErrorForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogErrorForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(ErrorLog, e, format, fmt::make_format_args(args...)); } /*! LogAlertForExceptionF pops up a message box displaying the alert message and logs to the error console. @@ -1057,7 +1140,119 @@ namespace BinaryNinja { template <typename... T> void LogAlertForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogAlertForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(AlertLog, e, format, fmt::make_format_args(args...)); + } + + /*! Logs to the error console with the given BNLogLevel. + + @threadsafe + + \ingroup logging + + \param level BNLogLevel debug log level + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogWithStackTraceF(BNLogLevel level, fmt::format_string<T...> format, T&&... args) + { + LogWithWithStackTraceFV(level, format, fmt::make_format_args(args...)); + } + + /*! LogTraceWithStackTraceF only writes text to the error console if the console is set to log level: DebugLog + Log level and the build is not a DEBUG build (i.e. the preprocessor directive _DEBUG is defined) + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogTraceWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogTraceWithStackTraceFV(format, fmt::make_format_args(args...)); + } + + /*! LogDebugWithStackTraceF only writes text to the error console if the console is set to log level: DebugLog + Log level DebugLog is the most verbose logging level in release builds. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogDebugWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(DebugLog, format, fmt::make_format_args(args...)); + } + + /*! LogInfoWithStackTraceF always writes text to the error console, and corresponds to the log level: InfoLog. + Log level InfoLog is the second most verbose logging level. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogInfoWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(InfoLog, format, fmt::make_format_args(args...)); + } + + /*! LogWarnWithStackTraceF writes text to the error console including a warning icon, + and also shows a warning icon in the bottom pane. LogWarn corresponds to the log level: WarningLog. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogWarnWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(WarningLog, format, fmt::make_format_args(args...)); + } + + /*! LogErrorWithStackTraceF writes text to the error console and pops up the error console. Additionally, + Errors in the console log include a error icon. LogError corresponds to the log level: ErrorLog. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogErrorWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(ErrorLog, format, fmt::make_format_args(args...)); + } + + /*! LogAlertWithStackTraceF pops up a message box displaying the alert message and logs to the error console. + LogAlert corresponds to the log level: AlertLog. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogAlertWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(AlertLog, format, fmt::make_format_args(args...)); } /*! Redirects the minimum level passed to standard out @@ -1112,20 +1307,11 @@ namespace BinaryNinja { void LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args); void LogTraceFV(fmt::string_view format, fmt::format_args args); - void LogDebugFV(fmt::string_view format, fmt::format_args args); - void LogInfoFV(fmt::string_view format, fmt::format_args args); - void LogWarnFV(fmt::string_view format, fmt::format_args args); - void LogErrorFV(fmt::string_view format, fmt::format_args args); - void LogAlertFV(fmt::string_view format, fmt::format_args args); - void LogForExceptionFV( BNLogLevel level, const std::exception& e, fmt::string_view format, fmt::format_args args); void LogTraceForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogDebugForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogInfoForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogWarnForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogErrorForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); - void LogAlertForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args); + void LogWithStackTraceFV(BNLogLevel level, fmt::string_view format, fmt::format_args args); + void LogTraceWithStackTraceFV(fmt::string_view format, fmt::format_args args); public: Logger(BNLogger* logger); @@ -1302,6 +1488,76 @@ namespace BinaryNinja { @threadsafe \param level BNLogLevel debug log level + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + void LogWithStackTrace(BNLogLevel level, const char* fmt, ...); + + /*! LogTraceWithStackTrace only writes text to the error console if the console is set to log level: + DebugLog Log level and the build is not a DEBUG build (i.e. the preprocessor directive _DEBUG is defined) + + @threadsafe + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + void LogTraceWithStackTrace(const char* fmt, ...); + + /*! LogDebugWithStackTrace only writes text to the error console if the console is set to log level: + DebugLog Log level DebugLog is the most verbose logging level in release builds. + + @threadsafe + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + void LogDebugWithStackTrace(const char* fmt, ...); + + /*! LogInfoWithStackTrace always writes text to the error console, and corresponds to the log level: + InfoLog. Log level InfoLog is the second most verbose logging level. + + @threadsafe + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + void LogInfoWithStackTrace(const char* fmt, ...); + + /*! LogWarnWithStackTrace writes text to the error console including a warning icon, + and also shows a warning icon in the bottom pane. LogWarn corresponds to the log level: WarningLog. + + @threadsafe + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + void LogWarnWithStackTrace(const char* fmt, ...); + + /*! LogErrorWithStackTrace writes text to the error console and pops up the error console. Additionally, + Errors in the console log include a error icon. LogError corresponds to the log level: ErrorLog. + + @threadsafe + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + void LogErrorWithStackTrace(const char* fmt, ...); + + /*! LogAlertWithStackTrace pops up a message box displaying the alert message and logs to the error console. + LogAlert corresponds to the log level: AlertLog. + + @threadsafe + + \param fmt C-style format string. + \param ... Variable arguments corresponding to the format string. + */ + void LogAlertWithStackTrace(const char* fmt, ...); + + /*! Logs to the error console with the given BNLogLevel. + + @threadsafe + + \param level BNLogLevel debug log level \param format fmt-style format string. \param ... Variable arguments corresponding to the format string. */ @@ -1336,7 +1592,7 @@ namespace BinaryNinja { template<typename... T> void LogDebugF(fmt::format_string<T...> format, T&&... args) { - LogDebugFV(format, fmt::make_format_args(args...)); + LogFV(DebugLog, format, fmt::make_format_args(args...)); } /*! LogInfo always writes text to the error console, and corresponds to the log level: InfoLog. @@ -1350,7 +1606,7 @@ namespace BinaryNinja { template<typename... T> void LogInfoF(fmt::format_string<T...> format, T&&... args) { - LogInfoFV(format, fmt::make_format_args(args...)); + LogFV(InfoLog, format, fmt::make_format_args(args...)); } /*! LogWarn writes text to the error console including a warning icon, @@ -1364,7 +1620,7 @@ namespace BinaryNinja { template<typename... T> void LogWarnF(fmt::format_string<T...> format, T&&... args) { - LogWarnFV(format, fmt::make_format_args(args...)); + LogFV(WarningLog, format, fmt::make_format_args(args...)); } /*! LogError writes text to the error console and pops up the error console. Additionally, @@ -1378,7 +1634,7 @@ namespace BinaryNinja { template<typename... T> void LogErrorF(fmt::format_string<T...> format, T&&... args) { - LogErrorFV(format, fmt::make_format_args(args...)); + LogFV(ErrorLog, format, fmt::make_format_args(args...)); } /*! LogAlert pops up a message box displaying the alert message and logs to the error console. @@ -1392,7 +1648,7 @@ namespace BinaryNinja { template<typename... T> void LogAlertF(fmt::format_string<T...> format, T&&... args) { - LogAlertFV(format, fmt::make_format_args(args...)); + LogFV(AlertLog, format, fmt::make_format_args(args...)); } /*! Logs to the error console with the given BNLogLevel and a stack trace. @@ -1408,7 +1664,7 @@ namespace BinaryNinja { void LogForExceptionF( BNLogLevel level, const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogWithForExceptionFV(level, e, format, fmt::make_format_args(args...)); + LogForExceptionFV(level, e, format, fmt::make_format_args(args...)); } /*! LogTraceForExceptionF only writes text to the error console if the console is set to log level: @@ -1438,7 +1694,7 @@ namespace BinaryNinja { template <typename... T> void LogDebugForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogDebugForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(DebugLog, e, format, fmt::make_format_args(args...)); } /*! LogInfoForExceptionF always writes text to the error console, and corresponds to the log level: @@ -1453,7 +1709,7 @@ namespace BinaryNinja { template <typename... T> void LogInfoForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogInfoForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(InfoLog, e, format, fmt::make_format_args(args...)); } /*! LogWarnForExceptionF writes text to the error console including a warning icon, @@ -1468,7 +1724,7 @@ namespace BinaryNinja { template <typename... T> void LogWarnForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogWarnForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(WarningLog, e, format, fmt::make_format_args(args...)); } /*! LogErrorForExceptionF writes text to the error console and pops up the error console. Additionally, @@ -1483,7 +1739,7 @@ namespace BinaryNinja { template <typename... T> void LogErrorForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogErrorForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(ErrorLog, e, format, fmt::make_format_args(args...)); } /*! LogAlertForExceptionF pops up a message box displaying the alert message and logs to the error @@ -1498,7 +1754,105 @@ namespace BinaryNinja { template <typename... T> void LogAlertForExceptionF(const std::exception& e, fmt::format_string<T...> format, T&&... args) { - LogAlertForExceptionFV(e, format, fmt::make_format_args(args...)); + LogForExceptionFV(AlertLog, e, format, fmt::make_format_args(args...)); + } + + /*! Logs to the error console with the given BNLogLevel and a stack trace. + + @threadsafe + + \param level BNLogLevel debug log level + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogWithStackTraceF(BNLogLevel level, fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(level, format, fmt::make_format_args(args...)); + } + + /*! LogTraceWithStackTraceF only writes text to the error console if the console is set to log level: + DebugLog Log level and the build is not a DEBUG build (i.e. the preprocessor directive _DEBUG is defined) + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogTraceWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogTraceWithStackTraceFV(format, fmt::make_format_args(args...)); + } + + /*! LogDebugWithStackTraceF only writes text to the error console if the console is set to log level: + DebugLog Log level DebugLog is the most verbose logging level in release builds. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogDebugWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(DebugLog, format, fmt::make_format_args(args...)); + } + + /*! LogInfoWithStackTraceF always writes text to the error console, and corresponds to the log level: + InfoLog. Log level InfoLog is the second most verbose logging level. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogInfoWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(InfoLog, format, fmt::make_format_args(args...)); + } + + /*! LogWarnWithStackTraceF writes text to the error console including a warning icon, + and also shows a warning icon in the bottom pane. LogWarn corresponds to the log level: WarningLog. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogWarnWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(WarningLog, format, fmt::make_format_args(args...)); + } + + /*! LogErrorWithStackTraceF writes text to the error console and pops up the error console. Additionally, + Errors in the console log include a error icon. LogError corresponds to the log level: ErrorLog. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogErrorWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(ErrorLog, format, fmt::make_format_args(args...)); + } + + /*! LogAlertWithStackTraceF pops up a message box displaying the alert message and logs to the error + console. LogAlert corresponds to the log level: AlertLog. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template <typename... T> + void LogAlertWithStackTraceF(fmt::format_string<T...> format, T&&... args) + { + LogWithStackTraceFV(AlertLog, format, fmt::make_format_args(args...)); } /*! Get the name registered for this Logger @@ -161,6 +161,49 @@ static void PerformLogForException(size_t session, BNLogLevel level, const strin } +static void PerformLogWithStackTrace(size_t session, BNLogLevel level, const string& logger_name, size_t tid, + const char* fmt, va_list args) +{ + #if defined(_MSC_VER) + int len = _vscprintf(fmt, args); + if (len < 0) + return; + char* msg = (char*)malloc(len + 1); + if (!msg) + return; + if (vsnprintf(msg, len + 1, fmt, args) >= 0) + { + char* stackTrace = BNGetCurrentStackTraceString(); + if (stackTrace) + { + BNLogWithStackTrace(session, level, logger_name.c_str(), tid, stackTrace, "%s", msg); + BNFreeString(stackTrace); + } + else + { + BNLog(session, level, logger_name.c_str(), tid, "%s", msg); + } + } + free(msg); + #else + char* msg; + if (vasprintf(&msg, fmt, args) < 0) + return; + char* stackTrace = BNGetCurrentStackTraceString(); + if (stackTrace) + { + BNLogWithStackTrace(session, level, logger_name.c_str(), tid, stackTrace, "%s", msg); + BNFreeString(stackTrace); + } + else + { + BNLog(session, level, logger_name.c_str(), tid, "%s", msg); + } + free(msg); + #endif +} + + void BinaryNinja::Log(BNLogLevel level, const char* fmt, ...) { va_list args; @@ -291,102 +334,111 @@ void BinaryNinja::LogAlertForException(const std::exception& e, const char* fmt, } -void BinaryNinja::LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args) -{ - std::string value = fmt::vformat(format, args); - Log(level, "%s", value.c_str()); -} - - -void BinaryNinja::LogTraceFV(fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogWithStackTrace(BNLogLevel level, const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogTrace("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace(0, level, "", 0, fmt, args); + va_end(args); } -void BinaryNinja::LogDebugFV(fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogTraceWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogDebug("%s", value.c_str()); + #ifdef _DEBUG + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace(0, DebugLog, "", 0, fmt, args); + va_end(args); + #endif } -void BinaryNinja::LogInfoFV(fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogDebugWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogInfo("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace(0, DebugLog, "", 0, fmt, args); + va_end(args); } -void BinaryNinja::LogWarnFV(fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogInfoWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogWarn("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace(0, InfoLog, "", 0, fmt, args); + va_end(args); } -void BinaryNinja::LogErrorFV(fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogWarnWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogError("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace(0, WarningLog, "", 0, fmt, args); + va_end(args); } -void BinaryNinja::LogAlertFV(fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogErrorWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogAlert("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace(0, ErrorLog, "", 0, fmt, args); + va_end(args); } -void BinaryNinja::LogForExceptionFV( - BNLogLevel level, const std::exception& e, fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogAlertWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogForException(level, e, "%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace(0, AlertLog, "", 0, fmt, args); + va_end(args); } -void BinaryNinja::LogTraceForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogTraceForException(e, "%s", value.c_str()); + Log(level, "%s", value.c_str()); } -void BinaryNinja::LogDebugForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogTraceFV(fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogDebugForException(e, "%s", value.c_str()); + LogTrace("%s", value.c_str()); } -void BinaryNinja::LogInfoForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogForExceptionFV( + BNLogLevel level, const std::exception& e, fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogInfoForException(e, "%s", value.c_str()); + LogForException(level, e, "%s", value.c_str()); } -void BinaryNinja::LogWarnForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogTraceForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogWarnForException(e, "%s", value.c_str()); + LogTraceForException(e, "%s", value.c_str()); } -void BinaryNinja::LogErrorForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogWithStackTraceFV(BNLogLevel level, fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogErrorForException(e, "%s", value.c_str()); + LogWithStackTrace(level, "%s", value.c_str()); } -void BinaryNinja::LogAlertForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void BinaryNinja::LogTraceWithStackTraceFV(fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogAlertForException(e, "%s", value.c_str()); + LogTraceWithStackTrace("%s", value.c_str()); } @@ -567,102 +619,118 @@ void Logger::LogAlertForException(const std::exception& e, const char* fmt, ...) } -void Logger::LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args) -{ - std::string value = fmt::vformat(format, args); - Log(level, "%s", value.c_str()); -} - - -void Logger::LogTraceFV(fmt::string_view format, fmt::format_args args) +void Logger::LogWithStackTrace(BNLogLevel level, const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogTrace("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace( + GetSessionId(), level, GetName(), GetThreadId(), fmt::format("{}{}", GetIndent(), fmt).c_str(), args); + va_end(args); } -void Logger::LogDebugFV(fmt::string_view format, fmt::format_args args) +void Logger::LogTraceWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogDebug("%s", value.c_str()); + #ifdef _DEBUG + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace( + GetSessionId(), DebugLog, GetName(), GetThreadId(), fmt::format("{}{}", GetIndent(), fmt).c_str(), args); + va_end(args); + #endif } -void Logger::LogInfoFV(fmt::string_view format, fmt::format_args args) +void Logger::LogDebugWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogInfo("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace( + GetSessionId(), DebugLog, GetName(), GetThreadId(), fmt::format("{}{}", GetIndent(), fmt).c_str(), args); + va_end(args); } -void Logger::LogWarnFV(fmt::string_view format, fmt::format_args args) +void Logger::LogInfoWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogWarn("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace( + GetSessionId(), InfoLog, GetName(), GetThreadId(), fmt::format("{}{}", GetIndent(), fmt).c_str(), args); + va_end(args); } -void Logger::LogErrorFV(fmt::string_view format, fmt::format_args args) +void Logger::LogWarnWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogError("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace( + GetSessionId(), WarningLog, GetName(), GetThreadId(), fmt::format("{}{}", GetIndent(), fmt).c_str(), args); + va_end(args); } -void Logger::LogAlertFV(fmt::string_view format, fmt::format_args args) +void Logger::LogErrorWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogAlert("%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace( + GetSessionId(), ErrorLog, GetName(), GetThreadId(), fmt::format("{}{}", GetIndent(), fmt).c_str(), args); + va_end(args); } -void Logger::LogForExceptionFV( - BNLogLevel level, const std::exception& e, fmt::string_view format, fmt::format_args args) +void Logger::LogAlertWithStackTrace(const char* fmt, ...) { - std::string value = fmt::vformat(format, args); - LogForException(level, e, "%s", value.c_str()); + va_list args; + va_start(args, fmt); + PerformLogWithStackTrace( + GetSessionId(), AlertLog, GetName(), GetThreadId(), fmt::format("{}{}", GetIndent(), fmt).c_str(), args); + va_end(args); } -void Logger::LogTraceForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void Logger::LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogTraceForException(e, "%s", value.c_str()); + Log(level, "%s", value.c_str()); } -void Logger::LogDebugForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void Logger::LogTraceFV(fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogDebugForException(e, "%s", value.c_str()); + LogTrace("%s", value.c_str()); } -void Logger::LogInfoForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void Logger::LogForExceptionFV( + BNLogLevel level, const std::exception& e, fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogInfoForException(e, "%s", value.c_str()); + LogForException(level, e, "%s", value.c_str()); } -void Logger::LogWarnForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void Logger::LogTraceForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogWarnForException(e, "%s", value.c_str()); + LogTraceForException(e, "%s", value.c_str()); } -void Logger::LogErrorForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void Logger::LogWithStackTraceFV(BNLogLevel level, fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogErrorForException(e, "%s", value.c_str()); + LogWithStackTrace(level, "%s", value.c_str()); } -void Logger::LogAlertForExceptionFV(const std::exception& e, fmt::string_view format, fmt::format_args args) +void Logger::LogTraceWithStackTraceFV(fmt::string_view format, fmt::format_args args) { std::string value = fmt::vformat(format, args); - LogAlertForException(e, "%s", value.c_str()); + LogTraceWithStackTrace("%s", value.c_str()); } diff --git a/python/log.py b/python/log.py index 678482b6..5c3f8d7d 100644 --- a/python/log.py +++ b/python/log.py @@ -233,6 +233,89 @@ def log_alert_for_exception(text: Any, logger: str = ""): core.BNLogStringWithStackTrace(0, LogLevel.AlertLog, logger, threading.current_thread().ident, traceback.format_exc(), text) +def log_with_traceback(level: LogLevel, text: Any, logger: str = "", session: int = 0): + """ + ``log_with_traceback`` writes messages to the log console for the given log level, including the current stack trace. + + ============ ======== ======================================================================= + LogLevelName LogLevel Description + ============ ======== ======================================================================= + DebugLog 0 Logs debugging information messages to the console. + InfoLog 1 Logs general information messages to the console. + WarningLog 2 Logs message to console with **Warning** icon. + ErrorLog 3 Logs message to console with **Error** icon, focusing the error console. + AlertLog 4 Logs message to pop up window. + ============ ======== ======================================================================= + + :param LogLevel level: Log level to use + :param str text: message to print + :rtype: None + """ + if not isinstance(text, str): + text = str(text) + core.BNLogStringWithStackTrace(session, level, logger, threading.current_thread().ident, ''.join(traceback.format_stack()), text) + + +def log_debug_with_traceback(text: Any, logger: str = ""): + """ + ``log_debug_with_traceback`` Logs debugging information messages to the console, including the current stack trace. + + :param str text: message to print + :rtype: None + """ + if not isinstance(text, str): + text = str(text) + core.BNLogStringWithStackTrace(0, LogLevel.DebugLog, logger, threading.current_thread().ident, ''.join(traceback.format_stack()), text) + + +def log_info_with_traceback(text: Any, logger: str = ""): + """ + ``log_info_with_traceback`` Logs general information messages to the console, including the current stack trace. + + :param str text: message to print + :rtype: None + """ + if not isinstance(text, str): + text = str(text) + core.BNLogStringWithStackTrace(0, LogLevel.InfoLog, logger, threading.current_thread().ident, ''.join(traceback.format_stack()), text) + + +def log_warn_with_traceback(text: Any, logger: str = ""): + """ + ``log_warn_with_traceback`` Logs message to console, including the current stack trace. When run through the GUI it logs with **Warning** icon. + + :param str text: message to print + :rtype: None + """ + if not isinstance(text, str): + text = str(text) + core.BNLogStringWithStackTrace(0, LogLevel.WarningLog, logger, threading.current_thread().ident, ''.join(traceback.format_stack()), text) + + +def log_error_with_traceback(text: Any, logger: str = ""): + """ + ``log_error_with_traceback`` Logs message to console, including the current stack trace. When run through the GUI it logs with **Error** icon, focusing the error console. + + :param str text: message to print + :rtype: None + """ + if not isinstance(text, str): + text = str(text) + core.BNLogStringWithStackTrace(0, LogLevel.ErrorLog, logger, threading.current_thread().ident, ''.join(traceback.format_stack()), text) + + +def log_alert_with_traceback(text: Any, logger: str = ""): + """ + ``log_alert_with_traceback`` Logs message console, including the current stack trace. A pop up window is created if run through the GUI. + + :param str text: message to print + :rtype: None + """ + if not isinstance(text, str): + text = str(text) + core.BNLogStringWithStackTrace(0, LogLevel.AlertLog, logger, threading.current_thread().ident, ''.join(traceback.format_stack()), text) + + def log_to_stdout(min_level: LogLevel = LogLevel.InfoLog): """ ``log_to_stdout`` redirects minimum log level to standard out. @@ -322,3 +405,21 @@ class Logger: def log_alert_for_exception(self, message: str) -> None: log_for_exception(LogLevel.AlertLog, message, self.logger_name, self.session_id) + + def log_with_traceback(self, level: LogLevel, message: str) -> None: + log_with_traceback(level, message, self.logger_name, self.session_id) + + def log_debug_with_traceback(self, message: str) -> None: + log_with_traceback(LogLevel.DebugLog, message, self.logger_name, self.session_id) + + def log_info_with_traceback(self, message: str) -> None: + log_with_traceback(LogLevel.InfoLog, message, self.logger_name, self.session_id) + + def log_warn_with_traceback(self, message: str) -> None: + log_with_traceback(LogLevel.WarningLog, message, self.logger_name, self.session_id) + + def log_error_with_traceback(self, message: str) -> None: + log_with_traceback(LogLevel.ErrorLog, message, self.logger_name, self.session_id) + + def log_alert_with_traceback(self, message: str) -> None: + log_with_traceback(LogLevel.AlertLog, message, self.logger_name, self.session_id) |
