The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
debug.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/** Debugging function definitions and structures
19 *
20 * @file src/lib/util/debug.h
21 *
22 * @copyright 2015-2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 */
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28#include <freeradius-devel/build.h>
29#include <freeradius-devel/missing.h>
30#include <freeradius-devel/util/fring.h>
31
32#ifdef NO_ASSERT
33# define MEM(x) error "Use of MEM() not allowed in this source file. Deal with memory allocation failure gracefully"
34#else
35/* Short circuit condition to prevent duplicate evaluation */
36# define MEM(x) do { if (!(x)) { fr_cond_assert_msg(0 && (x), "OUT OF MEMORY"); _fr_exit(__FILE__, __LINE__, EXIT_FAILURE, true); } } while (0)
37#endif
38
39typedef enum {
40 DEBUGGER_STATE_UNKNOWN_NO_PTRACE = -3, //!< We don't have ptrace so can't check.
41 DEBUGGER_STATE_UNKNOWN_NO_PTRACE_CAP = -2, //!< CAP_SYS_PTRACE not set for the process.
42 DEBUGGER_STATE_UNKNOWN = -1, //!< Unknown, likely fr_get_debug_state() not called yet.
43 DEBUGGER_STATE_NOT_ATTACHED = 0, //!< We can attach, so a debugger must not be.
44 DEBUGGER_STATE_ATTACHED = 1 //!< We can't attach, it's likely a debugger is already tracing.
46
48
49#define FR_FAULT_LOG(_fmt, ...) fr_fault_log(_fmt "\n", ## __VA_ARGS__)
50#define FR_FAULT_LOG_HEX(_data, _data_len) fr_fault_log_hex(_data, _data_len)
51
52/** Optional callback passed to fr_fault_setup
53 *
54 * Allows optional logic to be run before calling the main fault handler.
55 *
56 * If the callback returns < 0, the main fault handler will not be called.
57 *
58 * @param signum signal raised.
59 * @return
60 * - 0 on success.
61 * - < 0 on failure.
62 */
63typedef int (*fr_fault_cb_t)(int signum);
64typedef struct fr_bt_marker fr_bt_marker_t;
65
66int fr_get_lsan_state(void);
67
68int fr_get_debug_state(void);
69
70void fr_debug_state_store(void);
71
73
74void fr_debug_break(bool always);
75
76void backtrace_print(fr_fring_t *fring, void *obj);
77
79
81
82void fr_panic_on_free(TALLOC_CTX *ctx);
83
84int fr_set_dumpable_init(void);
85
86int fr_set_dumpable(bool allow_core_dumps);
87
88int fr_reset_dumpable(void);
89
90int fr_log_talloc_report(TALLOC_CTX const *ctx);
91
92void fr_fault_backtrace(void);
93
94void fr_fault(int sig);
95
96void fr_talloc_fault_setup(void);
97
98void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx);
99
100int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program);
101
103
104void fr_fault_set_log_fd(int fd);
105
106void fr_fault_log(char const *msg, ...) CC_HINT(format (printf, 1, 2));
107
108void fr_fault_log_hex(uint8_t const *data, size_t data_len);
109
110/** @name Assertion support functions
111 * @{
112 */
113bool _fr_assert_fail(char const *file, int line, char const *expr, char const *msg, ...)
114 CC_HINT(format (printf, 4, 5));
115
116NEVER_RETURNS void _fr_assert_fatal(char const *file, int line, char const *expr, char const *msg, ...)
117 CC_HINT(format (printf, 4, 5));
118
119NEVER_RETURNS void _fr_exit(char const *file, int line, int status, bool now);
120/** @} */
121
122/** @name Assertion and exit macros
123 * @{
124 */
125
126/** Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x
127 *
128 * Should be wrapped in a condition, and if false, should cause function to return
129 * an error code. This allows control to return to the caller if a precondition is
130 * not satisfied and we're not debugging.
131 *
132 * Example:
133 @verbatim
134 if (!fr_cond_assert(request)) return -1
135 @endverbatim
136 *
137 * @param[in] _x expression to test (should evaluate to true)
138 */
139#define fr_cond_assert(_x) likely((bool)((_x) ? true : (_fr_assert_fail(__FILE__, __LINE__, #_x, NULL) && false)))
140
141/** Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x
142 *
143 * Should be wrapped in a condition, and if false, should cause function to return
144 * an error code. This allows control to return to the caller if a precondition is
145 * not satisfied and we're not debugging.
146 *
147 * Example:
148 @verbatim
149 if (!fr_cond_assert_msg(request, "Bad stuff happened: %s", fr_syserror(errno)))) return -1
150 @endverbatim
151 *
152 * @param[in] _x expression to test (should evaluate to true)
153 * @param[in] _fmt of message to log.
154 * @param[in] ... fmt arguments.
155 */
156#define fr_cond_assert_msg(_x, _fmt, ...) likely((bool)((_x) ? true : (_fr_assert_fail(__FILE__, __LINE__, #_x, _fmt, ## __VA_ARGS__) && false)))
157
158/** Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code 134
159 *
160 * Example:
161 @verbatim
162 fr_fatal_assert(<extremely_unlikely_and_fatal_condition>);
163 @endverbatim
164 *
165 * @param _x expression to test (should evaluate to true)
166 */
167#define fr_fatal_assert(_x) if (unlikely(!((bool)(_x)))) _fr_assert_fatal(__FILE__, __LINE__, #_x, NULL)
168
169/** Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code 134
170 *
171 * Should be wrapped in a condition, and if false, should cause function to return
172 * an error code. This allows control to return to the caller if a precondition is
173 * not satisfied and we're not debugging.
174 *
175 * Example:
176 @verbatim
177 fr_fatal_assert(<extremely_unlikely_and_fatal_condition>);
178 @endverbatim
179 *
180 * @param[in] _x expression to test (should evaluate to true)
181 * @param[in] _fmt of message to log.
182 * @param[in] ... fmt arguments.
183 */
184#define fr_fatal_assert_msg(_x, _fmt, ...) if (unlikely(!((bool)(_x)))) _fr_assert_fatal(__FILE__, __LINE__, #_x, _fmt, ## __VA_ARGS__)
185
186/** Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code 134
187 *
188 * @param[in] _msg to log.
189 * @param[in] ... args.
190 */
191#define fr_fatal_assert_fail(_msg, ...) _fr_assert_fatal(__FILE__, __LINE__, "false", _msg, ## __VA_ARGS__)
192
193#ifdef NDEBUG
194# define fr_assert(_x)
195# define fr_assert_msg(_x, _msg, ...)
196# define fr_assert_fail(_msg, ...)
197#elif !defined(STATIC_ANALYZER)
198/** Calls panic_action ifndef NDEBUG, else logs error
199 *
200 * @param[in] _x expression to test (should evaluate to true)
201 */
202# define fr_assert(_x) if (unlikely(!((bool)(_x)))) _fr_assert_fail(__FILE__, __LINE__, #_x, NULL)
203
204/** Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code 134
205 *
206 * @param[in] _x expression to test (should evaluate to true)
207 * @param[in] _msg to log.
208 * @param[in] ... args.
209 */
210# define fr_assert_msg(_x, _msg, ...) if (unlikely(!((bool)(_x)))) _fr_assert_fail(__FILE__, __LINE__, #_x, _msg, ## __VA_ARGS__)
211/** Calls panic_action ifndef NDEBUG, else logs error
212 *
213 * @param[in] _msg to log.
214 * @param[in] ... args.
215 */
216#define fr_assert_fail(_msg, ...) _fr_assert_fail(__FILE__, __LINE__, "false", _msg, ## __VA_ARGS__)
217#else
218# include <assert.h>
219# define fr_assert(_x) assert(_x)
220# define fr_assert_msg(_x, _msg, ...) assert(_x)
221# define fr_assert_fail(_msg ...) assert(0)
222#endif
223
224/** Exit, producing a log message in debug builds
225 *
226 * @param[in] _x code to exit with.
227 */
228# define fr_exit(_x) _fr_exit(__FILE__, __LINE__, (_x), false)
229
230/** Exit without calling atexit() handlers, producing a log message in debug builds
231 *
232 * @param[in] _x code to exit with.
233 */
234# define fr_exit_now(_x) _fr_exit(__FILE__, __LINE__, (_x), true)
235/** @} */
236
237void fr_sign_struct(void *ptr, size_t size, size_t offset);
238void fr_verify_struct(void const *ptr, size_t size, size_t offset);
239void fr_verify_struct_member(void const *ptr, size_t len, uint32_t *signature);
240
241/** Manual validation of structures.
242 *
243 * typedef struct {
244 * char *a;
245 * int b;
246 * FR_SIGNATURE // no semicolon!
247 * } foo_t;
248 *
249 * and then once the structure is initialized (and will never be changed)
250 *
251 * foo_t *ptr;
252 * FR_STRUCT_SIGN(ptr);
253 *
254 * and some time later...
255 *
256 * foo_t *ptr;
257 * FR_STRUCT_VERIFY(ptr);
258 *
259 * Note that the structure can't contain variable elements such as fr_dlist_t.
260 * And that we're not verifying the contents of the members which are pointers.
261 */
262#ifndef NDEBUG
263#define FR_STRUCT_SIGN(_ptr) fr_sign_struct(_ptr, sizeof(__typeof__(*_ptr)), offsetof(__typeof__(*_ptr), _signature));
264#define FR_STRUCT_VERIFY(_ptr) fr_verify_struct(_ptr, sizeof(__typeof__(*_ptr)), offsetof(__typeof__(*_ptr), _signature))
265#define FR_STRUCT_SIGNATURE uint32_t _signature;
266
267#define FR_STRUCT_MEMBER_SIGN(_ptr, _member, _len) _ptr->_signature_##_member = fr_hash(_ptr->_member, _len)
268#define FR_STRUCT_MEMBER_VERIFY(_ptr, _member, _len) fr_verify_struct_member(_ptr->_member, _len, &(_ptr->_signature_##_member))
269#define FR_STRUCT_MEMBER_SIGNATURE(_member) uint32_t _signature_##_member;
270#else
271#define FR_STRUCT_SIGN(_ptr)
272#define FR_STRUCT_VERIFY(_ptr)
273#define FR_STRUCT_SIGNATURE
274
275#define FR_STRUCT_MEMBER_SIGN(_ptr, _member, _len)
276#define FR_STRUCT_MEMBER_VERIFY(_ptr, _member, _len)
277#define FR_STRUCT_MEMBER_SIGNATURE(_member)
278#endif
279
280#ifdef __cplusplus
281}
282#endif
int const char * file
Definition acutest.h:702
log_entry msg
Definition acutest.h:794
int const char int line
Definition acutest.h:702
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:313
char const * fr_debug_state_to_msg(fr_debug_state_t state)
Return current value of debug_state.
Definition debug.c:541
bool _fr_assert_fail(char const *file, int line, char const *expr, char const *msg,...))
A soft assertion which triggers the fault handler in debug builds.
Definition debug.c:1449
fr_debug_state_t
Definition debug.h:39
@ DEBUGGER_STATE_NOT_ATTACHED
We can attach, so a debugger must not be.
Definition debug.h:43
@ DEBUGGER_STATE_UNKNOWN_NO_PTRACE
We don't have ptrace so can't check.
Definition debug.h:40
@ DEBUGGER_STATE_UNKNOWN_NO_PTRACE_CAP
CAP_SYS_PTRACE not set for the process.
Definition debug.h:41
@ DEBUGGER_STATE_UNKNOWN
Unknown, likely fr_get_debug_state() not called yet.
Definition debug.h:42
@ DEBUGGER_STATE_ATTACHED
We can't attach, it's likely a debugger is already tracing.
Definition debug.h:44
void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx)
Disable the null tracking context when a talloc chunk is freed.
Definition debug.c:1207
void fr_fault_set_log_fd(int fd)
Set a file descriptor to log memory reports to.
Definition debug.c:1435
struct fr_bt_marker fr_bt_marker_t
Definition debug.h:64
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition debug.c:1147
int fr_set_dumpable(bool allow_core_dumps)
Enable or disable core dumps.
Definition debug.c:822
void fr_verify_struct(void const *ptr, size_t size, size_t offset)
Definition debug.c:1569
void fr_fault_backtrace(void)
Split out so it can be sprinkled throughout the server and called via a debugger.
Definition debug.c:945
void fr_fault_log(char const *msg,...))
Log output to the fr_fault_log_fd.
Definition debug.c:1401
int(* fr_fault_cb_t)(int signum)
Optional callback passed to fr_fault_setup.
Definition debug.h:63
int fr_reset_dumpable(void)
Reset dumpable state to previously configured value.
Definition debug.c:890
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition debug.c:1242
void fr_verify_struct_member(void const *ptr, size_t len, uint32_t *signature)
Definition debug.c:1578
void fr_sign_struct(void *ptr, size_t size, size_t offset)
Definition debug.c:1564
NEVER_RETURNS void _fr_assert_fatal(char const *file, int line, char const *expr, char const *msg,...))
A fatal assertion which triggers the fault handler in debug builds or exits.
Definition debug.c:1485
int fr_get_lsan_state(void)
Definition debug.c:261
void fr_debug_state_store(void)
Should be run before using setuid or setgid to get useful results.
Definition debug.c:521
void fr_fault(int sig)
Prints a simple backtrace (if execinfo is available) and calls panic_action if set.
Definition debug.c:975
NEVER_RETURNS void _fr_exit(char const *file, int line, int status, bool now)
Exit possibly printing a message about why we're exiting.
Definition debug.c:1517
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
Definition debug.c:1223
fr_bt_marker_t * fr_backtrace_attach(fr_fring_t **fring, TALLOC_CTX *obj)
void fr_debug_break(bool always)
Break in debugger (if were running under a debugger)
Definition debug.c:570
void fr_fault_set_cb(fr_fault_cb_t func)
Set a callback to be called before fr_fault()
Definition debug.c:1387
void fr_fault_log_hex(uint8_t const *data, size_t data_len)
Print data as a hex block.
Definition debug.c:1415
int fr_set_dumpable_init(void)
Get the current maximum for core files.
Definition debug.c:807
void fr_panic_on_free(TALLOC_CTX *ctx)
Insert memory into the context of another talloc memory chunk which causes a panic when freed.
Definition debug.c:712
fr_debug_state_t fr_debug_state
Whether we're attached to by a debugger.
Definition debug.c:104
int fr_backtrace_do(fr_bt_marker_t *marker)
int fr_get_debug_state(void)
Definition debug.c:509
void backtrace_print(fr_fring_t *fring, void *obj)
Standard thread safe circular buffer.
Definition fring.c:36
unsigned int uint32_t
unsigned char uint8_t
static fr_slen_t data
Definition value.h:1265