1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
/* debug.h
*
* Definitions for the debug and run-time analysis support module.
* Contains a lot of macros.
*
* Copyright 2008-2012 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DEBUG_H_INCLUDED
#define DEBUG_H_INCLUDED
#include <pthread.h>
#include "obj-types.h"
/* some settings for various debug modes */
#define DEBUG_OFF 0
#define DEBUG_ONDEMAND 1
#define DEBUG_FULL 2
/* external static data elements (some time to be replaced) */
extern int Debug; /* debug flag - read-only after startup */
extern int debugging_on; /* read-only, except on sig USR1 */
extern int stddbg; /* the handle for regular debug output, set to stdout if not forking, -1 otherwise */
/* data types */
/* the function database. It is used as a static var inside each function. That provides
* us the fast access to it that we need to make the instrumentation work. It's address
* also serves as a unique function identifier and can be used inside other structures
* to refer to the function (e.g. for pretty-printing names).
* rgerhards, 2008-01-24
*/
typedef struct dbgFuncDBmutInfoEntry_s {
pthread_mutex_t *pmut;
int lockLn; /* line where it was locked (inside our func): -1 means mutex is not locked */
pthread_t thrd; /* thrd where the mutex was locked */
unsigned long lInvocation; /* invocation (unique during program run!) of this function that locked the mutex */
} dbgFuncDBmutInfoEntry_t;
typedef struct dbgFuncDB_s {
unsigned magic;
unsigned long nTimesCalled;
char *func;
char *file;
int line;
dbgFuncDBmutInfoEntry_t mutInfo[5];
/* remember to update the initializer if you add anything or change the order! */
} dbgFuncDB_t;
#define dbgFUNCDB_MAGIC 0xA1B2C3D4
#define dbgFuncDB_t_INITIALIZER \
{ \
.magic = dbgFUNCDB_MAGIC,\
.nTimesCalled = 0,\
.func = __func__, \
.file = __FILE__, \
.line = __LINE__ \
}
/* the structure below was originally just the thread's call stack, but it has
* a bit evolved over time. So we have now ended up with the fact that it
* all debug info we know about the thread.
*/
typedef struct dbgCallStack_s {
pthread_t thrd;
dbgFuncDB_t *callStack[500];
int lastLine[500]; /* last line where code execution was seen */
int stackPtr;
int stackPtrMax;
char *pszThrdName;
struct dbgCallStack_s *pNext;
struct dbgCallStack_s *pPrev;
} dbgThrdInfo_t;
/* prototypes */
rsRetVal dbgClassInit(void);
rsRetVal dbgClassExit(void);
void dbgSetDebugFile(uchar *fn);
void dbgSetDebugLevel(int level);
void sigsegvHdlr(int signum);
void dbgoprint(obj_t *pObj, char *fmt, ...) __attribute__((format(printf, 2, 3)));
void dbgprintf(char *fmt, ...) __attribute__((format(printf, 1, 2)));
int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgMutexTryLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgCondTimedWait(pthread_cond_t *cond, pthread_mutex_t *pmut, const struct timespec *abstime, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
void dbgFree(void *pMem, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr);
int dbgEntrFunc(dbgFuncDB_t **ppFuncDB, const char *file, const char *func, int line);
void dbgExitFunc(dbgFuncDB_t *pFuncDB, int iStackPtrRestore, int iRet);
void dbgSetExecLocation(int iStackPtr, int line);
void dbgSetThrdName(uchar *pszName);
void dbgPrintAllDebugInfo(void);
void *dbgmalloc(size_t size);
void dbgOutputTID(char* name);
int dbgGetDbglogFd(void);
/* macros */
#ifdef DEBUGLESS
# define DBGPRINTF(...) {}
# define DBGOPRINT(...) {}
#else
# define DBGPRINTF(...) if(Debug) { dbgprintf(__VA_ARGS__); }
# define DBGOPRINT(...) if(Debug) { dbgoprint(__VA_ARGS__); }
#endif
#ifdef RTINST
# define BEGINfunc static dbgFuncDB_t *pdbgFuncDB; int dbgCALLStaCK_POP_POINT = dbgEntrFunc(&pdbgFuncDB, __FILE__, __func__, __LINE__);
# define ENDfunc dbgExitFunc(pdbgFuncDB, dbgCALLStaCK_POP_POINT, RS_RET_NO_IRET);
# define ENDfuncIRet dbgExitFunc(pdbgFuncDB, dbgCALLStaCK_POP_POINT, iRet);
# define ASSERT(x) assert(x)
#else
# define BEGINfunc
# define ENDfunc
# define ENDfuncIRet
# define ASSERT(x)
#endif
#ifdef RTINST
# define RUNLOG dbgSetExecLocation(dbgCALLStaCK_POP_POINT, __LINE__); dbgprintf("%s:%d: %s: log point\n", __FILE__, __LINE__, __func__)
# define RUNLOG_VAR(fmt, x) dbgSetExecLocation(dbgCALLStaCK_POP_POINT, __LINE__);\
dbgprintf("%s:%d: %s: var '%s'[%s]: " fmt "\n", __FILE__, __LINE__, __func__, #x, fmt, x)
# define RUNLOG_STR(str) dbgSetExecLocation(dbgCALLStaCK_POP_POINT, __LINE__);\
dbgprintf("%s:%d: %s: %s\n", __FILE__, __LINE__, __func__, str)
#else
# define RUNLOG
# define RUNLOG_VAR(fmt, x)
# define RUNLOG_STR(str)
#endif
#ifdef MEMCHECK
# define MALLOC(x) dbgmalloc(x)
#else
# define MALLOC(x) malloc(x)
#endif
/* mutex operations */
#define MUTOP_LOCKWAIT 1
#define MUTOP_LOCK 2
#define MUTOP_UNLOCK 3
#define MUTOP_TRYLOCK 4
/* debug aides */
#ifdef RTINST
#define d_pthread_mutex_lock(x) dbgMutexLock(x, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_mutex_trylock(x) dbgMutexTryLock(x, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_mutex_unlock(x) dbgMutexUnlock(x, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_cond_wait(cond, mut) dbgCondWait(cond, mut, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_cond_timedwait(cond, mut, to) dbgCondTimedWait(cond, mut, to, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_free(x) dbgFree(x, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#else
#define d_pthread_mutex_lock(x) pthread_mutex_lock(x)
#define d_pthread_mutex_trylock(x) pthread_mutex_trylock(x)
#define d_pthread_mutex_unlock(x) pthread_mutex_unlock(x)
#define d_pthread_cond_wait(cond, mut) pthread_cond_wait(cond, mut)
#define d_pthread_cond_timedwait(cond, mut, to) pthread_cond_timedwait(cond, mut, to)
#define d_free(x) free(x)
#endif
#endif /* #ifndef DEBUG_H_INCLUDED */
|