[FIX] pack_string: correct null string handling
[platform/core/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 // getpid/gettid
46 #include <sys/types.h>
47 #include <unistd.h>
48 #include <sys/syscall.h>
49
50 #include <sys/time.h>
51
52 #include <sys/socket.h>
53 #include "dahelper.h"
54 #include "api_id_mapping.h"
55
56 #define MSG_PROBE_MEMORY 0x0101
57 #define MSG_PROBE_UICONTROL 0x0102
58 #define MSG_PROBE_UIEVENT 0x0103
59 #define MSG_PROBE_RESOURCE 0x0104
60 #define MSG_PROBE_LIFECYCLE 0x0105
61 #define MSG_PROBE_SCREENSHOT 0x0106
62 #define MSG_PROBE_SCENE 0x0107
63 #define MSG_PROBE_THREAD 0x0108
64 #define MSG_PROBE_CUSTOM 0x0109
65 #define MSG_PROBE_SYNC 0x0110
66 #define MSG_PROBE_NETWORK 0x0111
67 #define MSG_PROBE_GL 0x0112
68
69 // TODO: remove this copy-paste
70 #define CALLER_ADDRESS                                                  \
71         ((void*) __builtin_extract_return_addr(__builtin_return_address(0)))
72
73 static inline uint64_t voidp_to_uint64(const void *p)
74 {
75         return (uint64_t)(uintptr_t)p;
76 }
77
78 // COMMON
79 static inline char *pack_int32(char *to, uint32_t val)
80 {
81         *(uint32_t *)to = val;
82         return to + sizeof(uint32_t);
83 }
84
85 static inline char *pack_int64(char *to, uint64_t val)
86 {
87         *(uint64_t *)to = val;
88         return to + sizeof(uint64_t);
89 }
90
91 static char __attribute__((used)) *pack_string(char *to, const char *str)
92 {
93         if (!str) {
94                 *to = '\0';
95                 return to + 1;
96         } else {
97                 size_t len = strlen(str) + 1;
98                 strncpy(to, str, len);
99                 return to + len;
100         }
101 }
102
103 static char __attribute__((used)) *pack_bin(char *to, const char *from,
104                                             uint32_t len)
105 {
106         memcpy(to, from, len);
107         return to + len;
108 }
109
110 static inline char *pack_double(char *to, double val)
111 {
112         *(double *)to = val;
113         return to + sizeof(double);
114 }
115
116 static inline char *pack_timestamp(char *to)
117 {
118         struct timeval tv;
119
120         gettimeofday(&tv, NULL);
121         to = pack_int32(to, tv.tv_sec);
122         to = pack_int32(to, tv.tv_usec * 1000);
123
124         return to;
125 }
126
127 static char __attribute__((used)) *pack_value_by_type(char *to, const char t, va_list *args)
128 {
129         uint8_t c;
130         uint32_t d;
131         uint64_t x;
132         uint64_t p;
133         float f;
134         double w;
135         char *s;
136         int n;
137
138         *to++ = t;
139
140         switch (t) {
141         case 'c':
142                 c = (uint8_t)va_arg(*args, uint32_t);
143                 memcpy(to, &c, sizeof(c));
144                 to += sizeof(c);
145                 break;
146         case 'd':
147                 d = va_arg(*args, uint32_t);
148                 memcpy(to, &d, sizeof(d));
149                 to += sizeof(d);
150                 break;
151         case 'x':
152                 x = 0; // real value may be less then uint64_t
153                 x = (unsigned long)(uint64_t)va_arg(*args, uint64_t);
154                 memcpy(to, &x, sizeof(x));
155                 to += sizeof(x);
156                 break;
157         case 'p':
158                 p = 0; // real value may be less then uint64_t
159                 p = (unsigned long)(uintptr_t)va_arg(*args, uint64_t);
160                 memcpy(to, &p, sizeof(p));
161                 to += sizeof(p);
162                 break;
163         case 'f':
164                 f = (float)va_arg(*args, double);
165                 memcpy(to, &f, sizeof(f));
166                 to += sizeof(f);
167                 break;
168         case 'w':
169                 w = va_arg(*args, double);
170                 memcpy(to, &w, sizeof(w));
171                 to += sizeof(w);
172                 break;
173         case 's':
174                 s = va_arg(*args, char *);
175                 n = strlen(s) + 1;
176                 strncpy(to, s, n);
177                 to += n;
178                 break;
179         case 'v':
180         case 'n':
181                 break;
182         default:
183                 to--;
184                 break;
185         }
186
187         return to;
188 }
189
190 static char __attribute__((used)) *pack_args(char *to, const char *fmt, ...)
191 {
192         va_list args;
193         uint32_t num = strlen(fmt);
194         const char *t = fmt;
195
196         if(*t == '\0') {
197                 num = 0;
198         }
199
200         memcpy(to, &num, sizeof(num));
201         to += sizeof(num);
202
203         va_start(args, fmt);
204
205         for (t = fmt; *t != '\0'; t++)
206                 to = pack_value_by_type(to, *t, &args);
207
208         va_end(args);
209
210         return to;
211 }
212
213 static char __attribute__((used)) *pack_ret(char *to, char ret_type, ...)
214 {
215         va_list args;
216
217         va_start(args, ret_type);
218         to = pack_value_by_type(to, ret_type, &args);
219         va_end(args);
220
221         return to;
222 }
223
224 #define BUF_PTR p
225 #define RET_PTR ret_p
226 #define PACK_INT32(val)                         \
227         BUF_PTR = pack_int32(BUF_PTR, val);
228 #define PACK_INT64(val)                         \
229         BUF_PTR = pack_int64(BUF_PTR, val);
230 #define PACK_STRING(str)                        \
231         BUF_PTR = pack_string(BUF_PTR, str);
232
233 #define PACK_COMMON_BEGIN(msg_id, api_id, fmt, ...)             \
234         do {                                                    \
235                 BUF_PTR = pack_int32(BUF_PTR, msg_id);          \
236                 BUF_PTR = pack_int32(BUF_PTR, 0);               \
237                 BUF_PTR = pack_timestamp(BUF_PTR);              \
238                 BUF_PTR = pack_int32(BUF_PTR, 0);               \
239                 BUF_PTR = pack_int32(BUF_PTR, api_id);          \
240                 BUF_PTR = pack_int32(BUF_PTR, getpid());                \
241                 BUF_PTR = pack_int32(BUF_PTR, syscall(__NR_gettid));    \
242                 BUF_PTR = pack_args(BUF_PTR, fmt, __VA_ARGS__); \
243                 RET_PTR = BUF_PTR;              \
244         } while (0)
245
246 #define PACK_COMMON_END(ret_type, ret, errn, intern_call)                       \
247         do {                                                                    \
248                 BUF_PTR = pack_ret(BUF_PTR, ret_type, (uintptr_t)ret);          \
249                 BUF_PTR = pack_int64(BUF_PTR, (uint64_t)errn);                  \
250                 BUF_PTR = pack_int32(BUF_PTR, (uint32_t)intern_call);           \
251                 BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)CALLER_ADDRESS);       \
252                 BUF_PTR = pack_int32(BUF_PTR, 0);                               \
253                 BUF_PTR = pack_int32(BUF_PTR, 0);                               \
254         } while (0)
255
256 #define PACK_RETURN_END(ret_type, ret)                                          \
257                 RET_PTR = pack_ret(RET_PTR, ret_type, (uintptr_t)ret);
258
259 #define PACK_MEMORY(size, memory_api_type, addr)                \
260         do {                                                    \
261                 BUF_PTR = pack_int64(BUF_PTR, size);                    \
262                 BUF_PTR = pack_int32(BUF_PTR, memory_api_type); \
263                 BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)addr); \
264         } while (0)
265
266 #define PACK_UICONTROL(control)                                         \
267         do {                                                            \
268                 if (unlikely(control == NULL)) {                        \
269                         BUF_PTR = pack_string(BUF_PTR, "");             \
270                         BUF_PTR = pack_string(BUF_PTR, "");             \
271                         BUF_PTR = pack_int64(BUF_PTR, 0);               \
272                 } else {                                                \
273                         char *type = NULL, *name = NULL;                \
274                         if (find_uiobject_hash((void*)(control),        \
275                                              &type, &name) == 1) {      \
276                                 BUF_PTR = pack_string(BUF_PTR, type);   \
277                                 BUF_PTR = pack_string(BUF_PTR, name);   \
278                         } else {                                        \
279                                 BUF_PTR = pack_string(BUF_PTR, "");     \
280                                 BUF_PTR = pack_string(BUF_PTR, "");     \
281                         }                                               \
282                         BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)(control)); \
283                 }                                                       \
284         } while(0)
285
286 #define PACK_UIEVENT(event_type, detail_type, x, y, info1, info2)       \
287         do {                                                            \
288                 BUF_PTR = pack_int32(BUF_PTR, event_type);              \
289                 BUF_PTR = pack_int32(BUF_PTR, detail_type);             \
290                 BUF_PTR = pack_int32(BUF_PTR, x);                       \
291                 BUF_PTR = pack_int32(BUF_PTR, y);                       \
292                 BUF_PTR = pack_string(BUF_PTR, info1);                  \
293                 BUF_PTR = pack_int32(BUF_PTR, info2);                   \
294         } while (0)
295
296 #define PACK_RESOURCE(size, fd_value, fd_api_type, file_size,   \
297                       file_path)                                        \
298         do {                                                            \
299                 BUF_PTR = pack_int64(BUF_PTR, size);                    \
300                 BUF_PTR = pack_int64(BUF_PTR, fd_value);                \
301                 BUF_PTR = pack_int32(BUF_PTR, fd_api_type);             \
302                 BUF_PTR = pack_int64(BUF_PTR, file_size);               \
303                 BUF_PTR = pack_string(BUF_PTR, file_path);              \
304         } while (0)
305
306 #define PACK_SCREENSHOT(image_file_path, orientation)                           \
307                 do {                                                            \
308                           BUF_PTR = pack_string(BUF_PTR, image_file_path);      \
309                           BUF_PTR = pack_int32(BUF_PTR, orientation);           \
310                 } while (0)
311
312 #define PACK_SCENE(scene_name, formid, pform, panelid, ppanel, transition, user)        \
313         do {                                                                            \
314                 BUF_PTR = pack_string(BUF_PTR,  scene_name);                            \
315                 if (unlikely(pform == NULL)) {                                          \
316                         BUF_PTR = pack_string(BUF_PTR, "");                             \
317                         BUF_PTR = pack_int64(BUF_PTR, 0);                               \
318                 } else {                                                                \
319                         char *type = NULL, *name = NULL;                                \
320                         if (find_uiobject_hash((void*)(pform), &type, &name) == 1) {    \
321                                 BUF_PTR = pack_string(BUF_PTR, name);                   \
322                         } else {                                                        \
323                                 BUF_PTR = pack_string(BUF_PTR, "");                     \
324                         }                                                               \
325                         BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)pform);                \
326                 }                                                                       \
327                 if (unlikely(ppanel == NULL)) {                                         \
328                         BUF_PTR = pack_string(BUF_PTR, "");                             \
329                         BUF_PTR = pack_int64(BUF_PTR, 0);                               \
330                 } else {                                                                \
331                         char *type = NULL, *name = NULL;                                \
332                         if (find_uiobject_hash((void*)(ppanel), &type, &name) == 1) {   \
333                                 BUF_PTR = pack_string(BUF_PTR, name);                   \
334                         } else {                                                        \
335                                 BUF_PTR = pack_string(BUF_PTR, "");                     \
336                         }                                                               \
337                         BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)(ppanel));             \
338                 }                                                                       \
339                 BUF_PTR = pack_int64(BUF_PTR, transition);                              \
340                 BUF_PTR = pack_int64(BUF_PTR, user);                                    \
341         } while(0)
342
343  #define PACK_THREAD(thread_id, thread_type, api_type)                  \
344          do {                                                           \
345         if(thread_type == THREAD_PTHREAD) {                             \
346             BUF_PTR = pack_int64(BUF_PTR, thread_id);                   \
347             BUF_PTR = pack_int64(BUF_PTR, 0);                           \
348         } else if(thread_type == THREAD_TIZENTHREAD_WORKER              \
349                     || thread_type == THREAD_TIZENTHREAD_EVENTDRIVEN) {   \
350             BUF_PTR = pack_int64(BUF_PTR, 0);                           \
351             BUF_PTR = pack_int64(BUF_PTR, thread_id);                   \
352         } else {                                                        \
353             BUF_PTR = pack_int64(BUF_PTR, 0);                           \
354             BUF_PTR = pack_int64(BUF_PTR, 0);                           \
355         }                                                               \
356         BUF_PTR = pack_int32(BUF_PTR, thread_type);                     \
357         BUF_PTR = pack_int32(BUF_PTR, api_type);                        \
358         } while (0)
359
360 #define PACK_CUSTOM(handle, type, name, color, value)           \
361         do {                                                    \
362                 BUF_PTR = pack_int32(BUF_PTR, handle);          \
363                 BUF_PTR = pack_int32(BUF_PTR, type);            \
364                 BUF_PTR = pack_string(BUF_PTR, name);           \
365                 BUF_PTR = pack_int32(BUF_PTR, color);           \
366                 BUF_PTR = pack_double(BUF_PTR, value);          \
367         } while (0)
368
369 #define PACK_SYNC(sync_val, sync_type, api_type)                     \
370         do {                                                         \
371                 BUF_PTR = pack_int64(BUF_PTR, (uintptr_t)sync_val);  \
372                 BUF_PTR = pack_int32(BUF_PTR, sync_type);            \
373                 BUF_PTR = pack_int32(BUF_PTR, api_type);             \
374         } while (0)
375
376 #define LOCAL_BUF_SIZE 2048
377
378 #define PREPARE_LOCAL_BUF()                     \
379                 char msg_buf[LOCAL_BUF_SIZE];\
380                 char *BUF_PTR = msg_buf;                        \
381                 char *RET_PTR = NULL
382
383 #define MSG_LEN_OFFSET 16
384 #define MSG_HDR_LEN 20
385 #define FLUSH_LOCAL_BUF()                                               \
386                 *(uint32_t *)(msg_buf + MSG_LEN_OFFSET) = (p - msg_buf) - MSG_HDR_LEN; \
387                 send(gTraceInfo.socket.daemonSock, msg_buf, (p - msg_buf), 0)
388
389 // =========================== post block macro ===========================
390
391 #define POST_PACK_PROBEBLOCK_BEGIN()                                    \
392         newerrno = errno;                                               \
393         if(postBlockBegin(blockresult)) {
394
395 #define POST_PACK_PROBEBLOCK_END()                                      \
396                 postBlockEnd();                                         \
397         }                                                               \
398         errno = (newerrno != 0) ? newerrno : olderrno
399
400 /* int main(int argc, char **argv) */
401 /* { */
402 /*      char buf[1024]; */
403 /*      char *p = buf; */
404
405 /*      p = PACK_COMMON_BEGIN(p, 42, "cdxpfws", 'a', 10, (uint64_t)80, */
406 /*                            (uint64_t)0, 0.19, 0.33, "hello!"); */
407 /*      p = PACK_COMMON_END('p', p, 0); */
408
409 /*      int fd = creat("out.bin", 0644); */
410 /*      if (fd == -1) { */
411 /*              printf("error\n"); */
412 /*              exit(1); */
413 /*      } */
414
415 /*      write(fd, buf, p - buf); */
416 /*      close(fd); */
417
418 /*      return 0; */
419 /* } */
420
421 #endif /* __BIN_PROTO_H__ */