You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
5.5 KiB
182 lines
5.5 KiB
/*
|
|
* include/haproxy/bug.h
|
|
* Assertions and instant crash macros needed everywhere.
|
|
*
|
|
* Copyright (C) 2000-2020 Willy Tarreau - w@1wt.eu
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#ifndef _HAPROXY_BUG_H
|
|
#define _HAPROXY_BUG_H
|
|
|
|
#include <haproxy/compiler.h>
|
|
|
|
/* quick debugging hack, should really be removed ASAP */
|
|
#ifdef DEBUG_FULL
|
|
#define DPRINTF(x...) fprintf(x)
|
|
#else
|
|
#define DPRINTF(x...)
|
|
#endif
|
|
|
|
#ifdef DEBUG_USE_ABORT
|
|
/* abort() is better recognized by code analysis tools */
|
|
#define ABORT_NOW() abort()
|
|
#else
|
|
/* More efficient than abort() because it does not mangle the
|
|
* stack and stops at the exact location we need.
|
|
*/
|
|
#define ABORT_NOW() (*(volatile int*)1=0)
|
|
#endif
|
|
|
|
/* BUG_ON: complains if <cond> is true when DEBUG_STRICT or DEBUG_STRICT_NOCRASH
|
|
* are set, does nothing otherwise. With DEBUG_STRICT in addition it immediately
|
|
* crashes using ABORT_NOW() above.
|
|
*/
|
|
#if defined(DEBUG_STRICT) || defined(DEBUG_STRICT_NOCRASH)
|
|
#if defined(DEBUG_STRICT)
|
|
#define CRASH_NOW() ABORT_NOW()
|
|
#else
|
|
#define CRASH_NOW()
|
|
#endif
|
|
|
|
#define BUG_ON(cond) _BUG_ON(cond, __FILE__, __LINE__)
|
|
#define _BUG_ON(cond, file, line) __BUG_ON(cond, file, line)
|
|
#define __BUG_ON(cond, file, line) \
|
|
do { \
|
|
if (unlikely(cond)) { \
|
|
const char msg[] = "\nFATAL: bug condition \"" #cond "\" matched at " file ":" #line "\n"; \
|
|
DISGUISE(write(2, msg, __builtin_strlen(msg))); \
|
|
CRASH_NOW(); \
|
|
} \
|
|
} while (0)
|
|
#else
|
|
#undef CRASH_NOW
|
|
#define BUG_ON(cond)
|
|
#endif
|
|
|
|
|
|
#if defined(DEBUG_MEM_STATS)
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/* Memory allocation statistics are centralized into a global "mem_stats"
|
|
* section. This will not work with some linkers.
|
|
*/
|
|
enum {
|
|
MEM_STATS_TYPE_UNSET = 0,
|
|
MEM_STATS_TYPE_CALLOC,
|
|
MEM_STATS_TYPE_FREE,
|
|
MEM_STATS_TYPE_MALLOC,
|
|
MEM_STATS_TYPE_REALLOC,
|
|
MEM_STATS_TYPE_STRDUP,
|
|
};
|
|
|
|
struct mem_stats {
|
|
size_t calls;
|
|
size_t size;
|
|
const char *file;
|
|
int line;
|
|
int type;
|
|
};
|
|
|
|
#undef calloc
|
|
#define calloc(x,y) ({ \
|
|
size_t __x = (x); size_t __y = (y); \
|
|
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
|
|
.file = __FILE__, .line = __LINE__, \
|
|
.type = MEM_STATS_TYPE_CALLOC, \
|
|
}; \
|
|
__asm__(".globl __start_mem_stats"); \
|
|
__asm__(".globl __stop_mem_stats"); \
|
|
_HA_ATOMIC_ADD(&_.calls, 1); \
|
|
_HA_ATOMIC_ADD(&_.size, __x * __y); \
|
|
calloc(__x,__y); \
|
|
})
|
|
|
|
/* note: we can't redefine free() because we have a few variables and struct
|
|
* members called like this.
|
|
*/
|
|
#undef __free
|
|
#define __free(x) ({ \
|
|
void *__x = (x); \
|
|
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
|
|
.file = __FILE__, .line = __LINE__, \
|
|
.type = MEM_STATS_TYPE_FREE, \
|
|
}; \
|
|
__asm__(".globl __start_mem_stats"); \
|
|
__asm__(".globl __stop_mem_stats"); \
|
|
if (__x) \
|
|
_HA_ATOMIC_ADD(&_.calls, 1); \
|
|
free(__x); \
|
|
})
|
|
|
|
#undef malloc
|
|
#define malloc(x) ({ \
|
|
size_t __x = (x); \
|
|
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
|
|
.file = __FILE__, .line = __LINE__, \
|
|
.type = MEM_STATS_TYPE_MALLOC, \
|
|
}; \
|
|
__asm__(".globl __start_mem_stats"); \
|
|
__asm__(".globl __stop_mem_stats"); \
|
|
_HA_ATOMIC_ADD(&_.calls, 1); \
|
|
_HA_ATOMIC_ADD(&_.size, __x); \
|
|
malloc(__x); \
|
|
})
|
|
|
|
#undef realloc
|
|
#define realloc(x,y) ({ \
|
|
void *__x = (x); size_t __y = (y); \
|
|
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
|
|
.file = __FILE__, .line = __LINE__, \
|
|
.type = MEM_STATS_TYPE_REALLOC, \
|
|
}; \
|
|
__asm__(".globl __start_mem_stats"); \
|
|
__asm__(".globl __stop_mem_stats"); \
|
|
_HA_ATOMIC_ADD(&_.calls, 1); \
|
|
_HA_ATOMIC_ADD(&_.size, __y); \
|
|
realloc(__x,__y); \
|
|
})
|
|
|
|
#undef strdup
|
|
#define strdup(x) ({ \
|
|
const char *__x = (x); size_t __y = strlen(__x); \
|
|
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
|
|
.file = __FILE__, .line = __LINE__, \
|
|
.type = MEM_STATS_TYPE_STRDUP, \
|
|
}; \
|
|
__asm__(".globl __start_mem_stats"); \
|
|
__asm__(".globl __stop_mem_stats"); \
|
|
_HA_ATOMIC_ADD(&_.calls, 1); \
|
|
_HA_ATOMIC_ADD(&_.size, __y); \
|
|
strdup(__x); \
|
|
})
|
|
#endif /* DEBUG_MEM_STATS*/
|
|
|
|
#endif /* _HAPROXY_BUG_H */
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-indent-level: 8
|
|
* c-basic-offset: 8
|
|
* End:
|
|
*/
|
|
|