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 **************************************************************************/
37 #include <sys/types.h>
38 #include <sys/fcntl.h>
46 #include "xdbg_types.h"
47 #include "xdbg_evlog.h"
48 #include "bool_exp_rule_checker.h"
49 #include <X11/Xlibint.h>
57 static char *evt_type[] = { "Event", "Request", "Reply", "Flush", "Error" };
58 static char *evt_dir[] = { "<====", "---->", "<----", "*****", "<----"};
60 static RULE_CHECKER rc = NULL;
63 _mergeArgs (char *target, int target_size, int argc, const char ** argv)
68 for (i=0; i<argc; i++)
70 len = snprintf (target, target_size, "%s", argv[i]);
83 _strcasecmp(const char *str1, const char *str2)
85 const u_char *us1 = (const u_char *) str1, *us2 = (const u_char *) str2;
87 while (tolower(*us1) == tolower(*us2)) {
93 return (tolower(*us1) - tolower(*us2));
97 xDbgEvlogGetCmd (char *path)
102 p = strrchr (path, '/');
107 xDbgEvlogRuleSet (const int argc, const char **argv, char *reply, int *len)
109 const char * command;
112 rc = rulechecker_init();
116 rulechecker_print_rule (rc, reply, len);
122 if (!_strcasecmp (command, "add"))
124 POLICY_TYPE policy_type;
125 RC_RESULT_TYPE result;
126 const char * policy = argv[1];
127 char merge[8192]={0,}, rule[8192]={0,};
128 int i, index = 0, size_rule;
133 REPLY ("Error : Too few arguments.\n");
137 if (!_strcasecmp (policy, "ALLOW"))
139 else if (!_strcasecmp (policy, "DENY"))
143 REPLY ("Error : Unknown policy : [%s].\n Policy should be ALLOW or DENY.\n", policy);
147 _mergeArgs (merge, sizeof (merge), argc - 2, &(argv[2]));
149 size_rule = sizeof (rule) - 1;
151 for (i = 0 ; i < strlen(merge) ; i++)
153 if(merge[i] == '\"' || merge[i] == '\'')
156 if (index > size_rule)
165 if (index > size_rule)
170 const char* plus = "|| type=reply || type=error";
171 int len = MIN (size_rule - index, strlen(plus));
172 strncat(rule, plus, len);
174 if (index > size_rule)
181 rule[index++] = merge[i];
182 if (index > size_rule)
186 result = rulechecker_add_rule (rc, policy_type, rule);
187 if (result == RC_ERR_TOO_MANY_RULES)
189 REPLY ("Error : Too many rules were added.\n");
192 else if (result == RC_ERR_PARSE_ERROR)
194 REPLY ("Error : An error occured during parsing the rule [%s]\n", rule);
198 REPLY ("The rule was successfully added.\n\n");
199 rulechecker_print_rule (rc, reply, len);
202 else if (!_strcasecmp (command, "remove"))
204 const char * remove_idx;
209 REPLY ("Error : Too few arguments.\n");
213 for (i=0; i<argc - 1; i++)
215 remove_idx = argv[i+1];
217 if (!_strcasecmp (remove_idx, "all"))
219 rulechecker_destroy (rc);
220 rc = rulechecker_init();
221 REPLY ("Every rules were successfully removed.\n");
225 int index = atoi (remove_idx);
226 if (isdigit (*remove_idx) && rulechecker_remove_rule (rc, index) == 0)
227 REPLY ("The rule [%d] was successfully removed.\n", index);
229 REPLY ("Rule remove fail : No such rule [%s].\n", remove_idx);
232 rulechecker_print_rule (rc, reply, len);
235 else if (!_strcasecmp (command, "file"))
239 REPLY ("Error : Too few arguments.\n");
243 if (!xDbgEvlogReadRuleFile(argv[1], reply, len))
245 rulechecker_print_rule (rc, reply, len);
249 else if (!_strcasecmp (command, "print"))
251 rulechecker_print_rule (rc, reply, len);
254 else if (!_strcasecmp (command, "help"))
256 REPLY ("%s", rulechecker_print_usage());
260 REPLY ("%s\nUnknown command : [%s].\n\n", rulechecker_print_usage(), command);
266 xDbgEvlogRuleValidate (EvlogInfo *evinfo)
268 const char *evlog_name = "";
272 rc = rulechecker_init ();
276 XDBG_LOG ("failed: create rulechecker\n");
280 cmd = xDbgEvlogGetCmd (evinfo->client.command);
282 if (evinfo->type == REQUEST)
283 evlog_name = evinfo->req.name;
284 else if (evinfo->type == EVENT)
285 evlog_name = evinfo->evt.name;
286 else if (evinfo ->type == REPLY)
287 evlog_name = evinfo->rep.name;
289 return rulechecker_validate_rule (rc,
298 xDbgEvlogReadRuleFile(const char *filename, char *reply, int *len)
305 fd = open (filename, O_RDONLY);
308 REPLY ("failed: open '%s'. (%s)\n", filename, strerror(errno));
312 rule_len = read(fd, fs, sizeof(fs));
315 while (pfs - fs < rule_len)
318 char *new_argv[3] = {"add", };
319 char policy[64] = {0, };
320 char rule[1024] = {0, };
323 if (pfs[0] == ' ' || pfs[0] == '\n')
328 for (i = 0 ; pfs[i] != ' ' ; i++)
331 new_argv[1] = policy;
332 pfs += (strlen(new_argv[1]) + 1);
334 memset(rule, 0, sizeof(rule));
335 for (i = 0 ; pfs[i] != '\n' ; i++)
340 pfs += (strlen(new_argv[2]) + 1);
342 if(!xDbgEvlogRuleSet ((const int) new_argc, (const char**) new_argv, reply, len))
357 ExtensionInfo Evlog_extensions[] = {
358 {xDbgEvlogCompositeGetBase, 0, 0, 0, NULL, NULL},
359 {xDbgEvlogDamageGetBase, 0, 0, 0, NULL, NULL},
360 {xDbgEvlogDri2GetBase, 0, 0, 0, NULL, NULL},
361 {xDbgEvlogGestureGetBase, 0, 0, 0, NULL, NULL},
362 {xDbgEvlogXinputGetBase, 0, 0, 0, NULL, NULL},
363 {xDbgEvlogRandrGetBase, 0, 0, 0, NULL, NULL},
364 {xDbgEvlogXextDpmsGetBase, 0, 0, 0, NULL, NULL},
365 {xDbgEvlogXextShmGetBase, 0, 0, 0, NULL, NULL},
366 {xDbgEvlogXextSyncGetBase, 0, 0, 0, NULL, NULL},
367 {xDbgEvlogXextXtestGetBase, 0, 0, 0, NULL, NULL},
368 {xDbgEvlogXextXtestExt1GetBase, 0, 0, 0, NULL, NULL},
369 {xDbgEvlogXextShapeGetBase, 0, 0, 0, NULL, NULL},
370 {xDbgEvlogXvGetBase, 0, 0, 0, NULL, NULL},
372 {xDbgEvlogHwcGetBase, 0, 0, 0, NULL, NULL},
376 ExtensionInfo* Sorted_Evlog_extensions;
377 int Extensions_size = 0;
380 _ExtensionsSwap(ExtensionInfo* first, ExtensionInfo* second)
390 _SortEvlogExtensions ()
395 Sorted_Evlog_extensions = (ExtensionInfo*)malloc(sizeof(Evlog_extensions));
396 RETURN_VAL_IF_FAIL (Sorted_Evlog_extensions != NULL, FALSE);
398 memcpy(Sorted_Evlog_extensions, Evlog_extensions, sizeof(Evlog_extensions));
400 for (i = 0 ; i < Extensions_size - 1 ; i++)
403 for (j = 1 ; j < Extensions_size - i ; j++)
405 if(Sorted_Evlog_extensions[j-1].evt_base > Sorted_Evlog_extensions[j].evt_base)
407 _ExtensionsSwap(&Sorted_Evlog_extensions[j-1], &Sorted_Evlog_extensions[j]);
419 xDbgEvlogGetExtensionEntry ()
422 static Bool success = FALSE;
429 Extensions_size = sizeof(Evlog_extensions) / sizeof (ExtensionInfo);
431 for (i = 0 ; i < Extensions_size ; i++)
433 Evlog_extensions[i].get_base_func (Evlog_extensions + i);
436 if(!_SortEvlogExtensions ())
447 xDbgEvlogFillLog (EvlogInfo *evinfo, int detail_level, char *reply, int *len)
451 RETURN_VAL_IF_FAIL (evinfo->type >= 0 && (sizeof (evt_dir) / sizeof (char*)), FALSE);
452 RETURN_VAL_IF_FAIL (evinfo->type >= 0 && (sizeof (evt_type) / sizeof (char*)), FALSE);
454 if (evinfo->type == REPLY && !evinfo->rep.isStart)
456 if (detail_level >= EVLOG_PRINT_REPLY_DETAIL)
462 REPLY ("[%10.3f][%5ld] %22s(%2d:%5d) %s %7s ",
463 evinfo->time / 1000.0,
464 (long int)evinfo->time - prev,
465 xDbgEvlogGetCmd (evinfo->client.command),
466 evinfo->client.index,
468 evt_dir[evinfo->type],
469 evt_type[evinfo->type]);
471 if (evinfo->type == REQUEST)
474 reply = xDbgEvlogReqeust (evinfo, detail_level, reply, len);
477 else if (evinfo->type == EVENT)
479 evinfo->evt.size = sizeof (xEvent);
481 reply = xDbgEvlogEvent (evinfo, detail_level, reply, len);
484 else if (evinfo->type == REPLY)
487 reply = xDbgEvlogReply (evinfo, detail_level, reply, len);
490 else if (evinfo->type == ERROR)
492 REPLY("(ErrorCode(0x%02x) resourceID(0x%x) majorCode(%d) minorCode(%d))",
493 evinfo->err.errorCode,
494 (unsigned int)evinfo->err.resourceID,
495 evinfo->err.majorCode,
496 evinfo->err.minorCode);
500 const char *evlog_name = "";
501 if (evinfo->type == REQUEST)
502 evlog_name = evinfo->req.name;
503 else if (evinfo->type == EVENT)
504 evlog_name = evinfo->evt.name;
505 else if (evinfo->type == REPLY)
506 evlog_name = evinfo->rep.name;
507 REPLY ("(%s)", evlog_name);
518 void xDbgDistroyAtomList (EvlogInfo *evinfo)
520 EvlogAtomTable *cur = NULL, *next = NULL;
522 if (!evinfo->evatom.init)
525 xorg_list_for_each_entry_safe(cur, next, &evinfo->evatom.list, link)
527 xorg_list_del(&cur->link);
531 evinfo->evatom.init = 0;
532 evinfo->evatom.size = 0;
535 void xDbgDistroyRegionList (EvlogInfo *evinfo)
537 EvlogRegionTable *cur = NULL, *next = NULL;
539 if (!evinfo->evregion.init)
542 xorg_list_for_each_entry_safe(cur, next, &evinfo->evregion.list, link)
544 xorg_list_del(&cur->link);
548 evinfo->evregion.init = 0;
549 evinfo->evregion.size = 0;
552 char* xDbgGetAtom(Atom atom, EvlogInfo *evinfo, char *reply, int *len)
554 EvlogAtomTable *table;
556 table = malloc (sizeof(EvlogAtomTable));
560 evinfo->mask |= EVLOG_MASK_ATOM;
563 if (!evinfo->evatom.init)
565 xorg_list_init(&evinfo->evatom.list);
566 evinfo->evatom.init = 1;
569 if (NameForAtom(atom))
570 snprintf (table->buf, XDBG_BUF_SIZE, "%s", (char*)NameForAtom(atom));
572 snprintf (table->buf, XDBG_BUF_SIZE, "0x%x", (unsigned int)atom);
574 xorg_list_add(&table->link, &evinfo->evatom.list);
575 evinfo->evatom.size++;
577 xorg_list_for_each_entry(table, &evinfo->evatom.list, link)
578 if(table->xid == atom)
580 REPLY ("(%s)", table->buf);
587 char* xDbgGetRegion(XserverRegion region, EvlogInfo *evinfo, char *reply, int *len)
589 EvlogRegionTable *table;
591 extern _X_EXPORT RESTYPE RegionResType;
596 int err = dixLookupResourceByType((pointer *) &pRegion, region,
597 RegionResType, (ClientPtr)evinfo->client.pClient,
600 evinfo->mask |= EVLOG_MASK_REGION;
602 if (!evinfo->evregion.init)
604 xorg_list_init(&evinfo->evregion.list);
605 evinfo->evregion.init = 1;
610 table = malloc (sizeof(EvlogAtomTable));
616 snprintf (table->buf, XDBG_BUF_SIZE, "0x%x", (unsigned int)region);
617 xorg_list_add(&table->link, &evinfo->evregion.list);
618 evinfo->evregion.size++;
622 nrect = RegionNumRects(pRegion);
623 rects = RegionRects(pRegion);
625 for (i = 0; i < nrect; i++)
627 table = malloc (sizeof(EvlogAtomTable));
634 s += snprintf (table->buf + s, XDBG_BUF_SIZE - s,
638 rects[i].x2 - rects[i].x1,
639 rects[i].y2 - rects[i].y1);
640 xorg_list_add(&table->link, &evinfo->evregion.list);
641 evinfo->evregion.size++;
647 xorg_list_for_each_entry(table, &evinfo->evregion.list, link)
648 if(table->xid == region)
650 REPLY ("%s", table->buf);
651 if(table != xorg_list_last_entry(&evinfo->evregion.list, EvlogRegionTable, link))