Merge pull request #2110 from akallabeth/winpr_backtrace_windows
Winpr backtrace windows
This commit is contained in:
commit
441632310a
@ -27,10 +27,10 @@ extern "C" {
|
|||||||
|
|
||||||
#include <winpr/wtypes.h>
|
#include <winpr/wtypes.h>
|
||||||
|
|
||||||
void *winpr_backtrace(DWORD size);
|
WINPR_API void *winpr_backtrace(DWORD size);
|
||||||
void winpr_backtrace_free(void *buffer);
|
WINPR_API void winpr_backtrace_free(void *buffer);
|
||||||
char **winpr_backtrace_symbols(void *buffer, size_t *used);
|
WINPR_API char **winpr_backtrace_symbols(void *buffer, size_t *used);
|
||||||
void winpr_backtrace_symbols_fd(void *buffer, int fd);
|
WINPR_API void winpr_backtrace_symbols_fd(void *buffer, int fd);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,10 @@ if(UNIX)
|
|||||||
winpr_library_add(m)
|
winpr_library_add(m)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
winpr_library_add(Dbghelp)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif()
|
endif()
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#if defined(HAVE_EXECINFO_H)
|
#if defined(HAVE_EXECINFO_H)
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#endif
|
#endif
|
||||||
@ -32,6 +35,11 @@
|
|||||||
#include <corkscrew/backtrace.h>
|
#include <corkscrew/backtrace.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <Dbghelp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
#include <winpr/wlog.h>
|
#include <winpr/wlog.h>
|
||||||
#include <winpr/debug.h>
|
#include <winpr/debug.h>
|
||||||
@ -55,6 +63,15 @@ typedef struct
|
|||||||
} t_execinfo;
|
} t_execinfo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PVOID* stack;
|
||||||
|
ULONG used;
|
||||||
|
ULONG max;
|
||||||
|
} t_win_stack;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ANDROID)
|
#if defined(ANDROID)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@ -191,6 +208,13 @@ void winpr_backtrace_free(void *buffer)
|
|||||||
free(data->buffer);
|
free(data->buffer);
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
|
#elif defined(_WIN32) || defined(_WIN64)
|
||||||
|
{
|
||||||
|
t_win_stack *data = (t_win_stack*)buffer;
|
||||||
|
if (data->stack)
|
||||||
|
free(data->stack);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
LOGF(support_msg);
|
LOGF(support_msg);
|
||||||
#endif
|
#endif
|
||||||
@ -232,6 +256,25 @@ void *winpr_backtrace(DWORD size)
|
|||||||
pthread_once(&initialized, load_library);
|
pthread_once(&initialized, load_library);
|
||||||
data->max = size;
|
data->max = size;
|
||||||
data->used = fkt->unwind_backtrace(data->buffer, 0, size);
|
data->used = fkt->unwind_backtrace(data->buffer, 0, size);
|
||||||
|
return data;
|
||||||
|
#elif defined(_WIN32) || defined(_WIN64)
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
t_win_stack *data = calloc(1, sizeof(t_win_stack));
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data->max = size;
|
||||||
|
data->stack = calloc(data->max, sizeof(PVOID));
|
||||||
|
if (!data->stack)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymInitialize( process, NULL, TRUE );
|
||||||
|
data->used = CaptureStackBackTrace(2, size, data->stack, NULL);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
#else
|
#else
|
||||||
LOGF(support_msg);
|
LOGF(support_msg);
|
||||||
@ -274,7 +317,7 @@ char **winpr_backtrace_symbols(void *buffer, size_t *used)
|
|||||||
size_t i;
|
size_t i;
|
||||||
char *lines = calloc(data->used + 1, sizeof(char *) * line_len);
|
char *lines = calloc(data->used + 1, sizeof(char *) * line_len);
|
||||||
char **vlines = (char **)lines;
|
char **vlines = (char **)lines;
|
||||||
backtrace_symbol_t *symbols = calloc(data->used, sizeof(backtrace_symbol_t));;
|
backtrace_symbol_t *symbols = calloc(data->used, sizeof(backtrace_symbol_t));
|
||||||
|
|
||||||
if (!lines || !symbols)
|
if (!lines || !symbols)
|
||||||
{
|
{
|
||||||
@ -298,13 +341,67 @@ char **winpr_backtrace_symbols(void *buffer, size_t *used)
|
|||||||
fkt->format_backtrace_line(i, &data->buffer[i], &symbols[i], vlines[i], line_len);
|
fkt->format_backtrace_line(i, &data->buffer[i], &symbols[i], vlines[i], line_len);
|
||||||
|
|
||||||
fkt->free_backtrace_symbols(symbols, data->used);
|
fkt->free_backtrace_symbols(symbols, data->used);
|
||||||
|
free(symbols);
|
||||||
|
|
||||||
if (used)
|
if (used)
|
||||||
*used = data->used;
|
*used = data->used;
|
||||||
|
|
||||||
return (char **)lines;
|
return (char **)lines;
|
||||||
}
|
}
|
||||||
|
#elif defined(_WIN32) || defined(_WIN64)
|
||||||
|
{
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
t_win_stack *data = (t_win_stack *)buffer;
|
||||||
|
size_t line_len = 1024;
|
||||||
|
size_t i;
|
||||||
|
char *lines = calloc(data->used + 1, sizeof(char *) * line_len);
|
||||||
|
char **vlines = (char **)lines;
|
||||||
|
SYMBOL_INFO* symbol = calloc(sizeof(SYMBOL_INFO) + line_len * sizeof(char), 1);
|
||||||
|
IMAGEHLP_LINE64 *line = (IMAGEHLP_LINE64 *)calloc(1, sizeof(IMAGEHLP_LINE64));
|
||||||
|
|
||||||
|
if (!lines || !symbol || !line)
|
||||||
|
{
|
||||||
|
if (lines)
|
||||||
|
free(lines);
|
||||||
|
|
||||||
|
if (symbol)
|
||||||
|
free(symbol);
|
||||||
|
|
||||||
|
if (line)
|
||||||
|
free(line);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
|
symbol->MaxNameLen = line_len;
|
||||||
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
|
||||||
|
/* To allow a char** malloced array to be returned, allocate n+1 lines
|
||||||
|
* and fill in the first lines[i] char with the address of lines[(i+1) * 1024] */
|
||||||
|
for (i=0; i<data->used; i++)
|
||||||
|
vlines[i] = &lines[(i + 1) * line_len];
|
||||||
|
|
||||||
|
for (i=0; i<data->used; i++)
|
||||||
|
{
|
||||||
|
DWORD64 address = (DWORD64)(data->stack[i]);
|
||||||
|
DWORD displacement;
|
||||||
|
|
||||||
|
SymFromAddr(process, address, 0, symbol);
|
||||||
|
if (SymGetLineFromAddr64(process, address, &displacement, line))
|
||||||
|
{
|
||||||
|
_snprintf(vlines[i], line_len, "%08lX: %s in %s:%lu", symbol->Address, symbol->Name, line->FileName, line->LineNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_snprintf(vlines[i], line_len, "%08lX: %s", symbol->Address, symbol->Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (used)
|
||||||
|
*used = data->used;
|
||||||
|
|
||||||
|
free(symbol);
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
return (char **)lines;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
LOGF(support_msg);
|
LOGF(support_msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -323,20 +420,18 @@ void winpr_backtrace_symbols_fd(void *buffer, int fd)
|
|||||||
t_execinfo *data = (t_execinfo *)buffer;
|
t_execinfo *data = (t_execinfo *)buffer;
|
||||||
assert(data);
|
assert(data);
|
||||||
backtrace_symbols_fd(data->buffer, data->used, fd);
|
backtrace_symbols_fd(data->buffer, data->used, fd);
|
||||||
#elif defined(ANDROID)
|
#elif defined(_WIN32) || defined(_WIN64) || defined(ANDROID)
|
||||||
size_t used;
|
{
|
||||||
t_corkscrew_data *data = (t_corkscrew_data *)buffer;
|
size_t used;
|
||||||
assert(data);
|
char **lines = winpr_backtrace_symbols(buffer, &used);
|
||||||
char **lines = winpr_backtrace_symbols(buffer, &used);
|
|
||||||
|
|
||||||
if (lines)
|
|
||||||
{
|
|
||||||
DWORD i;
|
|
||||||
|
|
||||||
for (i=0; i<used; i++)
|
|
||||||
write(fd, lines[i], strlen(lines[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (lines)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
for (i=0; i<used; i++)
|
||||||
|
write(fd, lines[i], strlen(lines[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
LOGF(support_msg);
|
LOGF(support_msg);
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,6 +7,7 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
|||||||
set(${MODULE_PREFIX}_TESTS
|
set(${MODULE_PREFIX}_TESTS
|
||||||
TestIni.c
|
TestIni.c
|
||||||
TestImage.c
|
TestImage.c
|
||||||
|
TestBacktrace.c
|
||||||
TestQueue.c
|
TestQueue.c
|
||||||
TestPrint.c
|
TestPrint.c
|
||||||
TestPubSub.c
|
TestPubSub.c
|
||||||
|
28
winpr/libwinpr/utils/test/TestBacktrace.c
Normal file
28
winpr/libwinpr/utils/test/TestBacktrace.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <winpr/debug.h>
|
||||||
|
|
||||||
|
int TestBacktrace(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
size_t used, x;
|
||||||
|
char **msg;
|
||||||
|
void *stack = winpr_backtrace(20);
|
||||||
|
if (!stack)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "winpr_backtrace failed!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = winpr_backtrace_symbols(stack, &used);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
for (x=0; x<used; x++)
|
||||||
|
printf("%zd: %s\n", x, msg[x]);
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
winpr_backtrace_symbols_fd(stack, stdout);
|
||||||
|
|
||||||
|
winpr_backtrace_free(stack);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user