Coverage Report

Created: 2023-11-27 07:17

/src/FreeRDP/winpr/libwinpr/utils/debug.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Debugging Utils
4
 *
5
 * Copyright 2014 Armin Novak <armin.novak@thincast.com>
6
 * Copyright 2014 Thincast Technologies GmbH
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
#include <winpr/config.h>
22
23
#include <stdio.h>
24
#include <fcntl.h>
25
26
#include <winpr/crt.h>
27
#include <winpr/string.h>
28
29
#if defined(WINPR_HAVE_EXECINFO_H)
30
#include <execinfo/debug.h>
31
#endif
32
33
#if defined(USE_UNWIND)
34
#include <unwind/debug.h>
35
#endif
36
37
#if defined(WINPR_HAVE_CORKSCREW)
38
#include <corkscrew/debug.h>
39
#endif
40
41
#if defined(_WIN32) || defined(_WIN64)
42
#include <io.h>
43
#include <windows/debug.h>
44
#endif
45
46
#include <winpr/crt.h>
47
#include <winpr/wlog.h>
48
#include <winpr/debug.h>
49
50
#ifndef MIN
51
#define MIN(a, b) (a) < (b) ? (a) : (b)
52
#endif
53
54
#define TAG "com.winpr.utils.debug"
55
#define LOGT(...)                                           \
56
  do                                                      \
57
  {                                                       \
58
    WLog_Print(WLog_Get(TAG), WLOG_TRACE, __VA_ARGS__); \
59
  } while (0)
60
#define LOGD(...)                                           \
61
  do                                                      \
62
  {                                                       \
63
    WLog_Print(WLog_Get(TAG), WLOG_DEBUG, __VA_ARGS__); \
64
  } while (0)
65
#define LOGI(...)                                          \
66
  do                                                     \
67
  {                                                      \
68
    WLog_Print(WLog_Get(TAG), WLOG_INFO, __VA_ARGS__); \
69
  } while (0)
70
#define LOGW(...)                                          \
71
  do                                                     \
72
  {                                                      \
73
    WLog_Print(WLog_Get(TAG), WLOG_WARN, __VA_ARGS__); \
74
  } while (0)
75
#define LOGE(...)                                           \
76
  do                                                      \
77
  {                                                       \
78
    WLog_Print(WLog_Get(TAG), WLOG_ERROR, __VA_ARGS__); \
79
  } while (0)
80
#define LOGF(...)                                           \
81
0
  do                                                      \
82
0
  {                                                       \
83
0
    WLog_Print(WLog_Get(TAG), WLOG_FATAL, __VA_ARGS__); \
84
0
  } while (0)
85
86
static const char* support_msg = "Invalid stacktrace buffer! check if platform is supported!";
87
88
void winpr_backtrace_free(void* buffer)
89
0
{
90
0
  if (!buffer)
91
0
    return;
92
93
#if defined(USE_UNWIND)
94
  winpr_unwind_backtrace_free(buffer);
95
#elif defined(WINPR_HAVE_EXECINFO_H)
96
0
  winpr_execinfo_backtrace_free(buffer);
97
#elif defined(WINPR_HAVE_CORKSCREW)
98
  winpr_corkscrew_backtrace_free(buffer);
99
#elif defined(_WIN32) || defined(_WIN64)
100
  winpr_win_backtrace_free(buffer);
101
#else
102
  LOGF(support_msg);
103
#endif
104
0
}
105
106
void* winpr_backtrace(DWORD size)
107
0
{
108
#if defined(USE_UNWIND)
109
  return winpr_unwind_backtrace(size);
110
#elif defined(WINPR_HAVE_EXECINFO_H)
111
0
  return winpr_execinfo_backtrace(size);
112
#elif defined(WINPR_HAVE_CORKSCREW)
113
  return winpr_corkscrew_backtrace(size);
114
#elif (defined(_WIN32) || defined(_WIN64)) && !defined(_UWP)
115
  return winpr_win_backtrace(size);
116
#else
117
  LOGF(support_msg);
118
  return NULL;
119
#endif
120
0
}
121
122
char** winpr_backtrace_symbols(void* buffer, size_t* used)
123
0
{
124
0
  if (used)
125
0
    *used = 0;
126
127
0
  if (!buffer)
128
0
  {
129
0
    LOGF(support_msg);
130
0
    return NULL;
131
0
  }
132
133
#if defined(USE_UNWIND)
134
  return winpr_unwind_backtrace_symbols(buffer, used);
135
#elif defined(WINPR_HAVE_EXECINFO_H)
136
0
  return winpr_execinfo_backtrace_symbols(buffer, used);
137
#elif defined(WINPR_HAVE_CORKSCREW)
138
  return winpr_corkscrew_backtrace_symbols(buffer, used);
139
#elif (defined(_WIN32) || defined(_WIN64)) && !defined(_UWP)
140
  return winpr_win_backtrace_symbols(buffer, used);
141
#else
142
  LOGF(support_msg);
143
  return NULL;
144
#endif
145
0
}
146
147
void winpr_backtrace_symbols_fd(void* buffer, int fd)
148
0
{
149
0
  if (!buffer)
150
0
  {
151
0
    LOGF(support_msg);
152
0
    return;
153
0
  }
154
155
0
#if defined(WINPR_HAVE_EXECINFO_H) && !defined(USE_UNWIND)
156
0
  winpr_execinfo_backtrace_symbols_fd(buffer, fd);
157
#elif !defined(ANDROID)
158
  {
159
    size_t i;
160
    size_t used = 0;
161
    char** lines = winpr_backtrace_symbols(buffer, &used);
162
163
    if (!lines)
164
      return;
165
166
    for (i = 0; i < used; i++)
167
      _write(fd, lines[i], (unsigned)strnlen(lines[i], UINT32_MAX));
168
  }
169
#else
170
  LOGF(support_msg);
171
#endif
172
0
}
173
174
void winpr_log_backtrace(const char* tag, DWORD level, DWORD size)
175
0
{
176
0
  winpr_log_backtrace_ex(WLog_Get(tag), level, size);
177
0
}
178
179
void winpr_log_backtrace_ex(wLog* log, DWORD level, DWORD size)
180
0
{
181
0
  size_t used, x;
182
0
  char** msg;
183
0
  void* stack = winpr_backtrace(20);
184
185
0
  if (!stack)
186
0
  {
187
0
    WLog_Print(log, WLOG_ERROR, "winpr_backtrace failed!\n");
188
0
    goto fail;
189
0
  }
190
191
0
  msg = winpr_backtrace_symbols(stack, &used);
192
193
0
  if (msg)
194
0
  {
195
0
    for (x = 0; x < used; x++)
196
0
      WLog_Print(log, level, "%" PRIuz ": %s", x, msg[x]);
197
0
  }
198
0
  free(msg);
199
200
0
fail:
201
0
  winpr_backtrace_free(stack);
202
0
}
203
204
char* winpr_strerror(DWORD dw, char* dmsg, size_t size)
205
0
{
206
#if defined(_WIN32)
207
  return winpr_win_strerror(dw, dmsg, size);
208
#else  /* defined(_WIN32) */
209
0
  _snprintf(dmsg, size, "%s", strerror(dw));
210
0
#endif /* defined(_WIN32) */
211
0
  return dmsg;
212
0
}