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 static Bool xev_trace_on = FALSE;
73 static int xev_trace_fd = -1;
74 static int xev_trace_record_fd = -1;
75 static Atom atom_rotate = None;
76 static Atom atom_client_pid = None;
79 static void evtRecord (int fd, EvlogInfo *evinfo)
81 extern ExtensionInfo Evlog_extensions[];
82 extern int Extensions_size;
86 XDBG_RETURN_IF_FAIL (fd >= 0)
87 XDBG_RETURN_IF_FAIL (evinfo != NULL);
89 write_len = sizeof (int) +
94 if (evinfo->mask & EVLOG_MASK_CLIENT)
95 write_len += sizeof (EvlogClient);
97 if (evinfo->mask & EVLOG_MASK_REQUEST)
98 write_len += (sizeof (EvlogRequest) + (evinfo->req.length * 4));
100 if (evinfo->mask & EVLOG_MASK_EVENT)
101 write_len += (sizeof (EvlogEvent) + evinfo->evt.size);
103 if (evinfo->mask & EVLOG_MASK_REPLY)
104 write_len += (sizeof (EvlogReply) + evinfo->rep.size);
106 if (evinfo->mask & EVLOG_MASK_ERROR)
107 write_len += (sizeof (EvlogError));
109 if (evinfo->mask & EVLOG_MASK_ATOM)
110 write_len += (sizeof (int) +
111 (sizeof (EvlogAtomTable) * evinfo->evatom.size));
113 if (evinfo->mask & EVLOG_MASK_REGION)
114 write_len += (sizeof (int) +
115 (sizeof (EvlogRegionTable) * evinfo->evregion.size));
118 write_len += (sizeof (int) +
119 ((sizeof (int) * 3) * Extensions_size));
121 if (write (fd, &write_len, sizeof(int)) == -1)
123 XDBG_ERROR (MXDBG, "failed: write write_len\n");
129 if (write (fd, &Extensions_size, sizeof(int)) == -1)
131 XDBG_ERROR (MXDBG, "failed: write Extensions_size\n");
135 for (i = 0 ; i < Extensions_size ; i++)
137 if (write (fd, &Evlog_extensions[i].opcode, sizeof(int)) == -1)
139 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] opcode\n", i);
142 if (write (fd, &Evlog_extensions[i].evt_base, sizeof(int)) == -1)
144 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] evt_base\n", i);
147 if (write (fd, &Evlog_extensions[i].err_base, sizeof(int)) == -1)
149 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] err_base\n", i);
157 if (write (fd, &evinfo->time, sizeof(CARD32)) == -1)
159 XDBG_ERROR (MXDBG, "failed: write msec\n");
162 if (write (fd, &evinfo->type, sizeof(EvlogType)) == -1)
164 XDBG_ERROR (MXDBG, "failed: write type\n");
167 if (write (fd, &evinfo->mask, sizeof(int)) == -1)
169 XDBG_ERROR (MXDBG, "failed: write mask\n");
173 if (evinfo->mask & EVLOG_MASK_CLIENT)
174 if (write (fd, &evinfo->client, sizeof (EvlogClient)) == -1)
176 XDBG_ERROR (MXDBG, "failed: write client\n");
180 if (evinfo->mask & EVLOG_MASK_REQUEST)
182 if (write (fd, &evinfo->req, sizeof (EvlogRequest)) == -1)
184 XDBG_ERROR (MXDBG, "failed: write request\n");
187 if (write (fd, evinfo->req.ptr, (evinfo->req.length * 4)) == -1)
189 XDBG_ERROR (MXDBG, "failed: write request\n");
193 if (evinfo->mask & EVLOG_MASK_EVENT)
195 if (write (fd, &evinfo->evt, sizeof (EvlogEvent)) == -1)
197 XDBG_ERROR (MXDBG, "failed: write event\n");
201 XDBG_WARNING_IF_FAIL (evinfo->evt.size > 0);
202 if (write (fd, evinfo->evt.ptr, evinfo->evt.size) == -1)
204 XDBG_ERROR (MXDBG, "failed: write event\n");
208 if (evinfo->mask & EVLOG_MASK_REPLY)
210 if (write (fd, &evinfo->rep, sizeof (EvlogReply)) == -1)
212 XDBG_ERROR (MXDBG, "failed: write reply\n");
216 XDBG_WARNING_IF_FAIL (evinfo->rep.size > 0);
217 if (write (fd, evinfo->rep.ptr, evinfo->rep.size) == -1)
219 XDBG_ERROR (MXDBG, "failed: write reply\n");
223 if (evinfo->mask & EVLOG_MASK_ERROR)
225 if (write (fd, &evinfo->err, sizeof (EvlogError)) == -1)
227 XDBG_ERROR (MXDBG, "failed: write reply\n");
232 if (evinfo->mask & EVLOG_MASK_ATOM)
234 EvlogAtomTable *table;
236 if (write (fd, &evinfo->evatom.size, sizeof (int)) == -1)
238 XDBG_ERROR (MXDBG, "failed: write atom size\n");
241 xorg_list_for_each_entry(table, &evinfo->evatom.list, link)
242 if (write (fd, table, sizeof (EvlogAtomTable)) == -1)
244 XDBG_ERROR (MXDBG, "failed: write atom table\n");
249 if (evinfo->mask & EVLOG_MASK_REGION)
251 EvlogRegionTable *table;
253 if (write (fd, &evinfo->evregion.size, sizeof (int)) == -1)
255 XDBG_ERROR (MXDBG, "failed: write region size\n");
258 xorg_list_for_each_entry(table, &evinfo->evregion.list, link)
259 if (write (fd, table, sizeof (EvlogRegionTable)) == -1)
261 XDBG_ERROR (MXDBG, "failed: write region table\n");
267 static void evtPrintF (int fd, EvlogInfo *evinfo, char *log)
272 dprintf (fd, "%s", log);
275 static void evtPrint (EvlogType type, ClientPtr client, xEvent *ev, ReplyInfoRec *rep)
277 EvlogInfo evinfo = {0,};
278 static int EntryInit = 0;
286 ModuleClientInfo *info = GetClientInfo (client);
287 XDBG_RETURN_IF_FAIL (info != NULL);
289 evinfo.mask |= EVLOG_MASK_CLIENT;
290 evinfo.client.index = info->index;
291 evinfo.client.pid = info->pid;
292 evinfo.client.gid = info->gid;
293 evinfo.client.uid = info->uid;
294 strncpy (evinfo.client.command, info->command, strlen (info->command));
295 evinfo.client.pClient = (void*)client;
304 evinfo.mask |= EVLOG_MASK_REQUEST;
305 evinfo.req.id = stuff->reqType;
306 evinfo.req.length = client->req_len;
307 evinfo.req.ptr = client->requestBuffer;
309 if (client->requestVector == InitialVector && stuff->reqType == 1)
310 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s", conn[0]);
311 else if (client->requestVector == InitialVector && stuff->reqType == 2)
312 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s", conn[1]);
315 if (stuff->reqType < EXTENSION_BASE)
316 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
317 LookupRequestName (stuff->reqType, 0));
319 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
320 LookupRequestName (stuff->reqType, stuff->data));
329 evinfo.mask |= EVLOG_MASK_REPLY;
330 evinfo.rep.reqType = stuff->reqType;
331 evinfo.rep.reqData = stuff->data;
332 evinfo.rep.ptr = (xGenericReply*)rep->replyData;
333 evinfo.rep.size = rep->dataLenBytes - rep->padBytes;
334 evinfo.rep.isStart = rep->startOfReply;
336 if (stuff->reqType < EXTENSION_BASE)
337 snprintf (evinfo.rep.name, sizeof (evinfo.rep.name), "%s",
338 LookupRequestName (stuff->reqType, 0));
340 snprintf (evinfo.rep.name, sizeof (evinfo.rep.name), "%s",
341 LookupRequestName (stuff->reqType, stuff->data));
351 err = (xError *) rep->replyData;
353 evinfo.mask |= EVLOG_MASK_ERROR;
354 evinfo.err.errorCode = err->errorCode;
355 evinfo.err.resourceID = err->resourceID;
356 evinfo.err.minorCode = err->minorCode;
357 evinfo.err.majorCode = err->majorCode;
366 evinfo.mask |= EVLOG_MASK_EVENT;
368 snprintf (evinfo.evt.name, sizeof (evinfo.evt.name), "%s",
369 LookupEventName ((int)(ev->u.u.type)));
374 evinfo.time = GetTimeInMillis ();
376 /* get extension entry */
377 if (!EntryInit && !xDbgEvlogGetExtensionEntry (NULL))
382 if (!xDbgEvlogRuleValidate (&evinfo))
385 if (xev_trace_record_fd >= 0)
387 xDbgEvlogFillLog (&evinfo, TRUE, NULL, NULL);
388 evtRecord (xev_trace_record_fd, &evinfo);
393 int size = sizeof (log);
395 xDbgEvlogFillLog (&evinfo, TRUE, log, &size);
396 evtPrintF (xev_trace_fd, &evinfo, log);
399 /* evatom initialize */
400 xDbgDistroyAtomList(&evinfo);
401 xDbgDistroyRegionList(&evinfo);
405 _traceGetWindowName (ClientPtr client, Window window)
409 Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
412 static char winname[128];
415 rc = dixLookupWindow (&pWin, window, client, win_mode);
419 property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
422 rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
423 if (rc == Success && pProp->data)
425 datalen = (pProp->size>127) ?127:pProp->size;
426 strncpy (winname, pProp->data, datalen);
427 winname[datalen] = 0;
439 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
441 if (xev_trace_on == FALSE)
444 evtPrint (FLUSH, NULL, NULL, NULL);
448 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
450 if (xev_trace_on == FALSE)
453 ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
455 evtPrint (REPLY, pri->client, NULL, pri);
459 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
461 EventInfoRec *pei = (EventInfoRec*)calldata;
463 ModuleClientInfo *info;
464 int ev; /* event index */
465 static int xi2_opcode = -1;
467 static char* ename[]=
475 XDBG_RETURN_IF_FAIL (pei != NULL);
477 pClient = pei->client;
478 XDBG_RETURN_IF_FAIL (pClient != NULL);
481 XDBG_RETURN_IF_FAIL (pev != NULL);
483 info = GetClientInfo (pClient);
484 XDBG_RETURN_IF_FAIL (info != NULL);
486 for (ev=0; ev < pei->count; ev++, pev++)
488 int type = pev->u.u.type & 0177;
490 if (type < LASTEvent)
496 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
497 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
498 , info->command, info->pid
499 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
500 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
501 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
506 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
507 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
508 , info->command, info->pid
509 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
510 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
511 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
514 if(!xi2_opcode) break;
517 ExtensionEntry *pExt = CheckExtension("XInputExtension");
518 if(!pExt) xi2_opcode = 0;
519 else xi2_opcode = pExt->base;
522 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
524 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
525 if(xidev->deviceid==2) break;
526 if(xidev->evtype==XI_ButtonPress)
527 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));
528 else if(xidev->evtype==XI_ButtonRelease)
529 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));
530 else if(xidev->evtype==XI_Motion)
531 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));
538 if (type != X_Error && xev_trace_on)
539 evtPrint (EVENT, pClient, pev, NULL);
540 else if (type == X_Error && xev_trace_on)
541 evtPrint (ERROR, pClient, pev, NULL);
546 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
548 if (xev_trace_on == FALSE)
551 XaceCoreDispatchRec *rec = calldata;
553 XDBG_RETURN_IF_FAIL (rec != NULL);
555 evtPrint (REQUEST, rec->client, NULL, NULL);
559 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
561 if (xev_trace_on == FALSE)
564 XaceExtAccessRec *rec = calldata;
566 XDBG_RETURN_IF_FAIL (rec != NULL);
568 evtPrint (REQUEST, rec->client, NULL, NULL);
572 _traceAuditEndEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
578 _traceProperty (CallbackListPtr *pcbl, pointer unused, pointer calldata)
580 XacePropertyAccessRec *rec = calldata;
581 ModuleClientInfo *info = GetClientInfo (rec->client);
582 PropertyPtr pProp = *rec->ppProp;
583 Atom name = pProp->propertyName;
585 /* Don't care about the new content check */
586 if (rec->client == serverClient || rec->access_mode & DixPostAccess)
589 if (name == atom_client_pid && (rec->access_mode & DixWriteAccess))
591 XDBG_WARNING (MXDBG, "Invalid access X_CLINET_PID pid:%d, uid:%d\n", info->pid, info->uid);
592 rec->status = BadAccess;
596 rec->status = Success;
601 _traceResource (CallbackListPtr *pcbl, pointer unused, pointer calldata)
603 XaceResourceAccessRec *rec = calldata;
604 Mask access_mode = rec->access_mode;
605 ModuleClientInfo *info = GetClientInfo (rec->client);
607 /* Perform the background none check on windows */
608 if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW)
610 WindowPtr pWin = (WindowPtr) rec->res;
614 rc = dixChangeWindowProperty (serverClient,
615 pWin, atom_client_pid, XA_CARDINAL, 32,
616 PropModeReplace, 1, &pid, FALSE);
618 XDBG_ERROR (MXDBG, "failed : set X_CLIENT_PID to %d.\n", pid);
623 _traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata)
625 XaceReceiveAccessRec *rec = calldata;
627 if (rec->events->u.u.type != VisibilityNotify)
630 rec->status = BadAccess;
634 xDbgModuleEvlogInstallHooks (XDbgModule *pMod)
638 ret &= AddCallback (&EventCallback, _traceEvent, NULL);
639 ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
640 ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
642 /*Disable Visibility Event*/
643 ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
645 if (atom_client_pid == None)
646 atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
647 if (atom_rotate == None)
648 atom_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", 12, TRUE);
652 XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
656 if (pMod && pMod->evlog_path)
657 xDbgModuleEvlogSetEvlogPath (pMod, -1, pMod->evlog_path, NULL, NULL);
663 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
665 DeleteCallback (&EventCallback, _traceEvent, NULL);
666 XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
667 XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
671 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
675 on = (on)?TRUE:FALSE;
676 if (xev_trace_on == on)
686 for (i=1 ; i< currentMaxClients ; i++)
689 ModuleClientInfo *info;
691 pClient = clients[i];
695 info = GetClientInfo (pClient);
699 if (strlen (info->command) > 0 && strstr (client_name, info->command))
703 if (xev_trace_fd >= 0)
704 close (xev_trace_fd);
706 snprintf (fd_name, 256, "/proc/%d/fd/1", info->pid);
707 xev_trace_fd = open (fd_name, O_RDWR);
708 if (xev_trace_fd < 0)
709 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
713 ret &= AddCallback (&FlushCallback, _traceFlush, NULL);
714 ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
715 ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
716 ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
717 ret &= XaceRegisterCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
721 XDBG_REPLY ("failed: register one or more callbacks.\n");
727 DeleteCallback (&FlushCallback, _traceFlush, NULL);
728 DeleteCallback (&ReplyCallback, _traceAReply, NULL);
729 XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
730 XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
731 XaceDeleteCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
738 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
740 return xDbgEvlogRuleSet (argc, argv, reply, len);
744 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
746 char fd_name[XDBG_PATH_MAX];
749 if (!path || strlen (path) <= 0)
751 XDBG_REPLY ("failed: invalid path\n");
755 if (xev_trace_record_fd >= 0)
757 close (xev_trace_record_fd);
758 xev_trace_record_fd = -1;
761 if (!strcmp (path, "console"))
767 if (xev_trace_fd >= 0)
768 close (xev_trace_fd);
770 snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
772 xev_trace_fd = open (fd_name, O_RDWR);
773 if (xev_trace_fd < 0)
774 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
781 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
785 snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", pMod->cwd, path);
787 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
790 fd_check = open (fd_name, O_RDONLY);
796 xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
797 if (xev_trace_record_fd < 0)
799 XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, strerror(errno));