modify detail option (to print supplementary log)
[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 (!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             read_len = read (fd, &evinfo.req, sizeof(EvlogRequest));
212             GOTO_IF_FAIL (read_len == sizeof(EvlogRequest), print_done);
213             total += read_len;
214
215             evinfo.req.ptr = malloc (evinfo.req.length * 4);
216             GOTO_IF_FAIL (evinfo.req.ptr != NULL, print_done);
217
218             read_len = read (fd, evinfo.req.ptr, (evinfo.req.length * 4));
219             GOTO_IF_FAIL (read_len == (evinfo.req.length * 4), print_done);
220             total += read_len;
221         }
222
223         if (evinfo.mask & EVLOG_MASK_EVENT)
224         {
225             read_len = read (fd, &evinfo.evt, sizeof(EvlogEvent));
226             GOTO_IF_FAIL (read_len == sizeof(EvlogEvent), print_done);
227             total += read_len;
228
229             evinfo.evt.ptr = malloc (evinfo.evt.size);
230             GOTO_IF_FAIL (evinfo.evt.ptr != NULL, print_done);
231
232             WARNING_IF_FAIL (evinfo.evt.size > 0);
233
234             read_len = read (fd, evinfo.evt.ptr, evinfo.evt.size);
235             GOTO_IF_FAIL (read_len == evinfo.evt.size, print_done);
236             total += read_len;
237         }
238
239         if (evinfo.mask & EVLOG_MASK_REPLY)
240         {
241             read_len = read (fd, &evinfo.rep, sizeof(EvlogReply));
242             GOTO_IF_FAIL (read_len == sizeof(EvlogReply), print_done);
243             total += read_len;
244
245             evinfo.rep.ptr = malloc (evinfo.rep.size);
246             GOTO_IF_FAIL (evinfo.rep.ptr != NULL, print_done);
247
248             WARNING_IF_FAIL (evinfo.rep.size > 0);
249
250             read_len = read (fd, evinfo.rep.ptr, evinfo.rep.size);
251             GOTO_IF_FAIL (read_len == evinfo.rep.size, print_done);
252             total += read_len;
253         }
254
255         if (evinfo.mask & EVLOG_MASK_ERROR)
256         {
257             read_len = read (fd, &evinfo.err, sizeof(EvlogError));
258             GOTO_IF_FAIL (read_len == sizeof(EvlogError), print_done);
259             total += read_len;
260         }
261
262         if (evinfo.mask & EVLOG_MASK_ATOM)
263         {
264             EvlogAtomTable *table;
265
266             read_len = read (fd, &evinfo.evatom.size, sizeof (int));
267             GOTO_IF_FAIL (read_len == sizeof(int), print_done);
268             total += read_len;
269
270             for (i = 0 ; i < evinfo.evatom.size ; i++)
271             {
272                 table = malloc (sizeof(EvlogAtomTable));
273                 GOTO_IF_FAIL (table != NULL, print_done);
274
275                 if (!evinfo.evatom.init)
276                 {
277                     xorg_list_init(&evinfo.evatom.list);
278                     evinfo.evatom.init = 1;
279                 }
280                 read_len = read (fd, table, sizeof (EvlogAtomTable));
281                 GOTO_IF_FAIL (read_len == sizeof(EvlogAtomTable), print_done);
282                 total += read_len;
283
284                 xorg_list_add(&table->link, &evinfo.evatom.list);
285             }
286         }
287
288         if (evinfo.mask & EVLOG_MASK_REGION)
289         {
290             EvlogRegionTable *table;
291
292             read_len = read (fd, &evinfo.evregion.size, sizeof (int));
293             GOTO_IF_FAIL (read_len == sizeof(int), print_done);
294             total += read_len;
295
296             for (i = 0 ; i < evinfo.evregion.size ; i++)
297             {
298                 table = malloc (sizeof(EvlogRegionTable));
299                 GOTO_IF_FAIL (table != NULL, print_done);
300
301                 if (!evinfo.evregion.init)
302                 {
303                     xorg_list_init(&evinfo.evregion.list);
304                     evinfo.evregion.init = 1;
305                 }
306
307                 read_len = read (fd, table, sizeof (EvlogRegionTable));
308                 GOTO_IF_FAIL (read_len == sizeof(EvlogRegionTable), print_done);
309                 total += read_len;
310
311                 xorg_list_add(&table->link, &evinfo.evregion.list);
312             }
313         }
314
315         GOTO_IF_FAIL (evlog_len == total, print_done);
316
317         if (xDbgEvlogRuleValidate (&evinfo))
318         {
319             if (xDbgEvlogFillLog(&evinfo, eo->detail_level, log, &size))
320                 printf ("%s", log);
321         }
322
323         if (evinfo.req.ptr)
324         {
325             free (evinfo.req.ptr);
326             evinfo.req.ptr = NULL;
327         }
328
329         if (evinfo.evt.ptr)
330         {
331             free (evinfo.evt.ptr);
332             evinfo.evt.ptr = NULL;
333         }
334
335         xDbgDistroyAtomList(&evinfo);
336         xDbgDistroyRegionList(&evinfo);
337     }
338
339
340 print_done:
341     if (evinfo.req.ptr)
342         free (evinfo.req.ptr);
343
344     if (evinfo.evt.ptr)
345         free (evinfo.evt.ptr);
346
347     xDbgDistroyAtomList(&evinfo);
348     xDbgDistroyRegionList(&evinfo);
349
350     if (cfd >= 0)
351         close (cfd);
352
353     if (fd >= 0)
354         close (fd);
355 }
356
357
358 static void
359 _checkOption(int argc, char** argv)
360 {
361     int c;
362     int opt_str_len = 0;
363     char* opt_str = NULL;
364     EvlogOption eo = {0,};
365     char rule_log[LOG_SIZE];
366     int rule_size = sizeof (rule_log);
367
368     eo.pid = atoi (argv[0]);
369     eo.isRule = FALSE;
370     eo.detail_level = 0;
371     strncpy(eo.command_name, argv[1], PATH_MAX);
372
373     if (argc < 3)
374     {
375         _printUsage( eo.command_name );
376         return;
377     }
378
379     while ((c = getopt(argc, argv, "f:a:n:r:d:h")) != EOF)
380     {
381         switch (c)
382         {
383             case 'f':
384                 {
385                     opt_str = optarg;
386                     opt_str_len = strlen(opt_str);
387
388                     if(opt_str_len > 0)
389                     {
390                         strncpy (eo.path_name, opt_str, PATH_MAX);
391                     }
392                     break;
393                 }
394
395             case 'a':
396                 {
397                     opt_str = optarg;
398                     opt_str_len = strlen(opt_str);
399                     if(opt_str_len > 0)
400                     {
401                         int new_argc = 3;
402                         char* new_argv[3] = {"add", "allow", };
403
404                         new_argv[2] = (char*)malloc (opt_str_len + 1);
405                         if(!new_argv[2])
406                         {
407                             printf ("failed: malloc new_argv[2]\n");
408                             return;
409                         }
410
411                         strncpy (new_argv[2], opt_str , opt_str_len);
412                         if(!xDbgEvlogRuleSet ((const int) new_argc,
413                                               (const char**) new_argv,
414                                                rule_log, &rule_size))
415                         {
416                             printf("%s\n", rule_log);
417                             return;
418                         }
419                         eo.isRule = TRUE;
420
421                         free (new_argv[2]);
422                     }
423
424                     break;
425                }
426
427             case 'n':
428                 {
429                     opt_str = optarg;
430                     opt_str_len = strlen(opt_str);
431
432                     if(opt_str_len > 0)
433                     {
434                         int new_argc = 3;
435                         char* new_argv[3] = {"add", "deny", };
436
437                         new_argv[2] = (char*)malloc (opt_str_len + 1);
438                         if(!new_argv[2])
439                         {
440                             printf ("failed: malloc new_argv[2]\n");
441                             return;
442                         }
443
444                         strncpy (new_argv[2], opt_str , opt_str_len);
445                         if(!xDbgEvlogRuleSet ((const int) new_argc,
446                                               (const char**) new_argv,
447                                                rule_log, &rule_size))
448                         {
449                             printf("%s\n", rule_log);
450                             return;
451                         }
452                         eo.isRule = TRUE;
453
454                         free (new_argv[2]);
455                     }
456
457                     break;
458                 }
459
460             case 'r':
461                 {
462                     opt_str = optarg;
463                     opt_str_len = strlen(opt_str);
464
465                     if(opt_str_len > 0)
466                     {
467                         int   fd = -1;
468                         char  fs[8096];
469                         char *pfs;
470                         int   len;
471
472                         fd = open (opt_str, O_RDONLY);
473                         if (fd < 0)
474                         {
475                             printf ("failed: open '%s'. (%s)\n", opt_str, strerror(errno));
476                             return;
477                         }
478
479                         len = read(fd, fs, sizeof(fs));
480                         pfs = fs;
481
482                         while (pfs - fs < len)
483                         {
484                             int   new_argc = 3;
485                             char *new_argv[3] = {"add", };
486                             char  policy[64] = {0, };
487                             char  rule[1024] = {0, };
488                             int   i;
489
490                             if (pfs[0] == ' ' || pfs[0] == '\n')
491                             {
492                                 pfs++;
493                                 continue;
494                             }
495                             for (i = 0 ; pfs[i] != ' ' ; i++)
496                                 policy[i] = pfs[i];
497
498                             new_argv[1] = policy;
499                             pfs += (strlen(new_argv[1]) + 1);
500
501                             memset(rule, 0, sizeof(rule));
502                             for (i = 0 ; pfs[i] != '\n' ; i++)
503                                 rule[i] = pfs[i];
504
505                             new_argv[2] = rule;
506
507                             pfs += (strlen(new_argv[2]) + 1);
508
509
510                             if(!xDbgEvlogRuleSet ((const int) new_argc,
511                                                   (const char**) new_argv,
512                                                    rule_log, &rule_size))
513                             {
514                                 printf("%s\n", rule_log);
515                                 return;
516                             }
517
518                         }
519
520                         eo.isRule = TRUE;
521
522                         if (fd >= 0)
523                             close (fd);
524                     }
525                     break;
526                 }
527
528             case 'd':
529                 {
530                     opt_str = optarg;
531                     opt_str_len = strlen(opt_str);
532
533                     if(opt_str_len > 0)
534                     {
535                         eo.detail_level = (atoi(optarg));
536                         printf ("Detail Level: %d\n", eo.detail_level);
537                     }
538                     break;
539                 }
540
541             case 'h':
542             case '?':
543                 {
544                     _printUsage( eo.command_name );
545                     return;
546                     break;
547                 }
548
549             default:
550                 break;
551         }
552     }
553
554     _xEvlogAnalyzePrint(&eo, rule_log, &rule_size);
555 }
556
557
558
559 int main(int argc, char** argv)
560 {
561     char **new_argv;
562     int new_argc, i;
563     char temp[128];
564
565     new_argc = argc + 1;
566     new_argv = (char**)malloc (new_argc * sizeof (char*));
567     if (!new_argv)
568     {
569         printf ("failed: malloc new argv\n");
570         exit (-1);
571     }
572
573     snprintf (temp, sizeof(temp), "%d", (int)getpid());
574     new_argv[0] = temp;
575
576     for (i = 0; i < argc; i++)
577         new_argv[i+1] = argv[i];
578
579     _checkOption(new_argc, new_argv);
580
581     free (new_argv);
582
583     return 0;
584 }