Initialize Tizen 2.3
[adaptation/xorg/driver/xserver-xorg-module-xdbg.git] / bin / xevlog_analyze / xevlog_analyze.c
1 /**************************************************************************
2
3 xevlog-analyze
4
5 Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
6
7 Contact: Boram Park <boram1288.park@samsung.com>
8          Sangjin LEE <lsj119@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <time.h>
38 #include <sys/ipc.h>
39 #include <sys/shm.h>
40
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <sys/ioctl.h>
44 #include <fcntl.h>
45 #include <unistd.h>
46 #include <sys/mman.h>
47
48 #include <X11/Xlib.h>
49 #include <X11/Xw32defs.h>
50 #include <xdbg_types.h>
51 #include <xdbg_evlog.h>
52
53 #define LOG_SIZE 1024
54
55 typedef struct _EvlogOption
56 {
57     int    pid;
58     char   command_name[PATH_MAX+1];
59     char   path_name[PATH_MAX+1];
60     Bool   isRule;
61     int    detail_level;
62 } EvlogOption;
63
64
65 static void
66 _printUsage(char* name)
67 {
68     printf("Usage: %s [OPTION]...\n", name);
69     printf("\n");
70     printf(" Options:\n");
71     printf("       -f [File_Name]      File to save information\n");
72     printf("\n");
73     printf("       -r [Rule_File_Name] Setting Rule of certain policy read in File to find information you want\n");
74     printf("\n");
75     printf("              [How To write Rule file form]\n");
76     printf("                ------------------------\n");
77     printf("                | allow [RULE]          |\n");
78     printf("                | deny [RULE]           |\n");
79     printf("                ------------------------\n");
80     printf("           * It is possible to write multiple policies.\n");
81     printf("\n");
82     printf("       -a [ALLOW Rule]       Setting Rule of 'ALLOW' policy to find information you want\n");
83     printf("\n");
84     printf("       -n [Deny Rule]      Setting Rule of 'Deny' policy to find information you want\n");
85     printf("\n");
86     printf("              [RULE] : C Language-style boolean expression syntax. [VARIABLE] [COMPAROTOR] [VALUE]\n");
87     printf("              [VARIABLE] : type / major / minor / command / cmd / pid\n");
88     printf("              [COMPARATOR] : & / && / and / | / || / or / = / == / != / > / >= / < / <=\n");
89     printf("              [VALUE] : string / number  \n");
90     printf("\n");
91     printf("           ie)\n");
92     printf("               xevlog_analyze -a \"(type=request) && (major == X11 and (minor = SendEvent or minor = ReceiveEvent))\"\n");
93     printf("               xevlog_analyze -n cmd!=ls\n");
94     printf("\n");
95     printf("           * WARNING : If you set both -a and -n option, must set -a option first. Otherwise Logs you DO NOT want can be printed.\n");
96     printf("\n");
97     printf("       -d [0-2]            To Set printing detail log level\n");
98     printf("\n");
99     printf("               0: To Print Primary Logs (XID, Root, Atom, Region ...)\n");
100     printf("               1: To Print More Detail Logs (Time, State, Mask ...\n");
101     printf("               2: To Print Supplementary Reply Logs (Information Including Each Item)\n");
102     printf("\n");
103     printf("       -h                  Usage of xevlog_anlayze\n");
104     printf("\n");
105 }
106
107 static void _xEvlogAnalyzePrint (EvlogOption *eo, char* reply, int* len)
108 {
109     int fd = -1, cfd = -1;
110     int total, read_len;
111     int evlog_len;
112     char fd_name[256];
113     EvlogInfo evinfo={0,};
114     int i;
115
116     if (!eo->path_name || !strlen(eo->path_name))
117     {
118         printf ("failed: no evlog path\n");
119         _printUsage(eo->command_name);
120         return;
121     }
122
123     fd = open (eo->path_name, O_RDONLY);
124     if (fd < 0)
125     {
126         printf ("failed: open '%s'. (%s)\n", eo->path_name, strerror(errno));
127         return;
128     }
129
130     snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", eo->pid);
131     cfd = open (fd_name, O_RDWR);
132
133     if (cfd < 0)
134     {
135         printf ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
136         goto print_done;
137     }
138
139     while ((read_len = read (fd, &evlog_len, sizeof (int))) == sizeof (int))
140     {
141         char log[LOG_SIZE];
142         int size = sizeof (log);
143         static int init = 0;
144
145         memset (&evinfo, 0, sizeof (EvlogInfo));
146         total = read_len;
147
148         if (!init)
149         {
150             extern ExtensionInfo Evlog_extensions[];
151             extern int Extensions_size;
152             int new_argc = 3;
153             char* new_argv[3] = {"add", "allow", "all"};
154             int i;
155
156             if(!eo->isRule)
157                 xDbgEvlogRuleSet ((const int) new_argc, (const char**) new_argv, reply, len);
158
159             printf("%s\n", reply);
160
161             read_len = read (fd, &Extensions_size, sizeof (int));
162             GOTO_IF_FAIL (read_len == sizeof (int), print_done);
163             total += read_len;
164
165             for (i = 0 ; i < Extensions_size ; i++)
166             {
167                 read_len = read (fd, &Evlog_extensions[i].opcode, sizeof (int));
168                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
169                 total += read_len;
170
171                 read_len = read (fd, &Evlog_extensions[i].evt_base, sizeof (int));
172                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
173                 total += read_len;
174
175                 read_len = read (fd, &Evlog_extensions[i].err_base, sizeof (int));
176                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
177                 total += read_len;
178             }
179
180             if (!xDbgEvlogGetExtensionEntry ())
181             {
182                 printf ("failed: get extentions\n");
183                 goto print_done;
184             }
185
186             init = 1;
187         }
188
189         read_len = read (fd, &evinfo.time, sizeof (CARD32));
190         GOTO_IF_FAIL (read_len == sizeof (CARD32), print_done);
191         total += read_len;
192
193         read_len = read (fd, &evinfo.type, sizeof (EvlogType));
194         GOTO_IF_FAIL (read_len == sizeof (EvlogType), print_done);
195         GOTO_IF_FAIL (evinfo.type >= EVENT && evinfo.type <= ERROR, print_done);
196         total += read_len;
197
198         read_len = read (fd, &evinfo.mask, sizeof (int));
199         GOTO_IF_FAIL (read_len == sizeof (int), print_done);
200         total += read_len;
201
202         if (evinfo.mask & EVLOG_MASK_CLIENT)
203         {
204             read_len = read (fd, &evinfo.client, sizeof (EvlogClient));
205             GOTO_IF_FAIL (read_len == sizeof (EvlogClient), print_done);
206             total += read_len;
207         }
208
209         if (evinfo.mask & EVLOG_MASK_REQUEST)
210         {
211             int size;
212
213             read_len = read (fd, &evinfo.req, sizeof(EvlogRequest));
214             GOTO_IF_FAIL (read_len == sizeof(EvlogRequest), print_done);
215             total += read_len;
216
217             size = (int)(evinfo.req.length * 4);
218             GOTO_IF_FAIL (size > 0, print_done);
219
220             evinfo.req.ptr = malloc (size);
221             GOTO_IF_FAIL (evinfo.req.ptr != NULL, print_done);
222
223             read_len = read (fd, evinfo.req.ptr, size);
224             GOTO_IF_FAIL (read_len == size, print_done);
225             total += read_len;
226         }
227
228         if (evinfo.mask & EVLOG_MASK_EVENT)
229         {
230             read_len = read (fd, &evinfo.evt, sizeof(EvlogEvent));
231             GOTO_IF_FAIL (read_len == sizeof(EvlogEvent), print_done);
232             total += read_len;
233
234             evinfo.evt.ptr = malloc (evinfo.evt.size);
235             GOTO_IF_FAIL (evinfo.evt.ptr != NULL, print_done);
236
237             WARNING_IF_FAIL (evinfo.evt.size > 0);
238
239             read_len = read (fd, evinfo.evt.ptr, evinfo.evt.size);
240             GOTO_IF_FAIL (read_len == evinfo.evt.size, print_done);
241             total += read_len;
242         }
243
244         if (evinfo.mask & EVLOG_MASK_REPLY)
245         {
246             read_len = read (fd, &evinfo.rep, sizeof(EvlogReply));
247             GOTO_IF_FAIL (read_len == sizeof(EvlogReply), print_done);
248             total += read_len;
249
250             evinfo.rep.ptr = malloc (evinfo.rep.size);
251             GOTO_IF_FAIL (evinfo.rep.ptr != NULL, print_done);
252
253             WARNING_IF_FAIL (evinfo.rep.size > 0);
254
255             read_len = read (fd, evinfo.rep.ptr, evinfo.rep.size);
256             GOTO_IF_FAIL (read_len == evinfo.rep.size, print_done);
257             total += read_len;
258         }
259
260         if (evinfo.mask & EVLOG_MASK_ERROR)
261         {
262             read_len = read (fd, &evinfo.err, sizeof(EvlogError));
263             GOTO_IF_FAIL (read_len == sizeof(EvlogError), print_done);
264             total += read_len;
265         }
266
267         if (evinfo.mask & EVLOG_MASK_ATOM)
268         {
269             EvlogAtomTable *table;
270
271             read_len = read (fd, &evinfo.evatom.size, sizeof (int));
272             GOTO_IF_FAIL (read_len == sizeof(int), print_done);
273             total += read_len;
274
275             for (i = 0 ; i < evinfo.evatom.size ; i++)
276             {
277                 table = malloc (sizeof(EvlogAtomTable));
278                 GOTO_IF_FAIL (table != NULL, print_done);
279
280                 if (!evinfo.evatom.init)
281                 {
282                     xorg_list_init(&evinfo.evatom.list);
283                     evinfo.evatom.init = 1;
284                 }
285
286                 read_len = read (fd, table, sizeof (EvlogAtomTable));
287                 if (read_len != sizeof(EvlogAtomTable))
288                 {
289                     WARNING_IF_FAIL (read_len == sizeof(EvlogAtomTable));
290                     free (table);
291                     goto print_done;
292                 }
293                 total += read_len;
294
295                 xorg_list_add(&table->link, &evinfo.evatom.list);
296             }
297         }
298
299         if (evinfo.mask & EVLOG_MASK_REGION)
300         {
301             EvlogRegionTable *table;
302
303             read_len = read (fd, &evinfo.evregion.size, sizeof (int));
304             GOTO_IF_FAIL (read_len == sizeof(int), print_done);
305             total += read_len;
306
307             for (i = 0 ; i < evinfo.evregion.size ; i++)
308             {
309                 table = malloc (sizeof(EvlogRegionTable));
310                 GOTO_IF_FAIL (table != NULL, print_done);
311
312                 if (!evinfo.evregion.init)
313                 {
314                     xorg_list_init(&evinfo.evregion.list);
315                     evinfo.evregion.init = 1;
316                 }
317
318                 read_len = read (fd, table, sizeof (EvlogRegionTable));
319                 if (read_len != sizeof(EvlogRegionTable))
320                 {
321                     WARNING_IF_FAIL (read_len == sizeof(EvlogRegionTable));
322                     free (table);
323                     goto print_done;
324                 }
325                 total += read_len;
326
327                 xorg_list_add(&table->link, &evinfo.evregion.list);
328             }
329         }
330
331         GOTO_IF_FAIL (evlog_len == total, print_done);
332
333         if (xDbgEvlogRuleValidate (&evinfo))
334         {
335             if (xDbgEvlogFillLog(&evinfo, eo->detail_level, log, &size))
336                 printf ("%s", log);
337         }
338
339         if (evinfo.req.ptr)
340         {
341             free (evinfo.req.ptr);
342             evinfo.req.ptr = NULL;
343         }
344
345         if (evinfo.evt.ptr)
346         {
347             free (evinfo.evt.ptr);
348             evinfo.evt.ptr = NULL;
349         }
350
351         xDbgDistroyAtomList(&evinfo);
352         xDbgDistroyRegionList(&evinfo);
353     }
354
355
356 print_done:
357     if (evinfo.req.ptr)
358         free (evinfo.req.ptr);
359
360     if (evinfo.evt.ptr)
361         free (evinfo.evt.ptr);
362
363     xDbgDistroyAtomList(&evinfo);
364     xDbgDistroyRegionList(&evinfo);
365
366     if (cfd >= 0)
367         close (cfd);
368
369     if (fd >= 0)
370         close (fd);
371 }
372
373
374 static void
375 _checkOption(int argc, char** argv)
376 {
377     int c;
378     EvlogOption eo = {0,};
379     char rule_log[LOG_SIZE];
380     int rule_size = sizeof (rule_log);
381
382     eo.pid = atoi (argv[0]);
383     eo.isRule = FALSE;
384     eo.detail_level = 0;
385     snprintf (eo.command_name, sizeof (eo.command_name), "%s", argv[1]);
386
387     if (argc < 3)
388     {
389         _printUsage( eo.command_name );
390         return;
391     }
392
393     while ((c = getopt(argc, argv, "f:a:n:r:d:h")) != EOF)
394     {
395         switch (c)
396         {
397             case 'f':
398                 {
399                     if (!optarg || strlen(optarg) <= 0)
400                         break;
401                     snprintf (eo.path_name, sizeof (eo.path_name), "%s", optarg);
402                     break;
403                 }
404
405             case 'a':
406                 {
407                     int new_argc = 3;
408                     char* new_argv[3] = {"add", "allow", };
409
410                     if (!optarg || strlen(optarg) <= 0)
411                         break;
412
413                     new_argv[2] = (char*)calloc (1, PATH_MAX);
414                     if(!new_argv[2])
415                     {
416                         printf ("failed: malloc new_argv[2]\n");
417                         return;
418                     }
419
420                     snprintf (new_argv[2], PATH_MAX, "%s", optarg);
421                     if(!xDbgEvlogRuleSet ((const int) new_argc,
422                                           (const char**) new_argv,
423                                            rule_log, &rule_size))
424                     {
425                         printf("%s\n", rule_log);
426                         return;
427                     }
428                     eo.isRule = TRUE;
429
430                     free (new_argv[2]);
431
432                     break;
433                }
434
435             case 'n':
436                 {
437                     int new_argc = 3;
438                     char* new_argv[3] = {"add", "deny", };
439
440                     if (!optarg || strlen(optarg) <= 0)
441                         break;
442
443                     new_argv[2] = (char*)calloc (1, PATH_MAX);
444                     if(!new_argv[2])
445                     {
446                         printf ("failed: malloc new_argv[2]\n");
447                         return;
448                     }
449
450                     snprintf (new_argv[2], PATH_MAX, "%s", optarg);
451                     if(!xDbgEvlogRuleSet ((const int) new_argc,
452                                           (const char**) new_argv,
453                                            rule_log, &rule_size))
454                     {
455                         printf("%s\n", rule_log);
456                         return;
457                     }
458                     eo.isRule = TRUE;
459
460                     free (new_argv[2]);
461
462                     break;
463                 }
464
465             case 'r':
466                 {
467                     if (!optarg || strlen(optarg) <= 0)
468                         break;
469
470                     if(!xDbgEvlogReadRuleFile(optarg, rule_log, &rule_size))
471                     {
472                         printf("%s", rule_log);
473                         return;
474                     }
475                     eo.isRule = TRUE;
476                     break;
477                 }
478
479             case 'd':
480                 {
481                     if (!optarg || strlen(optarg) <= 0 || strlen(optarg) > 2)
482                         break;
483
484                     eo.detail_level = atoi(optarg);
485                     printf ("Detail Level: %d\n", eo.detail_level);
486                     break;
487                 }
488
489             case 'h':
490             case '?':
491                 {
492                     _printUsage( eo.command_name );
493                     return;
494                     break;
495                 }
496
497             default:
498                 break;
499         }
500     }
501
502     _xEvlogAnalyzePrint(&eo, rule_log, &rule_size);
503 }
504
505
506
507 int main(int argc, char** argv)
508 {
509     char **new_argv;
510     int new_argc, i;
511     char temp[128];
512
513     new_argc = argc + 1;
514     new_argv = (char**)malloc (new_argc * sizeof (char*));
515     if (!new_argv)
516     {
517         printf ("failed: malloc new argv\n");
518         exit (-1);
519     }
520
521     snprintf (temp, sizeof(temp), "%d", (int)getpid());
522     new_argv[0] = temp;
523
524     for (i = 0; i < argc; i++)
525         new_argv[i+1] = argv[i];
526
527     _checkOption(new_argc, new_argv);
528
529     free (new_argv);
530
531     return 0;
532 }