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;
288 else if (evinfo ->type == XERROR)
291 return rulechecker_validate_rule (rc,
300 xDbgEvlogReadRuleFile(const char *filename, char *reply, int *len)
307 fd = open (filename, O_RDONLY);
310 char err_buf[256] = {0,};
313 errp = (char *)strerror_r (errno, err_buf, sizeof(err_buf));
314 REPLY ("failed: open '%s'. (%s)\n", filename, errp);
318 rule_len = read(fd, fs, sizeof(fs));
321 while (pfs - fs < rule_len)
324 char *new_argv[3] = {"add", };
325 char policy[64] = {0, };
326 char rule[1024] = {0, };
329 if (pfs[0] == ' ' || pfs[0] == '\n')
334 for (i = 0 ; pfs[i] != ' ' ; i++)
337 new_argv[1] = policy;
338 pfs += (strlen(new_argv[1]) + 1);
340 memset(rule, 0, sizeof(rule));
341 for (i = 0 ; pfs[i] != '\n' ; i++)
346 pfs += (strlen(new_argv[2]) + 1);
348 if(!xDbgEvlogRuleSet ((const int) new_argc, (const char**) new_argv, reply, len))
363 ExtensionInfo Evlog_extensions[] = {
364 {xDbgEvlogCompositeGetBase, 0, 0, 0, NULL, NULL},
365 {xDbgEvlogDamageGetBase, 0, 0, 0, NULL, NULL},
366 {xDbgEvlogDri2GetBase, 0, 0, 0, NULL, NULL},
367 {xDbgEvlogGestureGetBase, 0, 0, 0, NULL, NULL},
368 {xDbgEvlogXinputGetBase, 0, 0, 0, NULL, NULL},
369 {xDbgEvlogRandrGetBase, 0, 0, 0, NULL, NULL},
370 {xDbgEvlogXextDpmsGetBase, 0, 0, 0, NULL, NULL},
371 {xDbgEvlogXextShmGetBase, 0, 0, 0, NULL, NULL},
372 {xDbgEvlogXextSyncGetBase, 0, 0, 0, NULL, NULL},
373 {xDbgEvlogXextXtestGetBase, 0, 0, 0, NULL, NULL},
374 {xDbgEvlogXextXtestExt1GetBase, 0, 0, 0, NULL, NULL},
375 {xDbgEvlogXextShapeGetBase, 0, 0, 0, NULL, NULL},
376 {xDbgEvlogXvGetBase, 0, 0, 0, NULL, NULL},
377 {xDbgEvlogDri3GetBase, 0, 0, 0, NULL, NULL},
378 {xDbgEvlogPresentGetBase, 0, 0, 0, NULL, NULL},
380 {xDbgEvlogHwcGetBase, 0, 0, 0, NULL, NULL},
384 ExtensionInfo* Sorted_Evlog_extensions;
385 int Extensions_size = 0;
388 _ExtensionsSwap(ExtensionInfo* first, ExtensionInfo* second)
398 _SortEvlogExtensions ()
403 Sorted_Evlog_extensions = (ExtensionInfo*)malloc(sizeof(Evlog_extensions));
404 RETURN_VAL_IF_FAIL (Sorted_Evlog_extensions != NULL, FALSE);
406 memcpy(Sorted_Evlog_extensions, Evlog_extensions, sizeof(Evlog_extensions));
408 for (i = 0 ; i < Extensions_size - 1 ; i++)
411 for (j = 1 ; j < Extensions_size - i ; j++)
413 if(Sorted_Evlog_extensions[j-1].evt_base > Sorted_Evlog_extensions[j].evt_base)
415 _ExtensionsSwap(&Sorted_Evlog_extensions[j-1], &Sorted_Evlog_extensions[j]);
427 xDbgEvlogGetExtensionEntry ()
430 static Bool success = FALSE;
437 Extensions_size = sizeof(Evlog_extensions) / sizeof (ExtensionInfo);
439 for (i = 0 ; i < Extensions_size ; i++)
441 Evlog_extensions[i].get_base_func (Evlog_extensions + i);
444 if(!_SortEvlogExtensions ())
455 xDbgEvlogFillLog (EvlogInfo *evinfo, int detail_level, char *reply, int *len)
459 RETURN_VAL_IF_FAIL (evinfo->type >= 0 && (sizeof (evt_dir) / sizeof (char*)), FALSE);
460 RETURN_VAL_IF_FAIL (evinfo->type >= 0 && (sizeof (evt_type) / sizeof (char*)), FALSE);
462 if (evinfo->type == REPLY && !evinfo->rep.isStart)
464 if (detail_level >= EVLOG_PRINT_REPLY_DETAIL)
470 REPLY ("[%10.3f][%5ld] %22s(%2d:%5d) %s %7s ",
471 evinfo->time / 1000.0,
472 (long int)evinfo->time - prev,
473 xDbgEvlogGetCmd (evinfo->client.command),
474 evinfo->client.index,
476 evt_dir[evinfo->type],
477 evt_type[evinfo->type]);
479 if (evinfo->type == REQUEST)
482 reply = xDbgEvlogReqeust (evinfo, detail_level, reply, len);
485 else if (evinfo->type == EVENT)
487 evinfo->evt.size = sizeof (xEvent);
489 reply = xDbgEvlogEvent (evinfo, detail_level, reply, len);
492 else if (evinfo->type == REPLY)
495 reply = xDbgEvlogReply (evinfo, detail_level, reply, len);
498 else if (evinfo->type == ERROR || evinfo->type == XERROR)
500 REPLY("(%s:ErrorCode(0x%02x) %s:majorCode(%d) minorCode(%d) resourceID(0x%x))",
501 evinfo->err.errorName,
502 evinfo->err.errorCode,
503 evinfo->err.majorName,
504 evinfo->err.majorCode,
505 evinfo->err.minorCode,
506 (unsigned int)evinfo->err.resourceID);
510 const char *evlog_name = "";
511 if (evinfo->type == REQUEST)
512 evlog_name = evinfo->req.name;
513 else if (evinfo->type == EVENT)
514 evlog_name = evinfo->evt.name;
515 else if (evinfo->type == REPLY)
516 evlog_name = evinfo->rep.name;
517 REPLY ("(%s)", evlog_name);
528 void xDbgDistroyAtomList (EvlogInfo *evinfo)
530 EvlogAtomTable *cur = NULL, *next = NULL;
532 if (!evinfo->evatom.init)
535 xorg_list_for_each_entry_safe(cur, next, &evinfo->evatom.list, link)
537 xorg_list_del(&cur->link);
541 evinfo->evatom.init = 0;
542 evinfo->evatom.size = 0;
545 void xDbgDistroyRegionList (EvlogInfo *evinfo)
547 EvlogRegionTable *cur = NULL, *next = NULL;
549 if (!evinfo->evregion.init)
552 xorg_list_for_each_entry_safe(cur, next, &evinfo->evregion.list, link)
554 xorg_list_del(&cur->link);
558 evinfo->evregion.init = 0;
559 evinfo->evregion.size = 0;
562 char* xDbgGetAtom(Atom atom, EvlogInfo *evinfo, char *reply, int *len)
564 EvlogAtomTable *table;
566 table = malloc (sizeof(EvlogAtomTable));
570 evinfo->mask |= EVLOG_MASK_ATOM;
573 if (!evinfo->evatom.init)
575 xorg_list_init(&evinfo->evatom.list);
576 evinfo->evatom.init = 1;
579 if (NameForAtom(atom))
580 snprintf (table->buf, XDBG_BUF_SIZE, "%s", (char*)NameForAtom(atom));
582 snprintf (table->buf, XDBG_BUF_SIZE, "0x%x", (unsigned int)atom);
584 xorg_list_add(&table->link, &evinfo->evatom.list);
585 evinfo->evatom.size++;
587 xorg_list_for_each_entry(table, &evinfo->evatom.list, link)
588 if(table->xid == atom)
590 REPLY ("(%s)", table->buf);
597 char* xDbgGetRegion(XserverRegion region, EvlogInfo *evinfo, char *reply, int *len)
599 EvlogRegionTable *table;
601 extern _X_EXPORT RESTYPE RegionResType;
606 int err = dixLookupResourceByType((pointer *) &pRegion, region,
607 RegionResType, (ClientPtr)evinfo->client.pClient,
610 evinfo->mask |= EVLOG_MASK_REGION;
612 if (!evinfo->evregion.init)
614 xorg_list_init(&evinfo->evregion.list);
615 evinfo->evregion.init = 1;
620 table = malloc (sizeof(EvlogAtomTable));
626 snprintf (table->buf, XDBG_BUF_SIZE, "0x%x", (unsigned int)region);
627 xorg_list_add(&table->link, &evinfo->evregion.list);
628 evinfo->evregion.size++;
632 nrect = RegionNumRects(pRegion);
633 rects = RegionRects(pRegion);
635 for (i = 0; i < nrect; i++)
637 table = malloc (sizeof(EvlogAtomTable));
644 s += snprintf (table->buf + s, XDBG_BUF_SIZE - s,
648 rects[i].x2 - rects[i].x1,
649 rects[i].y2 - rects[i].y1);
650 xorg_list_add(&table->link, &evinfo->evregion.list);
651 evinfo->evregion.size++;
657 xorg_list_for_each_entry(table, &evinfo->evregion.list, link)
658 if(table->xid == region)
660 REPLY ("%s", table->buf);
661 if(table != xorg_list_last_entry(&evinfo->evregion.list, EvlogRegionTable, link))