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);
290 evinfo.mask |= EVLOG_MASK_CLIENT;
291 evinfo.client.index = info->index;
292 evinfo.client.pid = info->pid;
293 evinfo.client.gid = info->gid;
294 evinfo.client.uid = info->uid;
295 strncpy (evinfo.client.command, info->command, strlen (info->command));
296 evinfo.client.pClient = (void*)client;
305 evinfo.mask |= EVLOG_MASK_REQUEST;
306 evinfo.req.id = stuff->reqType;
307 evinfo.req.length = client->req_len;
308 evinfo.req.ptr = client->requestBuffer;
310 if (client->requestVector == InitialVector && stuff->reqType == 1)
311 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s", conn[0]);
312 else if (client->requestVector == InitialVector && stuff->reqType == 2)
313 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s", conn[1]);
316 if (stuff->reqType < EXTENSION_BASE)
317 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
318 LookupRequestName (stuff->reqType, 0));
320 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
321 LookupRequestName (stuff->reqType, stuff->data));
330 evinfo.mask |= EVLOG_MASK_REPLY;
331 evinfo.rep.reqType = stuff->reqType;
332 evinfo.rep.reqData = stuff->data;
333 evinfo.rep.ptr = (xGenericReply*)rep->replyData;
334 evinfo.rep.size = rep->dataLenBytes - rep->padBytes;
335 evinfo.rep.isStart = rep->startOfReply;
337 if (stuff->reqType < EXTENSION_BASE)
338 snprintf (evinfo.rep.name, sizeof (evinfo.rep.name), "%s",
339 LookupRequestName (stuff->reqType, 0));
341 snprintf (evinfo.rep.name, sizeof (evinfo.rep.name), "%s",
342 LookupRequestName (stuff->reqType, stuff->data));
352 err = (xError *) rep->replyData;
356 evinfo.mask |= EVLOG_MASK_ERROR;
357 evinfo.err.errorCode = err->errorCode;
358 evinfo.err.resourceID = err->resourceID;
359 evinfo.err.minorCode = err->minorCode;
360 evinfo.err.majorCode = err->majorCode;
363 XDBG_NEVER_GET_HERE (MXDBG);
372 evinfo.mask |= EVLOG_MASK_EVENT;
374 snprintf (evinfo.evt.name, sizeof (evinfo.evt.name), "%s",
375 LookupEventName ((int)(ev->u.u.type)));
380 evinfo.time = GetTimeInMillis ();
382 /* get extension entry */
383 if (!EntryInit && !xDbgEvlogGetExtensionEntry())
388 if (!xDbgEvlogRuleValidate (&evinfo))
391 if (xev_trace_record_fd >= 0)
393 if (xDbgEvlogFillLog (&evinfo, EVLOG_PRINT_REPLY_DETAIL, NULL, NULL))
394 evtRecord (xev_trace_record_fd, &evinfo);
399 int size = sizeof (log);
401 if (xDbgEvlogFillLog (&evinfo, xev_trace_detail_level, log, &size))
402 evtPrintF (xev_trace_fd, &evinfo, log);
405 /* evatom initialize */
406 xDbgDistroyAtomList(&evinfo);
407 xDbgDistroyRegionList(&evinfo);
412 _traceGetWindowName (ClientPtr client, Window window)
416 Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
419 static char winname[128];
422 rc = dixLookupWindow (&pWin, window, client, win_mode);
426 property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
429 rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
430 if (rc == Success && pProp->data)
432 datalen = (pProp->size>127) ?127:pProp->size;
433 strncpy (winname, pProp->data, datalen);
434 winname[datalen] = 0;
447 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
449 if (xev_trace_on == FALSE)
452 evtPrint (FLUSH, NULL, NULL, NULL);
456 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
458 if (xev_trace_on == FALSE)
461 ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
463 evtPrint (REPLY, pri->client, NULL, pri);
467 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
469 EventInfoRec *pei = (EventInfoRec*)calldata;
471 ModuleClientInfo *info;
472 int ev; /* event index */
473 static int xi2_opcode = -1;
477 static char* ename[]=
486 XDBG_RETURN_IF_FAIL (pei != NULL);
488 pClient = pei->client;
489 XDBG_RETURN_IF_FAIL (pClient != NULL);
492 XDBG_RETURN_IF_FAIL (pev != NULL);
494 info = GetClientInfo (pClient);
495 XDBG_RETURN_IF_FAIL (info != NULL);
497 for (ev=0; ev < pei->count; ev++, pev++)
499 int type = pev->u.u.type & 0177;
501 if (type < LASTEvent)
507 XDBG_SECURE (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%x) root(%d,%d) win(%d,%d)\n"
508 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
509 , info->command, info->pid
510 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), (unsigned int)pev->u.keyButtonPointer.event
511 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
512 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
517 XDBG_SECURE (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%x) root(%d,%d) win(%d,%d)\n"
518 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
519 , info->command, info->pid
520 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), (unsigned int)pev->u.keyButtonPointer.event
521 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
522 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
525 if(!xi2_opcode) break;
528 ExtensionEntry *pExt = CheckExtension("XInputExtension");
529 if(!pExt) xi2_opcode = 0;
530 else xi2_opcode = pExt->base;
533 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
535 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
536 if(xidev->deviceid==2) break;
537 if(xidev->evtype==XI_ButtonPress)
538 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));
539 else if(xidev->evtype==XI_ButtonRelease)
540 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));
541 else if(xidev->evtype==XI_Motion)
542 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));
549 if (type != X_Error && xev_trace_on)
550 evtPrint (EVENT, pClient, pev, NULL);
551 else if (type == X_Error && xev_trace_on)
552 evtPrint (ERROR, pClient, pev, NULL);
557 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
559 if (xev_trace_on == FALSE)
562 XaceCoreDispatchRec *rec = calldata;
564 XDBG_RETURN_IF_FAIL (rec != NULL);
566 evtPrint (REQUEST, rec->client, NULL, NULL);
570 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
572 if (xev_trace_on == FALSE)
575 XaceExtAccessRec *rec = calldata;
577 XDBG_RETURN_IF_FAIL (rec != NULL);
579 evtPrint (REQUEST, rec->client, NULL, NULL);
583 _traceAuditEndEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
589 _traceProperty (CallbackListPtr *pcbl, pointer unused, pointer calldata)
591 XacePropertyAccessRec *rec = calldata;
592 ModuleClientInfo *info = GetClientInfo (rec->client);
593 PropertyPtr pProp = *rec->ppProp;
594 Atom name = pProp->propertyName;
596 /* Don't care about the new content check */
597 if (rec->client == serverClient || rec->access_mode & DixPostAccess)
600 if (name == atom_client_pid && (rec->access_mode & DixWriteAccess))
602 XDBG_WARNING (MXDBG, "Invalid access X_CLINET_PID pid:%d, uid:%d\n", info->pid, info->uid);
603 rec->status = BadAccess;
607 rec->status = Success;
612 _traceResource (CallbackListPtr *pcbl, pointer unused, pointer calldata)
614 XaceResourceAccessRec *rec = calldata;
615 Mask access_mode = rec->access_mode;
616 ModuleClientInfo *info = GetClientInfo (rec->client);
618 /* Perform the background none check on windows */
619 if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW)
621 WindowPtr pWin = (WindowPtr) rec->res;
625 rc = dixChangeWindowProperty (serverClient,
626 pWin, atom_client_pid, XA_CARDINAL, 32,
627 PropModeReplace, 1, &pid, FALSE);
629 XDBG_ERROR (MXDBG, "failed : set X_CLIENT_PID to %d.\n", pid);
634 _traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata)
636 XaceReceiveAccessRec *rec = calldata;
638 if (rec->events->u.u.type != VisibilityNotify)
641 rec->status = BadAccess;
645 xDbgModuleEvlogInstallHooks (XDbgModule *pMod)
649 ret &= AddCallback (&EventCallback, _traceEvent, NULL);
650 ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
651 ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
653 /*Disable Visibility Event*/
654 ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
656 if (atom_client_pid == None)
657 atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
658 if (atom_rotate == None)
659 atom_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", 12, TRUE);
663 XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
667 if (pMod && pMod->evlog_path)
668 xDbgModuleEvlogSetEvlogPath (pMod, -1, pMod->evlog_path, NULL, NULL);
674 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
676 DeleteCallback (&EventCallback, _traceEvent, NULL);
677 XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
678 XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
682 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
686 on = (on)?TRUE:FALSE;
687 if (xev_trace_on == on)
697 for (i=1 ; i< currentMaxClients ; i++)
700 ModuleClientInfo *info;
702 pClient = clients[i];
706 info = GetClientInfo (pClient);
710 if (strlen (info->command) > 0 && strstr (client_name, info->command))
714 if (xev_trace_fd >= 0)
715 close (xev_trace_fd);
717 snprintf (fd_name, 256, "/proc/%d/fd/1", info->pid);
718 xev_trace_fd = open (fd_name, O_RDWR);
719 if (xev_trace_fd < 0)
720 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
724 ret &= AddCallback (&FlushCallback, _traceFlush, NULL);
725 ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
726 ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
727 ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
728 ret &= XaceRegisterCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
732 XDBG_REPLY ("failed: register one or more callbacks.\n");
738 DeleteCallback (&FlushCallback, _traceFlush, NULL);
739 DeleteCallback (&ReplyCallback, _traceAReply, NULL);
740 XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
741 XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
742 XaceDeleteCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
749 xDbgModuleEvlogDetail (XDbgModule *pMod, int level, char *reply, int *len)
751 xev_trace_detail_level = level;
755 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
757 return xDbgEvlogRuleSet (argc, argv, reply, len);
761 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
763 char fd_name[XDBG_PATH_MAX];
766 if (!path || strlen (path) <= 0)
768 XDBG_REPLY ("failed: invalid path\n");
772 if (xev_trace_record_fd >= 0)
774 close (xev_trace_record_fd);
775 xev_trace_record_fd = -1;
778 if (!strcmp (path, "console"))
784 if (xev_trace_fd >= 0)
785 close (xev_trace_fd);
787 snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
789 xev_trace_fd = open (fd_name, O_RDWR);
790 if (xev_trace_fd < 0)
791 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
798 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
802 snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", pMod->cwd, path);
804 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
807 fd_check = open (fd_name, O_RDONLY);
813 xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
814 if (xev_trace_record_fd < 0)
816 XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, strerror(errno));