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;
78 static void evtRecord (int fd, EvlogInfo *evinfo)
82 XDBG_RETURN_IF_FAIL (fd >= 0)
88 write_len = sizeof (int) +
93 evinfo->mask |= EVLOG_MASK_CLIENT;
94 write_len += sizeof (EvlogClient);
96 if (evinfo->type == REQUEST)
98 evinfo->mask |= EVLOG_MASK_REQUEST;
99 write_len += sizeof (EvlogRequest) + sizeof (xReq);
101 else if (evinfo->type == EVENT)
103 evinfo->mask |= EVLOG_MASK_EVENT;
104 write_len += sizeof (EvlogEvent) + sizeof (xEvent);
108 if (write (xev_trace_record_fd, &write_len, sizeof(int)) == -1)
110 XDBG_ERROR (MXDBG, "failed: write write_len\n");
116 if (write (xev_trace_record_fd, &evinfo->time, sizeof(CARD32)) == -1)
118 XDBG_ERROR (MXDBG, "failed: write msec\n");
121 if (write (xev_trace_record_fd, &evinfo->type, sizeof(EvlogType)) == -1)
123 XDBG_ERROR (MXDBG, "failed: write type\n");
126 if (write (xev_trace_record_fd, &evinfo->mask, sizeof(int)) == -1)
128 XDBG_ERROR (MXDBG, "failed: write mask\n");
131 if (write (xev_trace_record_fd, &evinfo->client, sizeof (EvlogClient)) == -1)
133 XDBG_ERROR (MXDBG, "failed: write client\n");
137 if (evinfo->type == REQUEST)
139 if (write (xev_trace_record_fd, &evinfo->req, sizeof (EvlogRequest)) == -1)
141 XDBG_ERROR (MXDBG, "failed: write request\n");
144 if (write (xev_trace_record_fd, evinfo->req.ptr, sizeof (xReq)) == -1)
146 XDBG_ERROR (MXDBG, "failed: write request\n");
150 else if (evinfo->type == EVENT)
152 if (write (xev_trace_record_fd, &evinfo->evt, sizeof (EvlogEvent)) == -1)
154 XDBG_ERROR (MXDBG, "failed: write event\n");
157 if (write (xev_trace_record_fd, evinfo->evt.ptr, sizeof (xEvent)) == -1)
159 XDBG_ERROR (MXDBG, "failed: write event\n");
166 static void evtPrintF (int fd, EvlogInfo *evinfo)
169 int size = sizeof (log);
171 xDbgEvlogFillLog (evinfo, log, &size);
176 dprintf (fd, "%s", log);
179 static void evtPrint (EvlogType type, ClientPtr client, xEvent *ev)
181 EvlogInfo evinfo = {0,};
189 ModuleClientInfo *info = GetClientInfo (client);
190 XDBG_RETURN_IF_FAIL (info != NULL);
192 evinfo.mask |= EVLOG_MASK_CLIENT;
193 evinfo.client.index = info->index;
194 evinfo.client.pid = info->pid;
195 evinfo.client.gid = info->gid;
196 evinfo.client.uid = info->uid;
197 strncpy (evinfo.client.command, info->command, strlen (info->command));
204 evinfo.mask |= EVLOG_MASK_REQUEST;
205 evinfo.req.id = stuff->reqType;
206 evinfo.req.length = client->req_len;
207 evinfo.req.ptr = client->requestBuffer;
209 if (stuff->reqType < EXTENSION_BASE)
210 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
211 LookupRequestName (stuff->reqType, 0));
213 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
214 LookupRequestName (stuff->reqType, stuff->data));
221 XDBG_RETURN_IF_FAIL (type == EVENT);
223 evinfo.mask |= EVLOG_MASK_EVENT;
225 snprintf (evinfo.evt.name, sizeof (evinfo.evt.name), "%s",
226 LookupEventName ((int)(ev->u.u.type)));
230 evinfo.time = GetTimeInMillis ();
232 if (!xDbgEvlogRuleValidate (&evinfo))
235 if (xev_trace_record_fd >= 0)
236 evtRecord (xev_trace_record_fd, &evinfo);
238 evtPrintF (xev_trace_fd, &evinfo);
243 _traceGetWindowName (ClientPtr client, Window window)
247 Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
250 static char winname[128];
253 rc = dixLookupWindow (&pWin, window, client, win_mode);
257 property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
260 rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
261 if (rc == Success && pProp->data)
263 datalen = (pProp->size>127) ?127:pProp->size;
264 strncpy (winname, pProp->data, datalen);
265 winname[datalen] = 0;
277 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
279 if (xev_trace_on == FALSE)
282 evtPrint (FLUSH, NULL, NULL);
286 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
288 if (xev_trace_on == FALSE)
291 ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
293 evtPrint (REPLY, pri->client, NULL);
297 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
299 EventInfoRec *pei = (EventInfoRec*)calldata;
301 ModuleClientInfo *info;
302 int ev; /* event index */
303 static int xi2_opcode = -1;
305 static char* ename[]=
313 XDBG_RETURN_IF_FAIL (pei != NULL);
315 pClient = pei->client;
316 XDBG_RETURN_IF_FAIL (pClient != NULL);
319 XDBG_RETURN_IF_FAIL (pev != NULL);
321 info = GetClientInfo (pClient);
322 XDBG_RETURN_IF_FAIL (info != NULL);
324 for (ev=0; ev < pei->count; ev++, pev++)
326 int type = pev->u.u.type & 0177;
328 if (type < LASTEvent)
334 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
335 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
336 , info->command, info->pid
337 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
338 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
339 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
344 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
345 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
346 , info->command, info->pid
347 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
348 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
349 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
352 if(!xi2_opcode) break;
355 ExtensionEntry *pExt = CheckExtension("XInputExtension");
356 if(!pExt) xi2_opcode = 0;
357 else xi2_opcode = pExt->base;
360 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
362 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
363 if(xidev->deviceid==2) break;
364 if(xidev->evtype==XI_ButtonPress)
365 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));
366 else if(xidev->evtype==XI_ButtonRelease)
367 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));
368 else if(xidev->evtype==XI_Motion)
369 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));
377 evtPrint (EVENT, pClient, pev);
382 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
384 if (xev_trace_on == FALSE)
387 XaceCoreDispatchRec *rec = calldata;
389 XDBG_RETURN_IF_FAIL (rec != NULL);
391 evtPrint (REQUEST, rec->client, NULL);
395 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
397 if (xev_trace_on == FALSE)
400 XaceExtAccessRec *rec = calldata;
402 XDBG_RETURN_IF_FAIL (rec != NULL);
404 evtPrint (REQUEST, rec->client, NULL);
408 _traceProperty (CallbackListPtr *pcbl, pointer unused, pointer calldata)
410 XacePropertyAccessRec *rec = calldata;
411 ModuleClientInfo *info = GetClientInfo (rec->client);
412 PropertyPtr pProp = *rec->ppProp;
413 Atom name = pProp->propertyName;
415 /* Don't care about the new content check */
416 if (rec->client == serverClient || rec->access_mode & DixPostAccess)
419 if (name == atom_client_pid && (rec->access_mode & DixWriteAccess))
421 XDBG_WARNING (MXDBG, "Invalid access X_CLINET_PID pid:%d, uid:%d\n", info->pid, info->uid);
422 rec->status = BadAccess;
426 rec->status = Success;
431 _traceResource (CallbackListPtr *pcbl, pointer unused, pointer calldata)
433 XaceResourceAccessRec *rec = calldata;
434 Mask access_mode = rec->access_mode;
435 ModuleClientInfo *info = GetClientInfo (rec->client);
437 /* Perform the background none check on windows */
438 if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW)
440 WindowPtr pWin = (WindowPtr) rec->res;
444 rc = dixChangeWindowProperty (serverClient,
445 pWin, atom_client_pid, XA_CARDINAL, 32,
446 PropModeReplace, 1, &pid, FALSE);
448 XDBG_ERROR (MXDBG, "failed : set X_CLIENT_PID to %d.\n", pid);
453 _traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata)
455 XaceReceiveAccessRec *rec = calldata;
457 if (rec->events->u.u.type != VisibilityNotify)
460 rec->status = BadAccess;
464 xDbgModuleEvlogInstallHooks (XDbgModule *pMod)
468 ret &= AddCallback (&EventCallback, _traceEvent, NULL);
469 ret &= AddCallback (&FlushCallback, _traceFlush, NULL);
470 ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
471 ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
472 ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
474 /*Disable Visibility Event*/
475 ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
477 if (atom_client_pid == None)
478 atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
479 if (atom_rotate == None)
480 atom_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", 12, TRUE);
484 XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
488 if (pMod && pMod->evlog_path)
489 xDbgModuleEvlogSetEvlogPath (pMod, -1, pMod->evlog_path, NULL, NULL);
495 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
497 DeleteCallback (&EventCallback, _traceEvent, NULL);
498 DeleteCallback (&FlushCallback, _traceFlush, NULL);
499 DeleteCallback (&ReplyCallback, _traceAReply, NULL);
500 XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
501 XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
505 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
509 on = (on)?TRUE:FALSE;
510 if (xev_trace_on == on)
520 for (i=1 ; i< currentMaxClients ; i++)
523 ModuleClientInfo *info;
525 pClient = clients[i];
529 info = GetClientInfo (pClient);
533 if (strlen (info->command) > 0 && strstr (client_name, info->command))
537 if (xev_trace_fd >= 0)
538 close (xev_trace_fd);
540 snprintf (fd_name, 256, "/proc/%d/fd/1", info->pid);
541 xev_trace_fd = open (fd_name, O_RDWR);
542 if (xev_trace_fd < 0)
543 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
548 ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
549 ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
553 XDBG_REPLY ("failed: register one or more callbacks.\n");
559 XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
560 XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
567 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
569 return xDbgEvlogRuleSet (argc, argv, reply, len);
573 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
575 char fd_name[XDBG_PATH_MAX];
576 char *temp[3] = {"/", "./", "../"};
580 if (!path || strlen (path) <= 0)
582 XDBG_REPLY ("failed: invalid path\n");
586 if (xev_trace_record_fd >= 0)
588 close (xev_trace_record_fd);
589 xev_trace_record_fd = -1;
592 if (!strcmp (path, "console"))
598 if (xev_trace_fd >= 0)
599 close (xev_trace_fd);
601 snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
603 xev_trace_fd = open (fd_name, O_RDWR);
604 if (xev_trace_fd < 0)
605 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
611 for (i = 0; i < sizeof (temp) / sizeof (char*); i++)
612 if (path == strstr (path, temp[i]))
620 XDBG_REPLY ("failed: invalid path(%s)\n", path);
625 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
629 if (getcwd (cwd, sizeof (cwd)))
630 snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", cwd, path);
632 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
635 xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
636 if (xev_trace_record_fd < 0)
638 XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, strerror(errno));