tizen 2.4 release
[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] : & / && / | / || / = / == / != / > / >= / < / <=\n");
89     printf("              [VALUE] : string / number  \n");
90     printf("\n");
91     printf("           ie)\n");
92     printf("               xevlog_analyze -a \"(type=request) && (major == X11 && (minor = SendEvent || 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 || !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         char err_buf[256] = {0,};
127         char *errp;
128
129         errp = (char *)strerror_r (errno, err_buf, sizeof(err_buf));
130         printf ("failed: open '%s'. (%s)\n", eo->path_name, errp);
131         return;
132     }
133
134     snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", eo->pid);
135     cfd = open (fd_name, O_RDWR);
136
137     if (cfd < 0)
138     {
139         char err_buf[256] = {0,};
140         char *errp;
141
142         errp = (char *)strerror_r (errno, err_buf, sizeof(err_buf));
143         printf ("failed: open consol '%s'. (%s)\n", fd_name, errp);
144         goto print_done;
145     }
146
147     while ((read_len = read (fd, &evlog_len, sizeof (int))) == sizeof (int))
148     {
149         char log[LOG_SIZE];
150         int size = sizeof (log);
151         static int init = 0;
152
153         memset (&evinfo, 0, sizeof (EvlogInfo));
154         total = read_len;
155
156         if (!init)
157         {
158             extern ExtensionInfo Evlog_extensions[];
159             extern int Extensions_size;
160             int new_argc = 3;
161             char* new_argv[3] = {"add", "allow", "all"};
162             int i;
163
164             if(!eo->isRule)
165                 xDbgEvlogRuleSet ((const int) new_argc, (const char**) new_argv, reply, len);
166
167             printf("%s\n", reply);
168
169             read_len = read (fd, &Extensions_size, sizeof (int));
170             GOTO_IF_FAIL (read_len == sizeof (int), print_done);
171             GOTO_IF_FAIL (Extensions_size > 0, print_done);
172             total += read_len;
173
174             for (i = 0 ; i < Extensions_size ; i++)
175             {
176                 read_len = read (fd, &Evlog_extensions[i].opcode, sizeof (int));
177                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
178                 total += read_len;
179
180                 read_len = read (fd, &Evlog_extensions[i].evt_base, sizeof (int));
181                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
182                 total += read_len;
183
184                 read_len = read (fd, &Evlog_extensions[i].err_base, sizeof (int));
185                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
186                 total += read_len;
187             }
188
189             if (!xDbgEvlogGetExtensionEntry ())
190             {
191                 printf ("failed: get extentions\n");
192                 goto print_done;
193             }
194
195             init = 1;
196         }
197
198         read_len = read (fd, &evinfo.time, sizeof (CARD32));
199         GOTO_IF_FAIL (read_len == sizeof (CARD32), print_done);
200         total += read_len;
201
202         read_len = read (fd, &evinfo.type, sizeof (EvlogType));
203         GOTO_IF_FAIL (read_len == sizeof (EvlogType), print_done);
204         GOTO_IF_FAIL (evinfo.type >= EVENT && evinfo.type <= ERROR, print_done);
205         total += read_len;
206
207         read_len = read (fd, &evinfo.mask, sizeof (int));
208         GOTO_IF_FAIL (read_len == sizeof (int), print_done);
209         total += read_len;
210
211         if (evinfo.mask & EVLOG_MASK_CLIENT)
212         {
213             read_len = read (fd, &evinfo.client, sizeof (EvlogClient));
214             GOTO_IF_FAIL (read_len == sizeof (EvlogClient), print_done);
215             total += read_len;
216         }
217
218         if (evinfo.mask & EVLOG_MASK_REQUEST)
219         {
220             int size;
221
222             read_len = read (fd, &evinfo.req, sizeof(EvlogRequest));
223             GOTO_IF_FAIL (read_len == sizeof(EvlogRequest), print_done);
224             total += read_len;
225
226             size = (int)(evinfo.req.length * 4);
227             GOTO_IF_FAIL (size > 0, print_done);
228
229             evinfo.req.ptr = malloc (size);
230             GOTO_IF_FAIL (evinfo.req.ptr != NULL, print_done);
231
232             read_len = read (fd, evinfo.req.ptr, size);
233             GOTO_IF_FAIL (read_len == size, print_done);
234             total += read_len;
235         }
236
237         if (evinfo.mask & EVLOG_MASK_EVENT)
238         {
239             read_len = read (fd, &evinfo.evt, sizeof(EvlogEvent));
240             GOTO_IF_FAIL (read_len == sizeof(EvlogEvent), print_done);
241             total += read_len;
242
243             evinfo.evt.ptr = malloc (evinfo.evt.size);
244             GOTO_IF_FAIL (evinfo.evt.ptr != NULL, print_done);
245
246             WARNING_IF_FAIL (evinfo.evt.size > 0);
247
248             read_len = read (fd, evinfo.evt.ptr, evinfo.evt.size);
249             GOTO_IF_FAIL (read_len == evinfo.evt.size, print_done);
250             total += read_len;
251         }
252
253         if (evinfo.mask & EVLOG_MASK_REPLY)
254         {
255             read_len = read (fd, &evinfo.rep, sizeof(EvlogReply));
256             GOTO_IF_FAIL (read_len == sizeof(EvlogReply), print_done);
257             total += read_len;
258
259             evinfo.rep.ptr = malloc (evinfo.rep.size);
260             GOTO_IF_FAIL (evinfo.rep.ptr != NULL, print_done);
261
262             WARNING_IF_FAIL (evinfo.rep.size > 0);
263
264             read_len = read (fd, evinfo.rep.ptr, evinfo.rep.size);
265             GOTO_IF_FAIL (read_len == evinfo.rep.size, print_done);
266             total += read_len;
267         }
268
269         if (evinfo.mask & EVLOG_MASK_ERROR)
270         {
271             read_len = read (fd, &evinfo.err, sizeof(EvlogError));
272             GOTO_IF_FAIL (read_len == sizeof(EvlogError), print_done);
273             total += read_len;
274         }
275
276         if (evinfo.mask & EVLOG_MASK_ATOM)
277         {
278             EvlogAtomTable *table;
279
280             read_len = read (fd, &evinfo.evatom.size, sizeof (int));
281             GOTO_IF_FAIL (read_len == sizeof(int), print_done);
282             total += read_len;
283
284             for (i = 0 ; i < evinfo.evatom.size ; i++)
285             {
286                 table = malloc (sizeof(EvlogAtomTable));
287                 GOTO_IF_FAIL (table != NULL, print_done);
288
289                 if (!evinfo.evatom.init)
290                 {
291                     xorg_list_init(&evinfo.evatom.list);
292                     evinfo.evatom.init = 1;
293                 }
294
295                 read_len = read (fd, table, sizeof (EvlogAtomTable));
296                 if (read_len != sizeof(EvlogAtomTable))
297                 {
298                     WARNING_IF_FAIL (read_len == sizeof(EvlogAtomTable));
299                     free (table);
300                     goto print_done;
301                 }
302                 total += read_len;
303
304                 xorg_list_add(&table->link, &evinfo.evatom.list);
305             }
306         }
307
308         if (evinfo.mask & EVLOG_MASK_REGION)
309         {
310             EvlogRegionTable *table;
311
312             read_len = read (fd, &evinfo.evregion.size, sizeof (int));
313             GOTO_IF_FAIL (read_len == sizeof(int), print_done);
314             total += read_len;
315
316             for (i = 0 ; i < evinfo.evregion.size ; i++)
317             {
318                 table = malloc (sizeof(EvlogRegionTable));
319                 GOTO_IF_FAIL (table != NULL, print_done);
320
321                 if (!evinfo.evregion.init)
322                 {
323                     xorg_list_init(&evinfo.evregion.list);
324                     evinfo.evregion.init = 1;
325                 }
326
327                 read_len = read (fd, table, sizeof (EvlogRegionTable));
328                 if (read_len != sizeof(EvlogRegionTable))
329                 {
330                     WARNING_IF_FAIL (read_len == sizeof(EvlogRegionTable));
331                     free (table);
332                     goto print_done;
333                 }
334                 total += read_len;
335
336                 xorg_list_add(&table->link, &evinfo.evregion.list);
337             }
338         }
339
340         GOTO_IF_FAIL (evlog_len == total, print_done);
341
342         if (xDbgEvlogRuleValidate (&evinfo))
343         {
344             if (xDbgEvlogFillLog(&evinfo, eo->detail_level, log, &size))
345                 printf ("%s", log);
346         }
347
348         if (evinfo.req.ptr)
349         {
350             free (evinfo.req.ptr);
351             evinfo.req.ptr = NULL;
352         }
353
354         if (evinfo.evt.ptr)
355         {
356             free (evinfo.evt.ptr);
357             evinfo.evt.ptr = NULL;
358         }
359
360         xDbgDistroyAtomList(&evinfo);
361         xDbgDistroyRegionList(&evinfo);
362     }
363
364
365 print_done:
366     if (evinfo.req.ptr)
367         free (evinfo.req.ptr);
368
369     if (evinfo.evt.ptr)
370         free (evinfo.evt.ptr);
371
372     xDbgDistroyAtomList(&evinfo);
373     xDbgDistroyRegionList(&evinfo);
374
375     if (cfd >= 0)
376         close (cfd);
377
378     if (fd >= 0)
379         close (fd);
380 }
381
382
383 static void
384 _checkOption(int argc, char** argv)
385 {
386     int c;
387     EvlogOption eo = {0,};
388     char rule_log[LOG_SIZE];
389     int rule_size = sizeof (rule_log);
390
391     eo.pid = atoi (argv[0]);
392     eo.isRule = FALSE;
393     eo.detail_level = 0;
394     snprintf (eo.command_name, sizeof (eo.command_name), "%s", argv[1]);
395
396     if (argc < 3)
397     {
398         _printUsage( eo.command_name );
399         return;
400     }
401
402     while ((c = getopt(argc, argv, "f:a:n:r:d:h")) != EOF)
403     {
404         switch (c)
405         {
406             case 'f':
407                 {
408                     if (!optarg || strlen(optarg) <= 0)
409                         break;
410                     snprintf (eo.path_name, sizeof (eo.path_name), "%s", optarg);
411                     break;
412                 }
413
414             case 'a':
415                 {
416                     int new_argc = 3;
417                     char* new_argv[3] = {"add", "allow", };
418
419                     if (!optarg || strlen(optarg) <= 0)
420                         break;
421
422                     new_argv[2] = (char*)calloc (1, PATH_MAX);
423                     if(!new_argv[2])
424                     {
425                         printf ("failed: malloc new_argv[2]\n");
426                         return;
427                     }
428
429                     snprintf (new_argv[2], PATH_MAX, "%s", optarg);
430                     if(!xDbgEvlogRuleSet ((const int) new_argc,
431                                           (const char**) new_argv,
432                                            rule_log, &rule_size))
433                     {
434                         printf("%s\n", rule_log);
435                         return;
436                     }
437                     eo.isRule = TRUE;
438
439                     free (new_argv[2]);
440
441                     break;
442                }
443
444             case 'n':
445                 {
446                     int new_argc = 3;
447                     char* new_argv[3] = {"add", "deny", };
448
449                     if (!optarg || strlen(optarg) <= 0)
450                         break;
451
452                     new_argv[2] = (char*)calloc (1, PATH_MAX);
453                     if(!new_argv[2])
454                     {
455                         printf ("failed: malloc new_argv[2]\n");
456                         return;
457                     }
458
459                     snprintf (new_argv[2], PATH_MAX, "%s", optarg);
460                     if(!xDbgEvlogRuleSet ((const int) new_argc,
461                                           (const char**) new_argv,
462                                            rule_log, &rule_size))
463                     {
464                         printf("%s\n", rule_log);
465                         return;
466                     }
467                     eo.isRule = TRUE;
468
469                     free (new_argv[2]);
470
471                     break;
472                 }
473
474             case 'r':
475                 {
476                     if (!optarg || strlen(optarg) <= 0)
477                         break;
478
479                     if(!xDbgEvlogReadRuleFile(optarg, rule_log, &rule_size))
480                     {
481                         printf("%s", rule_log);
482                         return;
483                     }
484                     eo.isRule = TRUE;
485                     break;
486                 }
487
488             case 'd':
489                 {
490                     if (!optarg || strlen(optarg) <= 0 || strlen(optarg) > 2)
491                         break;
492
493                     eo.detail_level = atoi(optarg);
494                     printf ("Detail Level: %d\n", eo.detail_level);
495                     break;
496                 }
497
498             case 'h':
499             case '?':
500                 {
501                     _printUsage( eo.command_name );
502                     return;
503                     break;
504                 }
505
506             default:
507                 break;
508         }
509     }
510
511     _xEvlogAnalyzePrint(&eo, rule_log, &rule_size);
512 }
513
514
515
516 int main(int argc, char** argv)
517 {
518     char **new_argv;
519     int new_argc, i;
520     char temp[128];
521
522     new_argc = argc + 1;
523     new_argv = (char**)malloc (new_argc * sizeof (char*));
524     if (!new_argv)
525     {
526         printf ("failed: malloc new argv\n");
527         return 0;
528     }
529
530     snprintf (temp, sizeof(temp), "%d", (int)getpid());
531     new_argv[0] = temp;
532
533     for (i = 0; i < argc; i++)
534         new_argv[i+1] = argv[i];
535
536     _checkOption(new_argc, new_argv);
537
538     free (new_argv);
539
540     return 0;
541 }