fix prevent violation
[framework/system/dynamic-analysis-probe.git] / include / daprobe.h
1 /*
2  *  DA probe
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: 
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * 
12  * This library is free software; you can redistribute it and/or modify it under
13  * the terms of the GNU Lesser General Public License as published by the
14  * Free Software Foundation; either version 2.1 of the License, or (at your option)
15  * any later version.
16  * 
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
18  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20  * License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * along with this library; if not, write to the Free Software Foundation, Inc., 51
24  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * 
29  */
30
31 #ifndef __DAPROBE_H__
32 #define __DAPROBE_H__
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdbool.h>
37 #include <dlfcn.h>
38 #include "probeinfo.h"
39
40 #ifdef __cplusplus
41 extern "C"{
42 #endif
43
44 #ifndef likely
45 #define likely(x)       __builtin_expect((x),1)
46 #define unlikely(x)     __builtin_expect((x),0)
47 #endif
48
49 #define NUM_OF_MONITOR          3
50 #define DA_LOG_MAX                      4096
51 #define PERROR_MSG_MAX          128
52
53 #define DEFAULT_TOKEN   "`,"
54
55 #define CALLER_ADDRESS  \
56         ((void*) __builtin_extract_return_addr(__builtin_return_address(0)))
57
58 #define BACKTRACE_SYMBOLS cached_backtrace_symbols
59
60 typedef enum
61 {
62         MT_MEMORY,
63         MT_FILE,
64         MT_SOCKET,
65 } MonitorType;
66
67 enum BlockLocation
68 {
69         BL_PRE,
70         BL_POST,
71 };
72
73 typedef struct
74 {
75         int type;
76         int length;
77         char data[DA_LOG_MAX];
78 } log_t;
79
80 typedef struct
81 {
82         int                             eventIndex;
83         int                             pID;
84         int                             tID;
85         unsigned long   currentTime;
86         unsigned int    callDepth;
87 } probeInfo_t;
88
89 /***************************************************************************
90  * helper apis
91  ***************************************************************************/
92
93 int preBlockBegin(void* caller, bool bFiltering, enum DaOptions);
94 void preBlockEnd();
95
96 int postBlockBegin(int preresult);
97 void postBlockEnd();
98
99 void probeBlockStart();
100 void probeBlockEnd();
101
102 unsigned int getCurrentEventIndex();
103 unsigned int getCallDepth();
104 unsigned long getTraceState();
105 unsigned long getCurrentTime();
106 bool setProbePoint(probeInfo_t * iProbe);
107 int update_heap_memory_size(bool isAdd, size_t size);
108
109 bool printLogStr(const char* str, int msgType);
110 bool printLog(log_t* log, int msgType);
111 int __appendTypeLog(log_t* log, int nInput, char* token, ...);
112 int getBacktraceString(log_t* log, int bufsize);
113
114 //char* captureScreenShotX(int* width, int* height);
115 //void releaseScreenShotX();
116
117 //int printSamplingLog(void);
118
119 //bool captureScreen(unsigned int logNum);
120 //void captureProbe();
121 //int registeScreenChange(int renderID);
122 //void detectTouchEvent(int touchID);
123 //int getTouchState();
124 //int isPossibleCapture();
125
126
127 /***************************************************************************
128  * helper macros
129  ***************************************************************************/
130
131 // ========================= print log =====================================
132 #define PRINTMSG(msg)   printLogStr(msg, MSG_MSG)
133
134 // =========================== declare variables ===========================
135 // local variable is faster than heap allocated variable
136 // array variable initialization with declare is expensive than memset
137 #define DECLARE_COMMON_VARIABLE                 \
138                 probeInfo_t     probeInfo;                      \
139                 log_t           log
140
141 // declare variable for standard api (not tizen related api)
142 #define DECLARE_VARIABLE_STANDARD               \
143                 DECLARE_COMMON_VARIABLE;                \
144                 int blockresult;                                \
145                 bool bfiltering = true;                 \
146                 int olderrno, newerrno;                 \
147                 int __attribute__((unused)) ret
148
149 // ========================== initialize variable ==========================
150
151 #define INIT_LOG                        \
152                 log.type = 0;           \
153                 log.length = 0;         \
154                 log.data[0] = '\0'
155
156 // ========================== get function pointer =========================
157
158 #define GET_REAL_FUNCP(FUNCNAME, SONAME, FUNCTIONPOINTER)                       \
159                 do {                                                                                                            \
160                         if(!FUNCTIONPOINTER) {                                                                  \
161                                 probeBlockStart();                                                                      \
162                                 if(lib_handle[SONAME] == NULL) {                                        \
163                                         lib_handle[SONAME] = dlopen(lib_string[SONAME], RTLD_LAZY);                     \
164                                         if(lib_handle[SONAME] == NULL) {                                \
165                                                 char perror_msg[PERROR_MSG_MAX];                        \
166                                                 sprintf(perror_msg, "dlopen failed : %s", lib_string[SONAME]);  \
167                                                 perror(perror_msg);                                                     \
168                                                 exit(0);                                                                        \
169                                         }                                                                                               \
170                                 }                                                                                                       \
171                                 FUNCTIONPOINTER = dlsym(lib_handle[SONAME], #FUNCNAME);         \
172                                 if(FUNCTIONPOINTER == NULL || dlerror() != NULL) {      \
173                                         perror("dlsym failed : " #FUNCNAME);                    \
174                                         exit(0);                                                                                \
175                                 }                                                                                                       \
176                                 probeBlockEnd();                                                                        \
177                         }                                                                                                               \
178                 } while(0)
179
180 #define GET_REAL_FUNC(FUNCNAME, SONAME)         \
181                 GET_REAL_FUNCP(FUNCNAME, SONAME, FUNCNAME##p)
182
183 #define GET_REAL_FUNCP_RTLD_NEXT(FUNCNAME, FUNCTIONPOINTER)                     \
184                 do {                                                                                                            \
185                         if(!FUNCTIONPOINTER) {                                                                  \
186                                 probeBlockStart();                                                                      \
187                                 FUNCTIONPOINTER = dlsym(RTLD_NEXT, #FUNCNAME);          \
188                                 if(FUNCTIONPOINTER == NULL || dlerror() != NULL) {      \
189                                         perror("dlsym failed");                                                 \
190                                         exit(0);                                                                                \
191                                 }                                                                                                       \
192                                 probeBlockEnd();                                                                        \
193                         }                                                                                                               \
194                 } while(0)
195
196 #define GET_REAL_FUNC_RTLD_NEXT(FUNCNAME)       \
197                 GET_REAL_FUNCP_RTLD_NEXT(FUNCNAME, FUNCNAME##p)
198
199 #define GET_REAL_FUNCP_RTLD_NEXT_CPP(FUNCNAME, FUNCTIONPOINTER)         \
200                 do {                                                                                                            \
201                         if(!FUNCTIONPOINTER) {                                                                  \
202                                 probeBlockStart();                                                                      \
203                                 void* funcp = dlsym(RTLD_NEXT, #FUNCNAME);                      \
204                                 if(funcp == NULL || dlerror() != NULL) {                        \
205                                         perror("dlsym failed : " #FUNCNAME);                    \
206                                         exit(0);                                                                                \
207                                 }                                                                                                       \
208                                 memcpy(&FUNCTIONPOINTER, &funcp, sizeof(void*));        \
209                                 probeBlockEnd();                                                                        \
210                         }                                                                                                               \
211                 } while(0)
212
213 #define GET_REAL_FUNC_RTLD_NEXT_CPP(FUNCNAME)   \
214                 GET_REAL_FUNCP_RTLD_NEXT_CPP(FUNCNAME, FUNCNAME##p)
215
216 // ======================= pre block macro ================================
217
218 #define PRE_PROBEBLOCK_BEGIN()                                                                                                  \
219         if((blockresult = preBlockBegin(CALLER_ADDRESS, bfiltering, _sopt)) != 0) {     \
220                 setProbePoint(&probeInfo)
221
222 #define PRE_PROBEBLOCK_END()    \
223                 preBlockEnd();                  \
224         }                                                       \
225         olderrno = errno;                       \
226         errno = 0
227
228 #define PRE_PROBEBLOCK() \
229                 PRE_PROBEBLOCK_BEGIN(); \
230                 PRE_PROBEBLOCK_END()
231
232 // ========================== make log macro ================================
233 #define APPEND_LOG_BASIC(LCTYPE)                                                                \
234         log.length = sprintf(log.data, "%d`,%d`,%s`,%lu`,%d`,%d",       \
235                         LCTYPE, probeInfo.eventIndex, __func__,                         \
236                         probeInfo.currentTime, probeInfo.pID, probeInfo.tID)
237
238 #define APPEND_LOG_BASIC_NAME(LCTYPE, APINAME)                                  \
239         log.length = sprintf(log.data, "%d`,%d`,%s`,%lu`,%d`,%d",       \
240                 LCTYPE, probeInfo.eventIndex, APINAME,                                  \
241                 probeInfo.currentTime, probeInfo.pID, probeInfo.tID)
242
243 #define APPEND_LOG_COMMON_NONE(CALLER)                                                          \
244         log.length += sprintf(log.data + log.length, "`,`,`,`,`,`,%u",  \
245                 (unsigned int)CALLER)
246
247 #define APPEND_LOG_INPUT(INPUTFORMAT, ...)                                                              \
248         log.length += sprintf(log.data + log.length,                                            \
249                         DEFAULT_TOKEN INPUTFORMAT, __VA_ARGS__)
250
251 #define APPEND_LOG_RESULT(RETTYPE, RETVALUE)                                                    \
252         __appendTypeLog(&log, 4, NULL, RETTYPE, RETVALUE, VT_INT, 0,            \
253                         VT_INT, newerrno, VT_INT, blockresult)
254
255 #define APPEND_LOG_CALLER()                                                                                             \
256         log.length += sprintf(log.data + log.length,                                            \
257                         "`,%u",(unsigned int) CALLER_ADDRESS)
258
259 #if defined(USING_BACKTRACE) || defined(PRINT_BACKTRACE_CALLSTACK)
260 #define APPEND_LOG_CALLSTACK()                                                                                  \
261         log.length += sprintf(log.data + log.length,                                            \
262                         "`,\ncallstack_start`,");                                                                       \
263         getBacktraceString(&log, DA_LOG_MAX - log.length - 17);                         \
264         log.length += sprintf(log.data + log.length, "`,callstack_end")
265 #else
266 #define APPEND_LOG_CALLSTACK()  APPEND_LOG_NULL_CALLSTACK()
267 #endif
268
269 #define APPEND_LOG_NULL_CALLSTACK()                                                                             \
270         log.length += sprintf(log.data + log.length,                                            \
271                         "`,\ncallstack_start`,`,callstack_end")
272
273
274 // =========================== post block macro ===========================
275
276 #define POST_PROBEBLOCK_BEGIN(LCTYPE, RETTYPE, RETVALUE, INPUTFORMAT, ...)      \
277         newerrno = errno;                                                                                                               \
278         if(postBlockBegin(blockresult)) {                                                                               \
279                 INIT_LOG;                                                                                                                       \
280                 APPEND_LOG_BASIC(LCTYPE);                                                                                       \
281                 APPEND_LOG_INPUT(INPUTFORMAT, __VA_ARGS__);                                                     \
282                 APPEND_LOG_RESULT(RETTYPE, RETVALUE);                                                           \
283                 APPEND_LOG_CALLER()
284
285 #define POST_PROBEBLOCK_CALLSTACK()                     \
286         do {                                                                    \
287                 if(newerrno != 0) {                                     \
288                         APPEND_LOG_CALLSTACK();                 \
289                 } else {                                                        \
290                         APPEND_LOG_NULL_CALLSTACK();    \
291                 }                                                                       \
292         } while(0)
293
294
295 #define POST_PROBEBLOCK_END()                                           \
296                 printLog(&log, MSG_LOG);                                        \
297                 postBlockEnd();                                                         \
298         }                                                                                               \
299         errno = (newerrno != 0) ? newerrno : olderrno
300
301 // ===================== unconditional probe block ========================
302
303 #define PRE_UNCONDITIONAL_BLOCK_BEGIN() \
304         do {                                                            \
305                 probeBlockStart();                              \
306                 setProbePoint(&probeInfo)
307
308 #define PRE_UNCONDITIONAL_BLOCK_END()   \
309                 probeBlockEnd();                                \
310         } while(0)
311
312 #define POST_UNCONDITIONAL_BLOCK_BEGIN(LCTYPE)  \
313         do {                                                                            \
314                 probeBlockStart();                                              \
315                 INIT_LOG;                                                               \
316                 APPEND_LOG_BASIC(LCTYPE)
317                 
318 #define POST_UNCONDITIONAL_BLOCK_END()                  \
319                 printLog(&log, MSG_LOG);                                \
320                 probeBlockEnd();                                                \
321         } while(0)
322
323 // ========================= simplify macro ================================
324
325 #define BEFORE_ORIGINAL(FUNCNAME, LIBNAME)      \
326         DECLARE_VARIABLE_STANDARD;                              \
327         GET_REAL_FUNC(FUNCNAME, LIBNAME);               \
328         PRE_PROBEBLOCK()
329
330 #define BEFORE_ORIGINAL_NOFILTER(FUNCNAME, LIBNAME)     \
331         DECLARE_VARIABLE_STANDARD;                                              \
332         GET_REAL_FUNC(FUNCNAME, LIBNAME);                               \
333         bfiltering = false;                                                             \
334         PRE_PROBEBLOCK()
335
336 #ifdef __cplusplus
337 }
338 #endif
339
340 #endif