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 **************************************************************************/
39 #include <sys/types.h>
40 #include <sys/fcntl.h>
48 #include <sys/socket.h>
49 #include <linux/socket.h>
51 #ifdef HAS_GETPEERUCRED
57 #include <X11/Xatom.h>
58 #include <X11/extensions/XI2proto.h>
59 #include <windowstr.h>
62 #include "xdbg_types.h"
63 #include "xdbg_module.h"
64 #include "xdbg_module_evlog.h"
65 #include "xdbg_evlog.h"
70 #define FP1616toDBL(x) ((x) * 1.0 / (1 << 16))
72 Bool xev_trace_on = FALSE;
73 int xev_trace_detail_level = EVLOG_PRINT_DEFAULT;
74 static int xev_trace_fd = -1;
75 static int xev_trace_record_fd = -1;
76 static Atom atom_rotate = None;
77 static Atom atom_client_pid = None;
80 static void evtRecord (int fd, EvlogInfo *evinfo)
82 extern ExtensionInfo Evlog_extensions[];
83 extern int Extensions_size;
87 XDBG_RETURN_IF_FAIL (fd >= 0)
88 XDBG_RETURN_IF_FAIL (evinfo != NULL);
90 write_len = sizeof (int) +
95 if (evinfo->mask & EVLOG_MASK_CLIENT)
96 write_len += sizeof (EvlogClient);
98 if (evinfo->mask & EVLOG_MASK_REQUEST)
99 write_len += (sizeof (EvlogRequest) + (evinfo->req.length * 4));
101 if (evinfo->mask & EVLOG_MASK_EVENT)
102 write_len += (sizeof (EvlogEvent) + evinfo->evt.size);
104 if (evinfo->mask & EVLOG_MASK_REPLY)
105 write_len += (sizeof (EvlogReply) + evinfo->rep.size);
107 if (evinfo->mask & EVLOG_MASK_ERROR)
108 write_len += (sizeof (EvlogError));
110 if (evinfo->mask & EVLOG_MASK_ATOM)
111 write_len += (sizeof (int) +
112 (sizeof (EvlogAtomTable) * evinfo->evatom.size));
114 if (evinfo->mask & EVLOG_MASK_REGION)
115 write_len += (sizeof (int) +
116 (sizeof (EvlogRegionTable) * evinfo->evregion.size));
119 write_len += (sizeof (int) +
120 ((sizeof (int) * 3) * Extensions_size));
122 if (write (fd, &write_len, sizeof(int)) == -1)
124 XDBG_ERROR (MXDBG, "failed: write write_len\n");
130 if (write (fd, &Extensions_size, sizeof(int)) == -1)
132 XDBG_ERROR (MXDBG, "failed: write Extensions_size\n");
136 for (i = 0 ; i < Extensions_size ; i++)
138 if (write (fd, &Evlog_extensions[i].opcode, sizeof(int)) == -1)
140 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] opcode\n", i);
143 if (write (fd, &Evlog_extensions[i].evt_base, sizeof(int)) == -1)
145 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] evt_base\n", i);
148 if (write (fd, &Evlog_extensions[i].err_base, sizeof(int)) == -1)
150 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] err_base\n", i);
158 if (write (fd, &evinfo->time, sizeof(CARD32)) == -1)
160 XDBG_ERROR (MXDBG, "failed: write msec\n");
163 if (write (fd, &evinfo->type, sizeof(EvlogType)) == -1)
165 XDBG_ERROR (MXDBG, "failed: write type\n");
168 if (write (fd, &evinfo->mask, sizeof(int)) == -1)
170 XDBG_ERROR (MXDBG, "failed: write mask\n");
174 if (evinfo->mask & EVLOG_MASK_CLIENT)
175 if (write (fd, &evinfo->client, sizeof (EvlogClient)) == -1)
177 XDBG_ERROR (MXDBG, "failed: write client\n");
181 if (evinfo->mask & EVLOG_MASK_REQUEST)
183 if (write (fd, &evinfo->req, sizeof (EvlogRequest)) == -1)
185 XDBG_ERROR (MXDBG, "failed: write request\n");
188 if (write (fd, evinfo->req.ptr, (evinfo->req.length * 4)) == -1)
190 XDBG_ERROR (MXDBG, "failed: write request\n");
194 if (evinfo->mask & EVLOG_MASK_EVENT)
196 if (write (fd, &evinfo->evt, sizeof (EvlogEvent)) == -1)
198 XDBG_ERROR (MXDBG, "failed: write event\n");
202 XDBG_WARNING_IF_FAIL (evinfo->evt.size > 0);
203 if (write (fd, evinfo->evt.ptr, evinfo->evt.size) == -1)
205 XDBG_ERROR (MXDBG, "failed: write event\n");
209 if (evinfo->mask & EVLOG_MASK_REPLY)
211 if (write (fd, &evinfo->rep, sizeof (EvlogReply)) == -1)
213 XDBG_ERROR (MXDBG, "failed: write reply\n");
217 XDBG_WARNING_IF_FAIL (evinfo->rep.size > 0);
218 if (write (fd, evinfo->rep.ptr, evinfo->rep.size) == -1)
220 XDBG_ERROR (MXDBG, "failed: write reply\n");
224 if (evinfo->mask & EVLOG_MASK_ERROR)
226 if (write (fd, &evinfo->err, sizeof (EvlogError)) == -1)
228 XDBG_ERROR (MXDBG, "failed: write reply\n");
233 if (evinfo->mask & EVLOG_MASK_ATOM)
235 EvlogAtomTable *table = NULL;
237 if (write (fd, &evinfo->evatom.size, sizeof (int)) == -1)
239 XDBG_ERROR (MXDBG, "failed: write atom size\n");
242 xorg_list_for_each_entry(table, &evinfo->evatom.list, link)
243 if (write (fd, table, sizeof (EvlogAtomTable)) == -1)
245 XDBG_ERROR (MXDBG, "failed: write atom table\n");
250 if (evinfo->mask & EVLOG_MASK_REGION)
252 EvlogRegionTable *table = NULL;
254 if (write (fd, &evinfo->evregion.size, sizeof (int)) == -1)
256 XDBG_ERROR (MXDBG, "failed: write region size\n");
259 xorg_list_for_each_entry(table, &evinfo->evregion.list, link)
260 if (write (fd, table, sizeof (EvlogRegionTable)) == -1)
262 XDBG_ERROR (MXDBG, "failed: write region table\n");
268 static void evtPrintF (int fd, EvlogInfo *evinfo, char *log)
273 dprintf (fd, "%s", log);
276 static void evtPrint (EvlogType type, ClientPtr client, xEvent *ev, ReplyInfoRec *rep)
278 EvlogInfo evinfo = {0,};
279 static int EntryInit = 0;
287 ModuleClientInfo *info = GetClientInfo (client);
288 XDBG_RETURN_IF_FAIL (info != NULL);
291 evinfo.mask |= EVLOG_MASK_CLIENT;
292 evinfo.client.index = info->index;
293 evinfo.client.pid = info->pid;
294 evinfo.client.gid = info->gid;
295 evinfo.client.uid = info->uid;
297 min = MIN (sizeof (evinfo.client.command) - 1, strlen (info->command));
298 strncpy (evinfo.client.command, info->command, min);
299 evinfo.client.command[min] = '\0';
301 evinfo.client.pClient = (void*)client;
310 evinfo.mask |= EVLOG_MASK_REQUEST;
311 evinfo.req.id = stuff->reqType;
312 evinfo.req.length = client->req_len;
313 evinfo.req.ptr = client->requestBuffer;
315 if (client->requestVector == InitialVector && stuff->reqType == 1)
316 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s", conn[0]);
317 else if (client->requestVector == InitialVector && stuff->reqType == 2)
318 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s", conn[1]);
321 if (stuff->reqType < EXTENSION_BASE)
322 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
323 LookupRequestName (stuff->reqType, 0));
325 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
326 LookupRequestName (stuff->reqType, stuff->data));
335 evinfo.mask |= EVLOG_MASK_REPLY;
336 evinfo.rep.reqType = stuff->reqType;
337 evinfo.rep.reqData = stuff->data;
338 evinfo.rep.ptr = (xGenericReply*)rep->replyData;
339 evinfo.rep.size = rep->dataLenBytes - rep->padBytes;
340 evinfo.rep.isStart = rep->startOfReply;
342 if (stuff->reqType < EXTENSION_BASE)
343 snprintf (evinfo.rep.name, sizeof (evinfo.rep.name), "%s",
344 LookupRequestName (stuff->reqType, 0));
346 snprintf (evinfo.rep.name, sizeof (evinfo.rep.name), "%s",
347 LookupRequestName (stuff->reqType, stuff->data));
357 err = (xError *) rep->replyData;
361 evinfo.mask |= EVLOG_MASK_ERROR;
362 evinfo.err.errorCode = err->errorCode;
363 evinfo.err.resourceID = err->resourceID;
364 evinfo.err.minorCode = err->minorCode;
365 evinfo.err.majorCode = err->majorCode;
368 XDBG_NEVER_GET_HERE (MXDBG);
377 evinfo.mask |= EVLOG_MASK_EVENT;
379 snprintf (evinfo.evt.name, sizeof (evinfo.evt.name), "%s",
380 LookupEventName ((int)(ev->u.u.type)));
385 evinfo.time = GetTimeInMillis ();
387 /* get extension entry */
388 if (!EntryInit && !xDbgEvlogGetExtensionEntry (NULL))
393 if (!xDbgEvlogRuleValidate (&evinfo))
396 if (xev_trace_record_fd >= 0)
398 if (xDbgEvlogFillLog (&evinfo, EVLOG_PRINT_REPLY_DETAIL, NULL, NULL))
399 evtRecord (xev_trace_record_fd, &evinfo);
404 int size = sizeof (log);
406 if (xDbgEvlogFillLog (&evinfo, xev_trace_detail_level, log, &size))
407 evtPrintF (xev_trace_fd, &evinfo, log);
410 /* evatom initialize */
411 xDbgDistroyAtomList(&evinfo);
412 xDbgDistroyRegionList(&evinfo);
415 #if TIZEN_ENGINEER_MODE
417 _traceGetWindowName (ClientPtr client, Window window)
421 Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
424 static char winname[128];
427 rc = dixLookupWindow (&pWin, window, client, win_mode);
431 property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
434 rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
435 if (rc == Success && pProp->data)
437 datalen = (pProp->size>127) ?127:pProp->size;
438 strncpy (winname, pProp->data, datalen);
439 winname[datalen] = 0;
452 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
454 if (xev_trace_on == FALSE)
457 evtPrint (FLUSH, NULL, NULL, NULL);
461 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
463 if (xev_trace_on == FALSE)
466 ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
468 evtPrint (REPLY, pri->client, NULL, pri);
472 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
474 EventInfoRec *pei = (EventInfoRec*)calldata;
476 ModuleClientInfo *info;
477 int ev; /* event index */
478 static int xi2_opcode = -1;
481 #if TIZEN_ENGINEER_MODE
482 static char* ename[]=
491 XDBG_RETURN_IF_FAIL (pei != NULL);
493 pClient = pei->client;
494 XDBG_RETURN_IF_FAIL (pClient != NULL);
497 XDBG_RETURN_IF_FAIL (pev != NULL);
499 info = GetClientInfo (pClient);
500 XDBG_RETURN_IF_FAIL (info != NULL);
502 for (ev=0; ev < pei->count; ev++, pev++)
504 int type = pev->u.u.type & 0177;
506 if (type < LASTEvent)
512 XDBG_SECURE (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
513 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
514 , info->command, info->pid
515 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
516 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
517 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
522 XDBG_SECURE (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
523 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
524 , info->command, info->pid
525 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
526 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
527 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
530 if(!xi2_opcode) break;
533 ExtensionEntry *pExt = CheckExtension("XInputExtension");
534 if(!pExt) xi2_opcode = 0;
535 else xi2_opcode = pExt->base;
538 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
540 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
541 if(xidev->deviceid==2) break;
542 if(xidev->evtype==XI_ButtonPress)
543 XDBG_TRACE (MXDBG, "XI_ButtonPress(%d) device(%d), event win(0x%x), child(0x%x), root(%.f,%.f), win(%.f, %.f)\n", XI_ButtonPress, xidev->deviceid, xidev->event, xidev->child, FP1616toDBL(xidev->root_x), FP1616toDBL(xidev->root_y), FP1616toDBL(xidev->event_x), FP1616toDBL(xidev->event_y));
544 else if(xidev->evtype==XI_ButtonRelease)
545 XDBG_TRACE (MXDBG, "XI_ButtonRelease(%d) device(%d), event win(0x%x), child(0x%x), root(%.f,%.f), win(%.f, %.f)\n", XI_ButtonRelease, xidev->deviceid, xidev->event, xidev->child, FP1616toDBL(xidev->root_x), FP1616toDBL(xidev->root_y), FP1616toDBL(xidev->event_x), FP1616toDBL(xidev->event_y));
546 else if(xidev->evtype==XI_Motion)
547 XDBG_TRACE (MXDBG, "XI_Motion(%d) device(%d), event win(0x%x), child(0x%x), root(%.f,%.f), win(%.f, %.f)\n", XI_Motion, xidev->deviceid, xidev->event, xidev->child, FP1616toDBL(xidev->root_x), FP1616toDBL(xidev->root_y), FP1616toDBL(xidev->event_x), FP1616toDBL(xidev->event_y));
554 if (type != X_Error && xev_trace_on)
555 evtPrint (EVENT, pClient, pev, NULL);
556 else if (type == X_Error && xev_trace_on)
557 evtPrint (ERROR, pClient, pev, NULL);
562 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
564 if (xev_trace_on == FALSE)
567 XaceCoreDispatchRec *rec = calldata;
569 XDBG_RETURN_IF_FAIL (rec != NULL);
571 evtPrint (REQUEST, rec->client, NULL, NULL);
575 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
577 if (xev_trace_on == FALSE)
580 XaceExtAccessRec *rec = calldata;
582 XDBG_RETURN_IF_FAIL (rec != NULL);
584 evtPrint (REQUEST, rec->client, NULL, NULL);
588 _traceAuditEndEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
594 _traceProperty (CallbackListPtr *pcbl, pointer unused, pointer calldata)
596 XacePropertyAccessRec *rec = calldata;
597 ModuleClientInfo *info = GetClientInfo (rec->client);
598 PropertyPtr pProp = *rec->ppProp;
599 Atom name = pProp->propertyName;
601 /* Don't care about the new content check */
602 if (rec->client == serverClient || rec->access_mode & DixPostAccess)
605 if (name == atom_client_pid && (rec->access_mode & DixWriteAccess))
607 XDBG_WARNING (MXDBG, "Invalid access X_CLINET_PID pid:%d, uid:%d\n", info->pid, info->uid);
608 rec->status = BadAccess;
612 rec->status = Success;
617 _traceResource (CallbackListPtr *pcbl, pointer unused, pointer calldata)
619 XaceResourceAccessRec *rec = calldata;
620 Mask access_mode = rec->access_mode;
621 ModuleClientInfo *info = GetClientInfo (rec->client);
623 /* Perform the background none check on windows */
624 if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW)
626 WindowPtr pWin = (WindowPtr) rec->res;
630 rc = dixChangeWindowProperty (serverClient,
631 pWin, atom_client_pid, XA_CARDINAL, 32,
632 PropModeReplace, 1, &pid, FALSE);
634 XDBG_ERROR (MXDBG, "failed : set X_CLIENT_PID to %d.\n", pid);
639 _traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata)
641 XaceReceiveAccessRec *rec = calldata;
643 if (rec->events->u.u.type != VisibilityNotify)
646 rec->status = BadAccess;
650 xDbgModuleEvlogInstallHooks (XDbgModule *pMod)
654 ret &= AddCallback (&EventCallback, _traceEvent, NULL);
655 ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
656 ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
658 /*Disable Visibility Event*/
659 ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
661 if (atom_client_pid == None)
662 atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
663 if (atom_rotate == None)
664 atom_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", 12, TRUE);
668 XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
676 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
678 DeleteCallback (&EventCallback, _traceEvent, NULL);
679 XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
680 XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
684 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
688 on = (on)?TRUE:FALSE;
689 if (xev_trace_on == on)
699 for (i=1 ; i< currentMaxClients ; i++)
702 ModuleClientInfo *info;
704 pClient = clients[i];
708 info = GetClientInfo (pClient);
712 if (strlen (info->command) > 0 && strstr (client_name, info->command))
716 if (xev_trace_fd >= 0)
717 close (xev_trace_fd);
719 snprintf (fd_name, 256, "/proc/%d/fd/1", info->pid);
720 xev_trace_fd = open (fd_name, O_RDWR);
721 if (xev_trace_fd < 0)
722 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
726 ret &= AddCallback (&FlushCallback, _traceFlush, NULL);
727 ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
728 ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
729 ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
730 ret &= XaceRegisterCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
734 XDBG_REPLY ("failed: register one or more callbacks.\n");
740 DeleteCallback (&FlushCallback, _traceFlush, NULL);
741 DeleteCallback (&ReplyCallback, _traceAReply, NULL);
742 XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
743 XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
744 XaceDeleteCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
751 xDbgModuleEvlogDetail (XDbgModule *pMod, int level, char *reply, int *len)
753 xev_trace_detail_level = level;
757 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
759 return xDbgEvlogRuleSet (argc, argv, reply, len);
763 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
765 char fd_name[XDBG_PATH_MAX];
768 if (!path || strlen (path) <= 0)
771 if (xev_trace_record_fd >= 0)
773 close (xev_trace_record_fd);
774 xev_trace_record_fd = -1;
779 free (pMod->log_path);
780 pMod->log_path = NULL;
783 if (!strcmp (path, "console"))
789 if (xev_trace_fd >= 0)
790 close (xev_trace_fd);
792 snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
794 xev_trace_fd = open (fd_name, O_RDWR);
795 if (xev_trace_fd < 0)
796 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
798 pMod->evlog_path = strdup (fd_name);
805 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
809 snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", pMod->cwd, path);
811 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
814 pMod->evlog_path = strdup (fd_name);
816 fd_check = open (fd_name, O_RDONLY);
822 xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
823 if (xev_trace_record_fd < 0)
825 XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, strerror(errno));