FreeRDP
Loading...
Searching...
No Matches
windows/debug.c
1
21#include <stdio.h>
22#include <fcntl.h>
23
24#include <io.h>
25#include <windows.h>
26#include <dbghelp.h>
27
28#include "debug.h"
29
30#ifndef MIN
31#define MIN(a, b) (a) < (b) ? (a) : (b)
32#endif
33
34typedef struct
35{
36 PVOID* stack;
37 ULONG used;
38 ULONG max;
39} t_win_stack;
40
41void winpr_win_backtrace_free(void* buffer)
42{
43 t_win_stack* data = (t_win_stack*)buffer;
44 if (!data)
45 return;
46
47 free(data->stack);
48 free(data);
49}
50
51void* winpr_win_backtrace(DWORD size)
52{
53 HANDLE process = GetCurrentProcess();
54 t_win_stack* data = calloc(1, sizeof(t_win_stack));
55
56 if (!data)
57 return nullptr;
58
59 data->max = size;
60 data->stack = calloc(data->max, sizeof(PVOID));
61
62 if (!data->stack)
63 {
64 free(data);
65 return nullptr;
66 }
67
68 SymInitialize(process, nullptr, TRUE);
69 data->used = RtlCaptureStackBackTrace(2, size, data->stack, nullptr);
70 return data;
71}
72
73char** winpr_win_backtrace_symbols(void* buffer, size_t* used)
74{
75 if (used)
76 *used = 0;
77
78 if (!buffer)
79 return nullptr;
80
81 {
82 size_t line_len = 1024;
83 HANDLE process = GetCurrentProcess();
84 t_win_stack* data = (t_win_stack*)buffer;
85 size_t array_size = data->used * sizeof(char*);
86 size_t lines_size = data->used * line_len;
87 char** vlines = calloc(1, array_size + lines_size);
88 SYMBOL_INFO* symbol = calloc(1, sizeof(SYMBOL_INFO) + line_len * sizeof(char));
89 IMAGEHLP_LINE64* line = (IMAGEHLP_LINE64*)calloc(1, sizeof(IMAGEHLP_LINE64));
90
91 if (!vlines || !symbol || !line)
92 {
93 free(vlines);
94 free(symbol);
95 free(line);
96 return nullptr;
97 }
98
99 line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
100 symbol->MaxNameLen = (ULONG)line_len;
101 symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
102
103 /* Set the pointers in the allocated buffer's initial array section */
104 for (size_t i = 0; i < data->used; i++)
105 vlines[i] = (char*)vlines + array_size + i * line_len;
106
107 for (size_t i = 0; i < data->used; i++)
108 {
109 DWORD64 address = (DWORD64)(data->stack[i]);
110 DWORD displacement;
111 SymFromAddr(process, address, 0, symbol);
112
113 if (SymGetLineFromAddr64(process, address, &displacement, line))
114 {
115 (void)sprintf_s(vlines[i], line_len, "%016" PRIx64 ": %s in %s:%" PRIu32,
116 symbol->Address, symbol->Name, line->FileName, line->LineNumber);
117 }
118 else
119 (void)sprintf_s(vlines[i], line_len, "%016" PRIx64 ": %s", symbol->Address,
120 symbol->Name);
121 }
122
123 if (used)
124 *used = data->used;
125
126 free(symbol);
127 free(line);
128 return vlines;
129 }
130}
131
132char* winpr_win_strerror(DWORD dw, char* dmsg, size_t size)
133{
134 DWORD nSize = 0;
135 DWORD dwFlags = 0;
136 LPTSTR msg = nullptr;
137 BOOL alloc = FALSE;
138 dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
139#ifdef FORMAT_MESSAGE_ALLOCATE_BUFFER
140 alloc = TRUE;
141 dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
142#else
143 nSize = (DWORD)(size * sizeof(WCHAR));
144 msg = (LPTSTR)calloc(nSize, sizeof(WCHAR));
145#endif
146 const DWORD rc =
147 FormatMessage(dwFlags, nullptr, dw, 0, alloc ? (LPTSTR)&msg : msg, nSize, nullptr);
148
149 if (rc > 0)
150 {
151#if defined(UNICODE)
152 (void)WideCharToMultiByte(CP_ACP, 0, msg, (int)rc, dmsg, (int)(MIN(size - 1, INT_MAX)),
153 nullptr, nullptr);
154#else /* defined(UNICODE) */
155 memcpy(dmsg, msg, MIN(rc, size - 1));
156#endif /* defined(UNICODE) */
157 dmsg[MIN(rc, size - 1)] = 0;
158#ifdef FORMAT_MESSAGE_ALLOCATE_BUFFER
159 LocalFree(msg);
160#else
161 free(msg);
162#endif
163 }
164 else
165 {
166 (void)_snprintf(dmsg, size, "FAILURE: 0x%08" PRIX32 "", GetLastError());
167 }
168
169 return dmsg;
170}