tizen 2.3 release
[framework/system/swap-probe.git] / include / binproto.h
1 /*
2  *  DA probe
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Nikita Kalyazin <n.kalyazin@samsung.com>
9  * Anastasia Lyupa <a.lyupa@samsung.com>
10  *
11  * This library is free software; you can redistribute it and/or modify it under
12  * the terms of the GNU Lesser General Public License as published by the
13  * Free Software Foundation; either version 2.1 of the License, or (at your option)
14  * any later version.
15  *
16  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
17  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19  * License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with this library; if not, write to the Free Software Foundation, Inc., 51
23  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24  *
25  * Contributors:
26  * - Samsung RnD Institute Russia
27  *
28  */
29
30 #ifndef __BIN_PROTO_H__
31 #define __BIN_PROTO_H__
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdint.h>
37 #include <stdarg.h>
38
39 #include <unistd.h>
40 #include <fcntl.h>
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44
45 #include <sys/time.h>
46
47 #include <sys/socket.h>
48 #include "dahelper.h"
49 #include "api_id_mapping.h"
50
51 #define MSG_PROBE_MEMORY 0x0101
52 #define MSG_PROBE_UICONTROL 0x0102
53 #define MSG_PROBE_UIEVENT 0x0103
54 #define MSG_PROBE_RESOURCE 0x0104
55 #define MSG_PROBE_LIFECYCLE 0x0105
56 #define MSG_PROBE_SCREENSHOT 0x0106
57 #define MSG_PROBE_SCENE 0x0107
58 #define MSG_PROBE_THREAD 0x0108
59 #define MSG_PROBE_CUSTOM 0x0109
60 #define MSG_PROBE_SYNC 0x0110
61 #define MSG_PROBE_NETWORK 0x0111
62 #define MSG_PROBE_GL 0x0112
63
64 #define SCREENSHOT_DIRECTORY    "/tmp/da"
65
66 #define MAX_PACK_FILENAME_LEN (4 * 1024)
67 #define MAX_SHADER_LEN (4 * 1024)
68 #define ADD_LOCAL_BUF_SIZE (1024)
69 #define MAX_GL_CONTEXT_VALUE_SIZE (1024)
70 #define MAX_LOCAL_BUF_SIZE (MAX_SHADER_LEN + ADD_LOCAL_BUF_SIZE)
71 #define LOCAL_BUF msg_buf
72
73 // TODO: remove this copy-paste
74 #define CALLER_ADDRESS                                                  \
75         ((void*) __builtin_extract_return_addr(__builtin_return_address(0)))
76
77 static inline uint64_t voidp_to_uint64(const void *p)
78 {
79         return (uint64_t)(uintptr_t)p;
80 }
81
82 // COMMON
83 static inline char *pack_int32(char *to, uint32_t val)
84 {
85         *(uint32_t *)to = val;
86         return to + sizeof(uint32_t);
87 }
88
89 static inline char *pack_int64(char *to, uint64_t val)
90 {
91         *(uint64_t *)to = val;
92         return to + sizeof(uint64_t);
93 }
94
95 static char __attribute__((used)) *pack_string(char *to, const char *str)
96 {
97         if (!str) {
98                 *to = '\0';
99                 return to + 1;
100         } else {
101                 size_t len = strlen(str) + 1;
102                 strncpy(to, str, len);
103                 return to + len;
104         }
105 }
106
107 static char __attribute__((used)) *pack_bin(char *to, const char *from,
108                                             uint32_t len)
109 {
110         memcpy(to, from, len);
111         return to + len;
112 }
113
114 static inline char *pack_double(char *to, double val)
115 {
116         *(double *)to = val;
117         return to + sizeof(double);
118 }
119
120 static inline char *pack_timestamp(char *to)
121 {
122         struct timeval tv;
123
124         gettimeofday(&tv, NULL);
125         to = pack_int32(to, tv.tv_sec);
126         to = pack_int32(to, tv.tv_usec * 1000);
127
128         return to;
129 }
130
131 ///////////////////////////////////////////////////////////////////
132 // function: pack_array
133 ///////////////////////////////////////////////////////////////////
134 // info:
135 //  Pack array param to buffer
136 // params:
137 //  char *to              - destination buffer
138 //  va_list *args         - array size and array (pointer)
139 //  uint32_t element_size - size of array element
140 // return:
141 //  char *                - destination pointer end after pack
142 static char *pack_array(char *to, va_list *args, uint32_t element_size)
143 {
144         uint32_t d;
145         uint64_t p;
146
147         // get array elements count
148         d = va_arg(*args, uint32_t);
149         // get array pointer
150         p = (unsigned long)(uintptr_t)va_arg(*args, uint64_t);
151
152         // pack original pointer
153         memcpy(to, &p, sizeof(p));
154         to += sizeof(p);
155         // pack array elements count
156         memcpy(to, &d, sizeof(d));
157         to += sizeof(d);
158
159         // pack array elements
160         element_size *= d;
161         memcpy(to, (void *)(long)p, element_size);
162         to += element_size;
163
164         return to;
165 }
166
167 static char __attribute__((used)) *pack_string_to_file(char *to, const char *st,
168                                                        uint32_t data_len,
169                                                        uint32_t max_len)
170 {
171         if (data_len < max_len) {
172                 /* pack string to buffer */
173                 to = pack_string(to, st);
174         } else {
175                 /* pack string to file */
176                 char template_name[] = SCREENSHOT_DIRECTORY "/swap_XXXXXX";
177                 char dst_path_pack[MAX_PATH_LENGTH];
178                 FILE *file;
179                 mktemp(template_name);
180                 file = fopen(template_name, "w");
181                 if (file != NULL) {
182                         fwrite(st, data_len, 1, file);
183                         fclose(file);
184                 }
185                 snprintf(dst_path_pack, sizeof(dst_path_pack), "FILE:%s", template_name);
186                 to = pack_string(to, dst_path_pack);
187         }
188         return to;
189 }
190
191 static char __attribute__((used)) *pack_value_by_type(char *to, const char **t, va_list *args)
192 {
193         uint8_t c;
194         uint8_t cs;
195         uint32_t d;
196         uint64_t x;
197         uint64_t p;
198         float f;
199         double w;
200         char *s;
201         int n;
202
203         *to++ = **t;
204
205         switch (**t) {
206         case 'b':
207         case 'c':
208                 c = (uint8_t)va_arg(*args, uint32_t);
209                 memcpy(to, &c, sizeof(c));
210                 to += sizeof(c);
211                 break;
212         case 'd':
213                 d = va_arg(*args, uint32_t);
214                 memcpy(to, &d, sizeof(d));
215                 to += sizeof(d);
216                 break;
217         case 'x':
218                 x = 0; // real value may be less then uint64_t
219                 x = (unsigned long)(uint64_t)va_arg(*args, uint64_t);
220                 memcpy(to, &x, sizeof(x));
221                 to += sizeof(x);
222                 break;
223         case 'p':
224                 p = 0; // real value may be less then uint64_t
225                 p = (unsigned long)(uintptr_t)va_arg(*args, uint64_t);
226                 memcpy(to, &p, sizeof(p));
227                 to += sizeof(p);
228                 break;
229         case 'f':
230                 f = (float)va_arg(*args, double);
231                 memcpy(to, &f, sizeof(f));
232                 to += sizeof(f);
233                 break;
234         case 'w':
235                 w = va_arg(*args, double);
236                 memcpy(to, &w, sizeof(w));
237                 to += sizeof(w);
238                 break;
239         case 's':
240                 cs = *((*t)+1);
241                 s = va_arg(*args, char *);
242
243                 switch (cs) {
244                         case '4': //"s4" - pack 4K or to file
245                                 (*t)++;
246                                 to = pack_string_to_file(to, s, strlen(s),
247                                                          MAX_PACK_FILENAME_LEN);
248                                 break;
249                         case '0': //"s0" - pack 256 bytes
250                                 (*t)++;
251                                 n = strlen(s) + 1;
252                                 if (n >= 255)
253                                         n = 255;
254                                 strncpy(to, s, n);
255                                 to[n-1] = '\0';
256                                 to += n;
257                                 break;
258                         default: //"s" - pack all string
259                                 n = strlen(s) + 1;
260                                 strncpy(to, s, n);
261                                 to += n;
262                                 break;
263                 }
264
265                 break;
266         case 'v':
267         case 'n':
268                 break;
269         /* pack arrays params */
270         case 'D':
271                 /* array of 'd' uint32_t */
272                 to = pack_array(to, args, sizeof(d));
273                 break;
274         case 'F':
275                 /* array of 'f' float */
276                 to = pack_array(to, args, sizeof(f));
277                 break;
278         case 'W':
279                 /* array of 'w' double */
280                 to = pack_array(to, args, sizeof(w));
281                 break;
282         default: {
283                 PRINTERR("ERROR PACK #%d '%c'!!!", **t, **t);
284                 to--;
285                 break;
286                 }
287         }
288
289         (*t)++;
290         return to;
291 }
292
293 static char __attribute__((used)) *pack_args(char *to, const char *fmt, ...)
294 {
295         va_list args;
296         uint32_t num = 0;
297         const char *t = fmt;
298         char *size_p = to;
299
300         //put dummy num value
301         memcpy(to, &num, sizeof(num));
302         to += sizeof(num);
303
304         va_start(args, fmt);
305
306         for (t = fmt; *t != '\0';) {
307                 to = pack_value_by_type(to, &t, &args);
308                 num++;
309         }
310
311         //set real num value
312         memcpy(size_p, &num, sizeof(num));
313
314         va_end(args);
315
316         return to;
317 }
318
319 static char __attribute__((used)) *pack_ret(char *to, char ret_type, ...)
320 {
321         va_list args;
322         char fmt[] = {ret_type, 0};
323         const char *fmtp = (const char *)fmt;
324
325         va_start(args, ret_type);
326         to = pack_value_by_type(to, &fmtp, &args);
327         va_end(args);
328
329         return to;
330 }
331
332 #define BUF_PTR p
333 #define RET_PTR ret_p
334 #define PACK_INT32(val)                         \
335         BUF_PTR = pack_int32(BUF_PTR, val);
336 #define PACK_INT64(val)                         \
337         BUF_PTR = pack_int64(BUF_PTR, val);
338 #define PACK_STRING(str)                        \
339         BUF_PTR = pack_string(BUF_PTR, str);
340
341 #define PACK_COMMON_BEGIN(msg_id, api_id, fmt, ...)             \
342         do {    /* PACK_COMMON_BEGIN*/                          \
343                 BUF_PTR = pack_int32(BUF_PTR, msg_id);          /* msg id */    \
344                 BUF_PTR = pack_int32(BUF_PTR, 0);               /* sequence */  \
345                 BUF_PTR = pack_timestamp(BUF_PTR);              /* timestamp */ \
346                 BUF_PTR = pack_int32(BUF_PTR, 0);               /* length */    \
347                 BUF_PTR = pack_int32(BUF_PTR, api_id);          /* API id */    \
348                 BUF_PTR = pack_int32(BUF_PTR, _getpid());       /* PID */       \
349                 BUF_PTR = pack_int32(BUF_PTR, _gettid());       /* call pc*/\
350                 BUF_PTR = pack_args(BUF_PTR, fmt, __VA_ARGS__); /* args */      \
351                 RET_PTR = BUF_PTR;              \
352         } while (0)
353
354 #define PACK_COMMON_END(ret_type, ret, errn, intern_call)                       \
355         do {    /* PACK_COMMON_END */                                           \
356                 BUF_PTR = pack_ret(RET_PTR, ret_type, (uintptr_t)ret); /* return val */ \
357                 BUF_PTR = pack_int64(BUF_PTR, (uint64_t)errn);  /* errno */     \
358                 BUF_PTR = pack_int32(BUF_PTR, (uint32_t)intern_call);   /* internal call*/      \
359                 BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)CALLER_ADDRESS); /*caller addr*/\
360                 BUF_PTR = pack_int32(BUF_PTR, 0);       /* reserved */          \
361                 BUF_PTR = pack_int32(BUF_PTR, 0);       /* reserved */          \
362         } while (0)
363
364 #define PACK_RETURN_END(ret_type, ret)                                          \
365                 RET_PTR = pack_ret(RET_PTR, ret_type, (uintptr_t)ret); /* return val */
366
367 #define PACK_MEMORY(size, memory_api_type, addr)                                \
368         do {    /* PACK_MEMORY */                                               \
369                 BUF_PTR = pack_int64(BUF_PTR, size);    /* alloc size */        \
370                 BUF_PTR = pack_int32(BUF_PTR, memory_api_type); /* alloc type */\
371                 BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)addr); /* alloc addr */\
372         } while (0)
373
374 #define PACK_UICONTROL(control)                                         \
375         do {                                                            \
376                 if (unlikely(control == NULL)) {                        \
377                         BUF_PTR = pack_string(BUF_PTR, "");             \
378                         BUF_PTR = pack_string(BUF_PTR, "");             \
379                         BUF_PTR = pack_int64(BUF_PTR, 0);               \
380                 } else {                                                \
381                         char *type = NULL, *name = NULL;                \
382                         if (find_uiobject_hash((void*)(control),        \
383                                              &type, &name) == 1) {      \
384                                 BUF_PTR = pack_string(BUF_PTR, type);   \
385                                 BUF_PTR = pack_string(BUF_PTR, name);   \
386                         } else {                                        \
387                                 BUF_PTR = pack_string(BUF_PTR, "");     \
388                                 BUF_PTR = pack_string(BUF_PTR, "");     \
389                         }                                               \
390                         BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)(control)); \
391                 }                                                       \
392         } while(0)
393
394 #define PACK_UIEVENT(event_type, detail_type, x, y, info1, info2)       \
395         do {    /* PACK_UIEVENT */                                      \
396                 BUF_PTR = pack_int32(BUF_PTR, event_type);              \
397                 BUF_PTR = pack_int32(BUF_PTR, detail_type);             \
398                 BUF_PTR = pack_int32(BUF_PTR, x);                       \
399                 BUF_PTR = pack_int32(BUF_PTR, y);                       \
400                 BUF_PTR = pack_string(BUF_PTR, info1);                  \
401                 BUF_PTR = pack_int32(BUF_PTR, info2);                   \
402         } while (0)
403
404 #define PACK_RESOURCE(size, fd_value, fd_api_type, file_size,   \
405                       file_path)                                        \
406         do {    /* PACK_RESOURCE */                                     \
407                 BUF_PTR = pack_int64(BUF_PTR, size);                    \
408                 BUF_PTR = pack_int64(BUF_PTR, fd_value);                \
409                 BUF_PTR = pack_int32(BUF_PTR, fd_api_type);             \
410                 BUF_PTR = pack_int64(BUF_PTR, file_size);               \
411                 BUF_PTR = pack_string_to_file(BUF_PTR, file_path,       \
412                                               strlen(file_path),        \
413                                               MAX_PACK_FILENAME_LEN);   \
414         } while (0)
415
416 #define PACK_SCREENSHOT(image_file_path, orientation)                           \
417                 do {    /* PACK_SCREENSHOT */                                   \
418                           BUF_PTR = pack_string(BUF_PTR, image_file_path);      \
419                           BUF_PTR = pack_int32(BUF_PTR, orientation);           \
420                 } while (0)
421
422 #define PACK_SCENE(scene_name, formid, pform, panelid, ppanel, transition, user)        \
423         do {                                                                            \
424                 BUF_PTR = pack_string(BUF_PTR,  scene_name);                            \
425                 if (unlikely(pform == NULL)) {                                          \
426                         BUF_PTR = pack_string(BUF_PTR, "");                             \
427                         BUF_PTR = pack_int64(BUF_PTR, 0);                               \
428                 } else {                                                                \
429                         char *type = NULL, *name = NULL;                                \
430                         if (find_uiobject_hash((void*)(pform), &type, &name) == 1) {    \
431                                 BUF_PTR = pack_string(BUF_PTR, name);                   \
432                         } else {                                                        \
433                                 BUF_PTR = pack_string(BUF_PTR, "");                     \
434                         }                                                               \
435                         BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)pform);                \
436                 }                                                                       \
437                 if (unlikely(ppanel == NULL)) {                                         \
438                         BUF_PTR = pack_string(BUF_PTR, "");                             \
439                         BUF_PTR = pack_int64(BUF_PTR, 0);                               \
440                 } else {                                                                \
441                         char *type = NULL, *name = NULL;                                \
442                         if (find_uiobject_hash((void*)(ppanel), &type, &name) == 1) {   \
443                                 BUF_PTR = pack_string(BUF_PTR, name);                   \
444                         } else {                                                        \
445                                 BUF_PTR = pack_string(BUF_PTR, "");                     \
446                         }                                                               \
447                         BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)(ppanel));             \
448                 }                                                                       \
449                 BUF_PTR = pack_int64(BUF_PTR, transition);                              \
450                 BUF_PTR = pack_int64(BUF_PTR, user);                                    \
451         } while(0)
452
453 #define PACK_THREAD(thread_id, thread_type, api_type, class_name)       \
454          do {                                                           \
455         if(thread_type == THREAD_PTHREAD) {                             \
456             BUF_PTR = pack_int64(BUF_PTR, thread_id);                   \
457             BUF_PTR = pack_int64(BUF_PTR, 0);                           \
458         } else if(thread_type == THREAD_TIZENTHREAD_WORKER              \
459                     || thread_type == THREAD_TIZENTHREAD_EVENTDRIVEN) {   \
460             BUF_PTR = pack_int64(BUF_PTR, 0);                           \
461             BUF_PTR = pack_int64(BUF_PTR, thread_id);                   \
462         } else {                                                        \
463             BUF_PTR = pack_int64(BUF_PTR, 0);                           \
464             BUF_PTR = pack_int64(BUF_PTR, 0);                           \
465         }                                                               \
466         BUF_PTR = pack_int32(BUF_PTR, thread_type);                     \
467         BUF_PTR = pack_int32(BUF_PTR, api_type);                        \
468         BUF_PTR = pack_string(BUF_PTR, class_name);                     \
469         } while (0)
470
471 #define PACK_CUSTOM(handle, type, name, color, value)           \
472         do {                                                    \
473                 BUF_PTR = pack_int32(BUF_PTR, handle);          \
474                 BUF_PTR = pack_int32(BUF_PTR, type);            \
475                 BUF_PTR = pack_string(BUF_PTR, name);           \
476                 BUF_PTR = pack_int32(BUF_PTR, color);           \
477                 BUF_PTR = pack_double(BUF_PTR, value);          \
478         } while (0)
479
480 #define PACK_SYNC(sync_val, sync_type, api_type)                     \
481         do {                                                         \
482                 BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)sync_val);  \
483                 BUF_PTR = pack_int32(BUF_PTR, sync_type);            \
484                 BUF_PTR = pack_int32(BUF_PTR, api_type);             \
485         } while (0)
486
487 /* TODO maloc/free for each event turns out expensive: think of buffer
488  * allocator implementation */
489 #define PREPARE_LOCAL_BUF()                     \
490                 char *LOCAL_BUF = (char *)(*real_malloc)(MAX_LOCAL_BUF_SIZE);   \
491                 char *BUF_PTR = LOCAL_BUF;                      \
492                 char *RET_PTR = NULL
493
494 #define PREPARE_LOCAL_BUF_THOUGH(BUFF)                          \
495                 char *LOCAL_BUF = BUFF;                         \
496                 char *BUF_PTR = LOCAL_BUF;                      \
497                 char *RET_PTR = NULL
498
499 #define MSG_LEN_OFFSET 16
500 #define MSG_HDR_LEN 20
501
502 #define SET_MSG_LEN()                                                   \
503                 *(uint32_t *)(msg_buf + MSG_LEN_OFFSET) = (p - msg_buf) - MSG_HDR_LEN;
504
505 #define GET_MSG_LEN()                                                   \
506                 (p - msg_buf) - MSG_HDR_LEN
507
508 #define FLUSH_LOCAL_BUF()                                               \
509                 SET_MSG_LEN();                                          \
510                 send(gTraceInfo.socket.daemonSock, msg_buf, (p - msg_buf), 0); \
511                 free(LOCAL_BUF);                                        \
512                 LOCAL_BUF = NULL
513
514 // =========================== post block macro ===========================
515
516 #define POST_PACK_PROBEBLOCK_BEGIN()                                    \
517         newerrno = errno;                                               \
518         if(postBlockBegin(blockresult)) {
519
520 #define POST_PACK_PROBEBLOCK_END()                                      \
521                 postBlockEnd();                                         \
522         }                                                               \
523         errno = (newerrno != 0) ? newerrno : olderrno
524
525 #define POST_PACK_PROBEBLOCK_ADD_END()                                  \
526                 preBlockEnd();                                          \
527         }                                                               \
528         errno = (newerrno != 0) ? newerrno : olderrno
529
530
531 /* int main(int argc, char **argv) */
532 /* { */
533 /*      char buf[1024]; */
534 /*      char *p = buf; */
535
536 /*      p = PACK_COMMON_BEGIN(p, 42, "cdxpfws", 'a', 10, (uint64_t)80, */
537 /*                            (uint64_t)0, 0.19, 0.33, "hello!"); */
538 /*      p = PACK_COMMON_END('p', p, 0); */
539
540 /*      int fd = creat("out.bin", 0644); */
541 /*      if (fd == -1) { */
542 /*              printf("error\n"); */
543 /*              exit(1); */
544 /*      } */
545
546 /*      write(fd, buf, p - buf); */
547 /*      close(fd); */
548
549 /*      return 0; */
550 /* } */
551
552 extern int _init_(void);
553 extern void _uninit_(void);
554
555 #endif /* __BIN_PROTO_H__ */