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