fc9e35fd017fd88cb26b734b8f8a3a1b62ed21a9
[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     Bool   detail;
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("       -a [Add Rule]       Setting Rule of 'Add' policy to find information you want\n");
74     printf("\n");
75     printf("       -n [Deny Rule]      Setting Rule of 'Deny' policy to find information you want\n");
76     printf("\n");
77     printf("              [RULE] : C Language-style boolean expression syntax. [VARIABLE] [COMPAROTOR] [VALUE]\n");
78     printf("              [VARIABLE] : type / major / minor / command / cmd / pid\n");
79     printf("              [COMPARATOR] : & / && / and / | / || / or / = / == / != / > / >= / < / <=\n");
80     printf("              [VALUE] : string / number  \n");
81     printf("\n");
82     printf("           ie)\n");
83     printf("               xevlog_analyze -a \"(type=request) && (major == X11 and (minor = SendEvent or minor = ReceiveEvent))\"\n");
84     printf("               xevlog_analyze -n cmd!=ls\n");
85     printf("\n");
86     printf("       -d [OFF:0/ON:1]     To Print detail log of extensions\n");
87     printf("\n");
88     printf("       -h                  Usage of xevlog_anlayze\n");
89     printf("\n");
90 }
91
92
93 static void _xEvlogAnalyzePrint (EvlogOption *eo, char* reply, int* len)
94 {
95     int fd = -1, cfd = -1;
96     int total, read_len;
97     int evlog_len;
98     char fd_name[256];
99     EvlogInfo evinfo={0,};
100     int i;
101
102     if (!strlen(eo->path_name))
103     {
104         printf ("failed: no evlog path\n");
105         return;
106     }
107
108     fd = open (eo->path_name, O_RDONLY);
109     if (fd < 0)
110     {
111         printf ("failed: open '%s'. (%s)\n", eo->path_name, strerror(errno));
112         return;
113     }
114
115     snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", eo->pid);
116     cfd = open (fd_name, O_RDWR);
117
118     if (cfd < 0)
119     {
120         printf ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
121         goto print_done;
122     }
123
124     while ((read_len = read (fd, &evlog_len, sizeof (int))) == sizeof (int))
125     {
126         char log[LOG_SIZE];
127         int size = sizeof (log);
128         static int init = 0;
129
130         memset (&evinfo, 0, sizeof (EvlogInfo));
131         total = read_len;
132
133         if (!init)
134         {
135             extern ExtensionInfo Evlog_extensions[];
136             extern int Extensions_size;
137             int new_argc = 3;
138             char* new_argv[3] = {"add", "allow", "all"};
139             int i;
140
141             if(!eo->isRule)
142                 xDbgEvlogRuleSet ((const int) new_argc, (const char**) new_argv, reply, len);
143
144             printf("%s\n", reply);
145
146             read_len = read (fd, &Extensions_size, sizeof (int));
147             GOTO_IF_FAIL (read_len == sizeof (int), print_done);
148             total += read_len;
149
150             for (i = 0 ; i < Extensions_size ; i++)
151             {
152                 read_len = read (fd, &Evlog_extensions[i].opcode, sizeof (int));
153                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
154                 total += read_len;
155
156                 read_len = read (fd, &Evlog_extensions[i].evt_base, sizeof (int));
157                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
158                 total += read_len;
159
160                 read_len = read (fd, &Evlog_extensions[i].err_base, sizeof (int));
161                 GOTO_IF_FAIL (read_len == sizeof (int), print_done);
162                 total += read_len;
163             }
164
165             if (!xDbgEvlogGetExtensionEntry ())
166             {
167                 printf ("failed: get extentions\n");
168                 goto print_done;
169             }
170
171             init = 1;
172         }
173
174         read_len = read (fd, &evinfo.time, sizeof (CARD32));
175         GOTO_IF_FAIL (read_len == sizeof (CARD32), print_done);
176         total += read_len;
177
178         read_len = read (fd, &evinfo.type, sizeof (EvlogType));
179         GOTO_IF_FAIL (read_len == sizeof (EvlogType), print_done);
180         GOTO_IF_FAIL (evinfo.type >= EVENT && evinfo.type <= FLUSH, print_done);
181         total += read_len;
182
183         read_len = read (fd, &evinfo.mask, sizeof (int));
184         GOTO_IF_FAIL (read_len == sizeof (int), print_done);
185         total += read_len;
186
187         if (evinfo.mask & EVLOG_MASK_CLIENT)
188         {
189             read_len = read (fd, &evinfo.client, sizeof (EvlogClient));
190             GOTO_IF_FAIL (read_len == sizeof (EvlogClient), print_done);
191             total += read_len;
192         }
193
194         if (evinfo.mask & EVLOG_MASK_REQUEST)
195         {
196             read_len = read (fd, &evinfo.req, sizeof(EvlogRequest));
197             GOTO_IF_FAIL (read_len == sizeof(EvlogRequest), print_done);
198             total += read_len;
199
200             evinfo.req.ptr = malloc (evinfo.req.length * 4);
201             GOTO_IF_FAIL (evinfo.req.ptr != NULL, print_done);
202
203             read_len = read (fd, evinfo.req.ptr, (evinfo.req.length * 4));
204             GOTO_IF_FAIL (read_len == (evinfo.req.length * 4), print_done);
205             total += read_len;
206         }
207
208         if (evinfo.mask & EVLOG_MASK_EVENT)
209         {
210             read_len = read (fd, &evinfo.evt, sizeof(EvlogEvent));
211             GOTO_IF_FAIL (read_len == sizeof(EvlogEvent), print_done);
212             total += read_len;
213
214             evinfo.evt.ptr = malloc (evinfo.evt.size);
215             GOTO_IF_FAIL (evinfo.evt.ptr != NULL, print_done);
216
217             WARNING_IF_FAIL (evinfo.evt.size > 0);
218
219             read_len = read (fd, evinfo.evt.ptr, evinfo.evt.size);
220             GOTO_IF_FAIL (read_len == evinfo.evt.size, print_done);
221             total += read_len;
222         }
223
224         if (evinfo.mask & EVLOG_MASK_ATOM)
225         {
226             EvlogAtomTable *table;
227
228             read_len = read (fd, &evinfo.evatom.size, sizeof (int));
229             GOTO_IF_FAIL (read_len == sizeof(int), print_done);
230             total += read_len;
231
232             for (i = 0 ; i < evinfo.evatom.size ; i++)
233             {
234                 table = malloc (sizeof(EvlogAtomTable));
235                 GOTO_IF_FAIL (table != NULL, print_done);
236
237                 if (!evinfo.evatom.init)
238                 {
239                     xorg_list_init(&evinfo.evatom.list);
240                     evinfo.evatom.init = 1;
241                 }
242                 read_len = read (fd, table, sizeof (EvlogAtomTable));
243                 GOTO_IF_FAIL (read_len == sizeof(EvlogAtomTable), print_done);
244                 total += read_len;
245
246                 xorg_list_add(&table->link, &evinfo.evatom.list);
247             }
248         }
249
250         if (evinfo.mask & EVLOG_MASK_REGION)
251         {
252             EvlogRegionTable *table;
253
254             read_len = read (fd, &evinfo.evregion.size, sizeof (int));
255             GOTO_IF_FAIL (read_len == sizeof(int), print_done);
256             total += read_len;
257
258             for (i = 0 ; i < evinfo.evregion.size ; i++)
259             {
260                 table = malloc (sizeof(EvlogRegionTable));
261                 GOTO_IF_FAIL (table != NULL, print_done);
262
263                 if (!evinfo.evregion.init)
264                 {
265                     xorg_list_init(&evinfo.evregion.list);
266                     evinfo.evregion.init = 1;
267                 }
268
269                 read_len = read (fd, table, sizeof (EvlogRegionTable));
270                 GOTO_IF_FAIL (read_len == sizeof(EvlogRegionTable), print_done);
271                 total += read_len;
272
273                 xorg_list_add(&table->link, &evinfo.evregion.list);
274             }
275         }
276
277         GOTO_IF_FAIL (evlog_len == total, print_done);
278
279         if (xDbgEvlogRuleValidate (&evinfo))
280         {
281             xDbgEvlogFillLog(&evinfo, eo->detail, log, &size);
282             printf ("%s", log);
283         }
284
285         if (evinfo.req.ptr)
286         {
287             free (evinfo.req.ptr);
288             evinfo.req.ptr = NULL;
289         }
290
291         if (evinfo.evt.ptr)
292         {
293             free (evinfo.evt.ptr);
294             evinfo.evt.ptr = NULL;
295         }
296
297         xDbgDistroyAtomList(&evinfo);
298         xDbgDistroyRegionList(&evinfo);
299     }
300
301
302 print_done:
303     if (evinfo.req.ptr)
304         free (evinfo.req.ptr);
305
306     if (evinfo.evt.ptr)
307         free (evinfo.evt.ptr);
308
309     xDbgDistroyAtomList(&evinfo);
310     xDbgDistroyRegionList(&evinfo);
311
312     if (cfd >= 0)
313         close (cfd);
314
315     if (fd >= 0)
316         close (fd);
317 }
318
319
320 static void
321 _checkOption(int argc, char** argv)
322 {
323     int c;
324     int opt_str_len = 0;
325     char* opt_str = NULL;
326     EvlogOption eo = {0,};
327     char rule_log[LOG_SIZE];
328     int rule_size = sizeof (rule_log);
329
330     eo.pid = atoi (argv[0]);
331     eo.isRule = FALSE;
332     eo.detail = TRUE;
333     strncpy(eo.command_name, argv[1], PATH_MAX);
334
335     if (argc < 3)
336     {
337         _printUsage( eo.command_name );
338         return;
339     }
340
341     while ((c = getopt(argc, argv, "f:a:n:d:h")) != EOF)
342     {
343         switch (c)
344         {
345             case 'f':
346                 {
347                     opt_str = optarg;
348                     opt_str_len = strlen(opt_str);
349
350                     if(opt_str_len > 0)
351                     {
352                         strncpy (eo.path_name, opt_str, PATH_MAX);
353                     }
354                     break;
355                 }
356
357             case 'a':
358                 {
359                     opt_str = optarg;
360                     opt_str_len = strlen(opt_str);
361                     if(opt_str_len > 0)
362                     {
363                         int new_argc = 3;
364                         char* new_argv[3] = {"add", "allow", };
365
366                         new_argv[2] = (char*)malloc (opt_str_len + 1);
367                         if(!new_argv[2])
368                         {
369                             printf ("failed: malloc new_argv[2]\n");
370                             return;
371                         }
372
373                         strncpy (new_argv[2], opt_str , opt_str_len);
374                         if(!xDbgEvlogRuleSet ((const int) new_argc,
375                                               (const char**) new_argv,
376                                                rule_log, &rule_size))
377                         {
378                             printf("%s\n", rule_log);
379                             return;
380                         }
381                         eo.isRule = TRUE;
382
383                         free (new_argv[2]);
384                     }
385
386                     break;
387                }
388
389             case 'n':
390                 {
391                     opt_str = optarg;
392                     opt_str_len = strlen(opt_str);
393
394                     if(opt_str_len > 0)
395                     {
396                         int new_argc = 3;
397                         char* new_argv[3] = {"add", "deny", };
398
399                         new_argv[2] = (char*)malloc (opt_str_len + 1);
400                         if(!new_argv[2])
401                         {
402                             printf ("failed: malloc new_argv[2]\n");
403                             return;
404                         }
405
406                         strncpy (new_argv[2], opt_str , opt_str_len);
407                         if(!xDbgEvlogRuleSet ((const int) new_argc,
408                                               (const char**) new_argv,
409                                                rule_log, &rule_size))
410                         {
411                             printf("%s\n", rule_log);
412                             return;
413                         }
414                         eo.isRule = TRUE;
415
416                         free (new_argv[2]);
417                     }
418
419                     break;
420                 }
421
422             case 'd':
423                 {
424                     opt_str = optarg;
425                     opt_str_len = strlen(opt_str);
426
427                     if(opt_str_len > 0)
428                     {
429                         eo.detail = (atoi(optarg))?TRUE:FALSE;
430                         printf ("detail %s\n", (eo.detail)?"ON":"OFF");
431                     }
432                     break;
433                 }
434
435             case 'h':
436             case '?':
437                 {
438                     _printUsage( eo.command_name );
439                     return;
440                     break;
441                 }
442
443             default:
444                 break;
445         }
446     }
447
448     _xEvlogAnalyzePrint(&eo, rule_log, &rule_size);
449 }
450
451
452
453 int main(int argc, char** argv)
454 {
455     char **new_argv;
456     int new_argc, i;
457     char temp[128];
458
459     new_argc = argc + 1;
460     new_argv = (char**)malloc (new_argc * sizeof (char*));
461     if (!new_argv)
462     {
463         printf ("failed: malloc new argv\n");
464         exit (-1);
465     }
466
467     snprintf (temp, sizeof(temp), "%d", (int)getpid());
468     new_argv[0] = temp;
469
470     for (i = 0; i < argc; i++)
471         new_argv[i+1] = argv[i];
472
473     _checkOption(new_argc, new_argv);
474
475     free (new_argv);
476
477     return 0;
478 }