4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
8 * Jaewon Lim <jaewon81.lim@samsung.com>
9 * Woojin Jung <woojin2.jung@samsung.com>
10 * Juyoung Kim <j0.kim@samsung.com>
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)
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.
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
38 #include "probeinfo.h"
45 #define likely(x) __builtin_expect((x),1)
46 #define unlikely(x) __builtin_expect((x),0)
49 #define NUM_OF_MONITOR 3
50 #define DA_LOG_MAX 4096
51 #define PERROR_MSG_MAX 128
53 #define DEFAULT_TOKEN "`,"
55 #define CALLER_ADDRESS \
56 ((void*) __builtin_extract_return_addr(__builtin_return_address(0)))
58 #define BACKTRACE_SYMBOLS cached_backtrace_symbols
77 char data[DA_LOG_MAX];
85 unsigned long currentTime;
86 unsigned int callDepth;
89 /***************************************************************************
91 ***************************************************************************/
93 int preBlockBegin(void* caller, bool bFiltering, enum DaOptions);
96 int postBlockBegin(int preresult);
99 void probeBlockStart();
100 void probeBlockEnd();
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);
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);
114 //char* captureScreenShotX(int* width, int* height);
115 //void releaseScreenShotX();
117 //int printSamplingLog(void);
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();
127 /***************************************************************************
129 ***************************************************************************/
131 // ========================= print log =====================================
132 #define PRINTMSG(msg) printLogStr(msg, MSG_MSG)
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; \
141 // declare variable for standard api (not tizen related api)
142 #define DECLARE_VARIABLE_STANDARD \
143 DECLARE_COMMON_VARIABLE; \
145 bool bfiltering = true; \
146 int olderrno, newerrno; \
147 int __attribute__((unused)) ret
149 // ========================== initialize variable ==========================
156 // ========================== get function pointer =========================
158 #define GET_REAL_FUNCP(FUNCNAME, SONAME, FUNCTIONPOINTER) \
160 if(!FUNCTIONPOINTER) { \
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); \
171 FUNCTIONPOINTER = dlsym(lib_handle[SONAME], #FUNCNAME); \
172 if(FUNCTIONPOINTER == NULL || dlerror() != NULL) { \
173 perror("dlsym failed : " #FUNCNAME); \
180 #define GET_REAL_FUNC(FUNCNAME, SONAME) \
181 GET_REAL_FUNCP(FUNCNAME, SONAME, FUNCNAME##p)
183 #define GET_REAL_FUNCP_RTLD_NEXT(FUNCNAME, FUNCTIONPOINTER) \
185 if(!FUNCTIONPOINTER) { \
187 FUNCTIONPOINTER = dlsym(RTLD_NEXT, #FUNCNAME); \
188 if(FUNCTIONPOINTER == NULL || dlerror() != NULL) { \
189 perror("dlsym failed"); \
196 #define GET_REAL_FUNC_RTLD_NEXT(FUNCNAME) \
197 GET_REAL_FUNCP_RTLD_NEXT(FUNCNAME, FUNCNAME##p)
199 #define GET_REAL_FUNCP_RTLD_NEXT_CPP(FUNCNAME, FUNCTIONPOINTER) \
201 if(!FUNCTIONPOINTER) { \
203 void* funcp = dlsym(RTLD_NEXT, #FUNCNAME); \
204 if(funcp == NULL || dlerror() != NULL) { \
205 perror("dlsym failed : " #FUNCNAME); \
208 memcpy(&FUNCTIONPOINTER, &funcp, sizeof(void*)); \
213 #define GET_REAL_FUNC_RTLD_NEXT_CPP(FUNCNAME) \
214 GET_REAL_FUNCP_RTLD_NEXT_CPP(FUNCNAME, FUNCNAME##p)
216 // ======================= pre block macro ================================
218 #define PRE_PROBEBLOCK_BEGIN() \
219 if((blockresult = preBlockBegin(CALLER_ADDRESS, bfiltering, _sopt)) != 0) { \
220 setProbePoint(&probeInfo)
222 #define PRE_PROBEBLOCK_END() \
228 #define PRE_PROBEBLOCK() \
229 PRE_PROBEBLOCK_BEGIN(); \
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)
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)
243 #define APPEND_LOG_COMMON_NONE(CALLER) \
244 log.length += sprintf(log.data + log.length, "`,`,`,`,`,`,%u", \
245 (unsigned int)CALLER)
247 #define APPEND_LOG_INPUT(INPUTFORMAT, ...) \
248 log.length += sprintf(log.data + log.length, \
249 DEFAULT_TOKEN INPUTFORMAT, __VA_ARGS__)
251 #define APPEND_LOG_RESULT(RETTYPE, RETVALUE) \
252 __appendTypeLog(&log, 4, NULL, RETTYPE, RETVALUE, VT_INT, 0, \
253 VT_INT, newerrno, VT_INT, blockresult)
255 #define APPEND_LOG_CALLER() \
256 log.length += sprintf(log.data + log.length, \
257 "`,%u",(unsigned int) CALLER_ADDRESS)
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")
266 #define APPEND_LOG_CALLSTACK() APPEND_LOG_NULL_CALLSTACK()
269 #define APPEND_LOG_NULL_CALLSTACK() \
270 log.length += sprintf(log.data + log.length, \
271 "`,\ncallstack_start`,`,callstack_end")
274 // =========================== post block macro ===========================
276 #define POST_PROBEBLOCK_BEGIN(LCTYPE, RETTYPE, RETVALUE, INPUTFORMAT, ...) \
278 if(postBlockBegin(blockresult)) { \
280 APPEND_LOG_BASIC(LCTYPE); \
281 APPEND_LOG_INPUT(INPUTFORMAT, __VA_ARGS__); \
282 APPEND_LOG_RESULT(RETTYPE, RETVALUE); \
285 #define POST_PROBEBLOCK_CALLSTACK() \
287 if(newerrno != 0) { \
288 APPEND_LOG_CALLSTACK(); \
290 APPEND_LOG_NULL_CALLSTACK(); \
295 #define POST_PROBEBLOCK_END() \
296 printLog(&log, MSG_LOG); \
299 errno = (newerrno != 0) ? newerrno : olderrno
301 // ===================== unconditional probe block ========================
303 #define PRE_UNCONDITIONAL_BLOCK_BEGIN() \
306 setProbePoint(&probeInfo)
308 #define PRE_UNCONDITIONAL_BLOCK_END() \
312 #define POST_UNCONDITIONAL_BLOCK_BEGIN(LCTYPE) \
316 APPEND_LOG_BASIC(LCTYPE)
318 #define POST_UNCONDITIONAL_BLOCK_END() \
319 printLog(&log, MSG_LOG); \
323 // ========================= simplify macro ================================
325 #define BEFORE_ORIGINAL(FUNCNAME, LIBNAME) \
326 DECLARE_VARIABLE_STANDARD; \
327 GET_REAL_FUNC(FUNCNAME, LIBNAME); \
330 #define BEFORE_ORIGINAL_NOFILTER(FUNCNAME, LIBNAME) \
331 DECLARE_VARIABLE_STANDARD; \
332 GET_REAL_FUNC(FUNCNAME, LIBNAME); \
333 bfiltering = false; \