1 /**************************************************************************
5 Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
7 Contact: Boram Park <boram1288.park@samsung.com>
8 Sangjin LEE <lsj119@samsung.com>
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:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
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.
30 **************************************************************************/
35 #include <sys/types.h>
36 #include <sys/fcntl.h>
44 #include "xdbg_types.h"
45 #include "xdbg_evlog.h"
46 #include "bool_exp_rule_checker.h"
47 #include <X11/Xlibint.h>
55 static char *evt_type[] = { "Event", "Request", "Reply", "Flush", "Error" };
56 static char *evt_dir[] = { "<====", "---->", "<----", "*****", "<----"};
58 static RULE_CHECKER rc = NULL;
61 _mergeArgs (char *target, int target_size, int argc, const char ** argv)
66 for (i=0; i<argc; i++)
68 len = snprintf (target, target_size, "%s", argv[i]);
81 _strcasecmp(const char *str1, const char *str2)
83 const u_char *us1 = (const u_char *) str1, *us2 = (const u_char *) str2;
85 while (tolower(*us1) == tolower(*us2)) {
91 return (tolower(*us1) - tolower(*us2));
95 xDbgEvlogGetCmd (char *path)
100 p = strrchr (path, '/');
105 xDbgEvlogRuleSet (const int argc, const char **argv, char *reply, int *len)
107 const char * command;
110 rc = rulechecker_init();
114 rulechecker_print_rule (rc, reply, len);
120 if (!_strcasecmp (command, "add"))
122 POLICY_TYPE policy_type;
123 RC_RESULT_TYPE result;
124 const char * policy = argv[1];
125 char merge[8192]={0,}, rule[8192]={0,};
126 int i, index = 0, size_rule;
131 REPLY ("Error : Too few arguments.\n");
135 if (!_strcasecmp (policy, "ALLOW"))
137 else if (!_strcasecmp (policy, "DENY"))
141 REPLY ("Error : Unknown policy : [%s].\n Policy should be ALLOW or DENY.\n", policy);
145 _mergeArgs (merge, sizeof (merge), argc - 2, &(argv[2]));
147 size_rule = sizeof (rule) - 1;
149 for (i = 0 ; i < strlen(merge) ; i++)
151 if(merge[i] == '\"' || merge[i] == '\'')
154 if (index > size_rule)
163 if (index > size_rule)
168 const char* plus = "|| type=reply || type=error";
169 int len = MIN (size_rule - index, strlen(plus));
170 strncat(rule, plus, len);
172 if (index > size_rule)
179 rule[index++] = merge[i];
180 if (index > size_rule)
184 result = rulechecker_add_rule (rc, policy_type, rule);
185 if (result == RC_ERR_TOO_MANY_RULES)
187 REPLY ("Error : Too many rules were added.\n");
190 else if (result == RC_ERR_PARSE_ERROR)
192 REPLY ("Error : An error occured during parsing the rule [%s]\n", rule);
196 REPLY ("The rule was successfully added.\n\n");
197 rulechecker_print_rule (rc, reply, len);
200 else if (!_strcasecmp (command, "remove"))
202 const char * remove_idx;
207 REPLY ("Error : Too few arguments.\n");
211 for (i=0; i<argc - 1; i++)
213 remove_idx = argv[i+1];
215 if (!_strcasecmp (remove_idx, "all"))
217 rulechecker_destroy (rc);
218 rc = rulechecker_init();
219 REPLY ("Every rules were successfully removed.\n");
223 int index = atoi (remove_idx);
224 if (isdigit (*remove_idx) && rulechecker_remove_rule (rc, index) == 0)
225 REPLY ("The rule [%d] was successfully removed.\n", index);
227 REPLY ("Rule remove fail : No such rule [%s].\n", remove_idx);
230 rulechecker_print_rule (rc, reply, len);
233 else if (!_strcasecmp (command, "file"))
237 REPLY ("Error : Too few arguments.\n");
241 if (!xDbgEvlogReadRuleFile(argv[1], reply, len))
243 rulechecker_print_rule (rc, reply, len);
247 else if (!_strcasecmp (command, "print"))
249 rulechecker_print_rule (rc, reply, len);
252 else if (!_strcasecmp (command, "help"))
254 REPLY ("%s", rulechecker_print_usage());
258 REPLY ("%s\nUnknown command : [%s].\n\n", rulechecker_print_usage(), command);
264 xDbgEvlogRuleValidate (EvlogInfo *evinfo)
266 const char *evlog_name = "";
270 rc = rulechecker_init ();
274 XDBG_LOG ("failed: create rulechecker\n");
278 cmd = xDbgEvlogGetCmd (evinfo->client.command);
280 if (evinfo->type == REQUEST)
281 evlog_name = evinfo->req.name;
282 else if (evinfo->type == EVENT)
283 evlog_name = evinfo->evt.name;
284 else if (evinfo ->type == REPLY)
285 evlog_name = evinfo->rep.name;
287 return rulechecker_validate_rule (rc,
296 xDbgEvlogReadRuleFile(const char *filename, char *reply, int *len)
303 fd = open (filename, O_RDONLY);
306 REPLY ("failed: open '%s'. (%s)\n", filename, strerror(errno));
310 rule_len = read(fd, fs, sizeof(fs));
313 while (pfs - fs < rule_len)
316 char *new_argv[3] = {"add", };
317 char policy[64] = {0, };
318 char rule[1024] = {0, };
321 if (pfs[0] == ' ' || pfs[0] == '\n')
326 for (i = 0 ; pfs[i] != ' ' ; i++)
329 new_argv[1] = policy;
330 pfs += (strlen(new_argv[1]) + 1);
332 memset(rule, 0, sizeof(rule));
333 for (i = 0 ; pfs[i] != '\n' ; i++)
338 pfs += (strlen(new_argv[2]) + 1);
341 if(!xDbgEvlogRuleSet ((const int) new_argc, (const char**) new_argv, reply, len))
355 ExtensionInfo Evlog_extensions[] = {
356 {xDbgEvlogCompositeGetBase, 0, 0, 0, NULL, NULL},
357 {xDbgEvlogDamageGetBase, 0, 0, 0, NULL, NULL},
358 {xDbgEvlogDri2GetBase, 0, 0, 0, NULL, NULL},
359 {xDbgEvlogGestureGetBase, 0, 0, 0, NULL, NULL},
360 {xDbgEvlogXinputGetBase, 0, 0, 0, NULL, NULL},
361 {xDbgEvlogRandrGetBase, 0, 0, 0, NULL, NULL},
362 {xDbgEvlogXextDpmsGetBase, 0, 0, 0, NULL, NULL},
363 {xDbgEvlogXextShmGetBase, 0, 0, 0, NULL, NULL},
364 {xDbgEvlogXextSyncGetBase, 0, 0, 0, NULL, NULL},
365 {xDbgEvlogXextXtestGetBase, 0, 0, 0, NULL, NULL},
366 {xDbgEvlogXextXtestExt1GetBase, 0, 0, 0, NULL, NULL},
367 {xDbgEvlogXextShapeGetBase, 0, 0, 0, NULL, NULL},
368 {xDbgEvlogXvGetBase, 0, 0, 0, NULL, NULL}
370 ExtensionInfo* Sorted_Evlog_extensions;
371 int Extensions_size = 0;
374 _ExtensionsSwap(ExtensionInfo* first, ExtensionInfo* second)
384 _SortEvlogExtensions ()
389 Sorted_Evlog_extensions = (ExtensionInfo*)malloc(sizeof(Evlog_extensions));
390 RETURN_VAL_IF_FAIL (Sorted_Evlog_extensions != NULL, FALSE);
392 memcpy(Sorted_Evlog_extensions, Evlog_extensions, sizeof(Evlog_extensions));
394 for (i = 0 ; i < Extensions_size - 1 ; i++)
397 for (j = 1 ; j < Extensions_size - i ; j++)
399 if(Sorted_Evlog_extensions[j-1].evt_base > Sorted_Evlog_extensions[j].evt_base)
401 _ExtensionsSwap(&Sorted_Evlog_extensions[j-1], &Sorted_Evlog_extensions[j]);
413 xDbgEvlogGetExtensionEntry ()
416 static Bool success = FALSE;
423 Extensions_size = sizeof(Evlog_extensions) / sizeof (ExtensionInfo);
425 for (i = 0 ; i < Extensions_size ; i++)
427 Evlog_extensions[i].get_base_func (Evlog_extensions + i);
430 if(!_SortEvlogExtensions ())
441 xDbgEvlogFillLog (EvlogInfo *evinfo, int detail_level, char *reply, int *len)
445 RETURN_VAL_IF_FAIL (evinfo->type >= 0 && (sizeof (evt_dir) / sizeof (char*)), FALSE);
446 RETURN_VAL_IF_FAIL (evinfo->type >= 0 && (sizeof (evt_type) / sizeof (char*)), FALSE);
448 if (evinfo->type == REPLY && !evinfo->rep.isStart)
450 if (detail_level >= EVLOG_PRINT_REPLY_DETAIL)
456 REPLY ("[%10.3f][%5ld] %22s(%2d:%5d) %s %7s ",
457 evinfo->time / 1000.0,
459 xDbgEvlogGetCmd (evinfo->client.command),
460 evinfo->client.index,
462 evt_dir[evinfo->type],
463 evt_type[evinfo->type]);
465 if (evinfo->type == REQUEST)
468 reply = xDbgEvlogReqeust (evinfo, detail_level, reply, len);
471 else if (evinfo->type == EVENT)
473 evinfo->evt.size = sizeof (xEvent);
475 reply = xDbgEvlogEvent (evinfo, detail_level, reply, len);
478 else if (evinfo->type == REPLY)
481 reply = xDbgEvlogReply (evinfo, detail_level, reply, len);
484 else if (evinfo->type == ERROR)
486 REPLY("(ErrorCode(0x%02x) resourceID(0x%lx) majorCode(%d) minorCode(%d))",
487 evinfo->err.errorCode,
488 evinfo->err.resourceID,
489 evinfo->err.majorCode,
490 evinfo->err.minorCode);
494 const char *evlog_name = "";
495 if (evinfo->type == REQUEST)
496 evlog_name = evinfo->req.name;
497 else if (evinfo->type == EVENT)
498 evlog_name = evinfo->evt.name;
499 else if (evinfo->type == REPLY)
500 evlog_name = evinfo->rep.name;
501 REPLY ("(%s)", evlog_name);
512 void xDbgDistroyAtomList (EvlogInfo *evinfo)
514 EvlogAtomTable *cur = NULL, *next = NULL;
516 if (!evinfo->evatom.init)
519 xorg_list_for_each_entry_safe(cur, next, &evinfo->evatom.list, link)
521 xorg_list_del(&cur->link);
525 evinfo->evatom.init = 0;
526 evinfo->evatom.size = 0;
529 void xDbgDistroyRegionList (EvlogInfo *evinfo)
531 EvlogRegionTable *cur = NULL, *next = NULL;
533 if (!evinfo->evregion.init)
536 xorg_list_for_each_entry_safe(cur, next, &evinfo->evregion.list, link)
538 xorg_list_del(&cur->link);
542 evinfo->evregion.init = 0;
543 evinfo->evregion.size = 0;
546 char* xDbgGetAtom(Atom atom, EvlogInfo *evinfo, char *reply, int *len)
548 EvlogAtomTable *table;
550 table = malloc (sizeof(EvlogAtomTable));
554 evinfo->mask |= EVLOG_MASK_ATOM;
557 if (!evinfo->evatom.init)
559 xorg_list_init(&evinfo->evatom.list);
560 evinfo->evatom.init = 1;
563 if (NameForAtom(atom))
564 snprintf (table->buf, XDBG_BUF_SIZE, "%s", (char*)NameForAtom(atom));
566 snprintf (table->buf, XDBG_BUF_SIZE, "0x%lx", atom);
568 xorg_list_add(&table->link, &evinfo->evatom.list);
569 evinfo->evatom.size++;
571 xorg_list_for_each_entry(table, &evinfo->evatom.list, link)
572 if(table->xid == atom)
574 REPLY ("(%s)", table->buf);
581 char* xDbgGetRegion(XserverRegion region, EvlogInfo *evinfo, char *reply, int *len)
583 EvlogRegionTable *table;
585 extern _X_EXPORT RESTYPE RegionResType;
590 int err = dixLookupResourceByType((pointer *) &pRegion, region,
591 RegionResType, (ClientPtr)evinfo->client.pClient,
594 evinfo->mask |= EVLOG_MASK_REGION;
596 if (!evinfo->evregion.init)
598 xorg_list_init(&evinfo->evregion.list);
599 evinfo->evregion.init = 1;
604 table = malloc (sizeof(EvlogAtomTable));
610 snprintf (table->buf, XDBG_BUF_SIZE, "0x%lx", region);
611 xorg_list_add(&table->link, &evinfo->evregion.list);
612 evinfo->evregion.size++;
616 nrect = RegionNumRects(pRegion);
617 rects = RegionRects(pRegion);
619 for (i = 0; i < nrect; i++)
621 table = malloc (sizeof(EvlogAtomTable));
628 s += snprintf (table->buf + s, XDBG_BUF_SIZE - s,
632 rects[i].x2 - rects[i].x1,
633 rects[i].y2 - rects[i].y1);
634 xorg_list_add(&table->link, &evinfo->evregion.list);
635 evinfo->evregion.size++;
641 xorg_list_for_each_entry(table, &evinfo->evregion.list, link)
642 if(table->xid == region)
644 REPLY ("%s", table->buf);
645 if(table != xorg_list_last_entry(&evinfo->evregion.list, EvlogRegionTable, link))