21#include <winpr/config.h>
22#include <winpr/buildflags.h>
23#include <winpr/platform.h>
26WINPR_PRAGMA_DIAG_IGNORED_RESERVED_ID_MACRO
27WINPR_PRAGMA_DIAG_IGNORED_UNUSED_MACRO
29#define __STDC_WANT_LIB_EXT1__ 1
39#include <winpr/string.h>
41#if defined(USE_EXECINFO)
42#include <execinfo/debug.h>
45#if defined(USE_UNWIND)
46#include <unwind/debug.h>
49#if defined(WINPR_HAVE_CORKSCREW)
50#include <corkscrew/debug.h>
53#if defined(_WIN32) || defined(_WIN64)
55#include <windows/debug.h>
58#include <winpr/wlog.h>
59#include <winpr/debug.h>
61#define TAG "com.winpr.utils.debug"
63#define LINE_LENGTH_MAX 2048
65static const char support_msg[] =
"Invalid stacktrace buffer! check if platform is supported!";
67void winpr_backtrace_free(
void* buffer)
72#if defined(USE_UNWIND)
73 winpr_unwind_backtrace_free(buffer);
74#elif defined(USE_EXECINFO)
75 winpr_execinfo_backtrace_free(buffer);
76#elif defined(WINPR_HAVE_CORKSCREW)
77 winpr_corkscrew_backtrace_free(buffer);
78#elif defined(_WIN32) || defined(_WIN64)
79 winpr_win_backtrace_free(buffer);
82 WLog_FATAL(TAG,
"%s", support_msg);
86void* winpr_backtrace(DWORD size)
88#if defined(USE_UNWIND)
89 return winpr_unwind_backtrace(size);
90#elif defined(USE_EXECINFO)
91 return winpr_execinfo_backtrace(size);
92#elif defined(WINPR_HAVE_CORKSCREW)
93 return winpr_corkscrew_backtrace(size);
94#elif (defined(_WIN32) || defined(_WIN64)) && !defined(_UWP)
95 return winpr_win_backtrace(size);
97 WLog_FATAL(TAG,
"%s", support_msg);
100 return strndup(support_msg,
sizeof(support_msg));
104char** winpr_backtrace_symbols(
void* buffer,
size_t* used)
111 WLog_FATAL(TAG,
"%s", support_msg);
115#if defined(USE_UNWIND)
116 return winpr_unwind_backtrace_symbols(buffer, used);
117#elif defined(USE_EXECINFO)
118 return winpr_execinfo_backtrace_symbols(buffer, used);
119#elif defined(WINPR_HAVE_CORKSCREW)
120 return winpr_corkscrew_backtrace_symbols(buffer, used);
121#elif (defined(_WIN32) || defined(_WIN64)) && !defined(_UWP)
122 return winpr_win_backtrace_symbols(buffer, used);
124 WLog_FATAL(TAG,
"%s", support_msg);
132 size_t len = strnlen(support_msg,
sizeof(support_msg));
133 char* ppmsg = calloc(
sizeof(
char*) + len + 1,
sizeof(
char));
136 char** msgptr = (
char**)ppmsg;
137 char* msg = &ppmsg[
sizeof(
char*)];
140 strncpy(msg, support_msg, len);
146void winpr_backtrace_symbols_fd(
void* buffer,
int fd)
150 WLog_FATAL(TAG,
"%s", support_msg);
154#if defined(USE_EXECINFO) && !defined(USE_UNWIND)
155 winpr_execinfo_backtrace_symbols_fd(buffer, fd);
156#elif !defined(ANDROID)
159 char** lines = winpr_backtrace_symbols(buffer, &used);
164 for (
size_t i = 0; i < used; i++)
165 (
void)_write(fd, lines[i], (
unsigned)strnlen(lines[i], LINE_LENGTH_MAX));
169 WLog_FATAL(TAG,
"%s", support_msg);
173void winpr_log_backtrace(
const char* tag, DWORD level, DWORD size)
175 winpr_log_backtrace_ex(WLog_Get(tag), level, size);
178void winpr_log_backtrace_ex(wLog* log, DWORD level, WINPR_ATTR_UNUSED DWORD size)
180 if (!WLog_IsLevelActive(log, level))
184 char** msg =
nullptr;
185 void* stack = winpr_backtrace(20);
189 WLog_Print(log, WLOG_ERROR,
"winpr_backtrace failed!\n");
193 msg = winpr_backtrace_symbols(stack, &used);
197 for (
size_t x = 0; x < used; x++)
198 WLog_Print(log, level,
"%" PRIuz
": %s", x, msg[x]);
203 winpr_backtrace_free(stack);
206char* winpr_strerror(INT32 dw,
char* dmsg,
size_t size)
208#ifdef __STDC_LIB_EXT1__
209 (void)strerror_s(dw, dmsg, size);
210#elif defined(WINPR_HAVE_STRERROR_R)
211 (void)strerror_r(dw, dmsg, size);
213 (void)_snprintf(dmsg, size,
"%s", strerror(dw));
219static BOOL starts_with(
const char* tok,
const char* val)
221 const size_t len = strlen(val);
222 if (strncmp(tok, val, len) != 0)
225 if (!strchr(tok,
'='))
231static BOOL option_equals(
const char* what,
const char* val)
233 return _stricmp(what, val) == 0;
237static BOOL parse_on_off_option(
const char* value)
240 const char* sep = strchr(value,
'=');
243 if (option_equals(
"on", &sep[1]))
245 if (option_equals(
"true", &sep[1]))
247 if (option_equals(
"off", &sep[1]))
249 if (option_equals(
"false", &sep[1]))
253 long val = strtol(value,
nullptr, 0);
261static BOOL option_is_debug(wLog* log, DWORD level,
const char* tok)
267 if (starts_with(tok,
"WITH_DEBUG_"))
268 return parse_on_off_option(tok);
273static void log_build_warn(wLog* log, DWORD level,
const char* what,
const char* msg,
274 BOOL (*cmp)(wLog* log, DWORD level,
const char* tok),
const char* input,
279 if (!input || (ilen == 0))
282 char* list = calloc(ilen,
sizeof(
char));
283 char* config = _strdup(input);
287 char* saveptr =
nullptr;
288 char* tok = strtok_s(config,
" ", &saveptr);
291 if (!cmp || cmp(log, level, tok))
292 winpr_str_append(tok, list, ilen,
" ");
294 tok = strtok_s(
nullptr,
" ", &saveptr);
301 if (strlen(list) > 0)
303 WLog_Print(log, level,
"*************************************************");
304 WLog_Print(log, level,
"This WinPR build is using [%s] build options:", what);
306 char* saveptr =
nullptr;
307 char* tok = strtok_s(list,
" ", &saveptr);
310 WLog_Print(log, level,
"* '%s'", tok);
311 tok = strtok_s(
nullptr,
" ", &saveptr);
313 WLog_Print(log, level,
"*");
314 WLog_Print(log, level,
"[%s] build options %s", what, msg);
315 WLog_Print(log, level,
"*************************************************");
321void winpr_log_build_warn(wLog* log, DWORD level)
323#if !defined(WINPR_ARCH_SUPPORTED) || (WINPR_ARCH_SUPPORTED == 0) || \
324 defined(DISABLE_SUPPORTED_ARCH_CHECKS)
328 const char configurations[] = {
329#if !defined(WINPR_ARCH_SUPPORTED) || (WINPR_ARCH_SUPPORTED == 0)
330 STR(WINPR_ARCH_SUPPORTED)
"==0 "
332#if defined(DISABLE_SUPPORTED_ARCH_CHECKS)
333 STR(DISABLE_SUPPORTED_ARCH_CHECKS)
" "
338 log_build_warn(log, level,
"experimental",
339 "might crash, overwrite data or steal your kitten, you have been warned!",
340 nullptr, configurations,
sizeof(configurations));
342 WINPR_PRAGMA_DIAG_PUSH
343 WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
344 log_build_warn(log, level,
"debug",
345 "might leak sensitive information (credentials, ...), slow down runtime, "
346 "increase memory usage",
347 option_is_debug, WINPR_BUILD_CONFIG,
sizeof(WINPR_BUILD_CONFIG));
348 WINPR_PRAGMA_DIAG_POP