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)
83 XDBG_RETURN_IF_FAIL (evinfo != NULL);
85 write_len = sizeof (int) +
90 if (evinfo->mask & EVLOG_MASK_CLIENT)
91 write_len += sizeof (EvlogClient);
93 if (evinfo->mask & EVLOG_MASK_REQUEST)
94 write_len += (sizeof (EvlogRequest) + (evinfo->req.length * 4));
96 if (evinfo->mask & EVLOG_MASK_EVENT)
97 write_len += (sizeof (EvlogEvent) + sizeof (xEvent));
99 if (write (fd, &write_len, sizeof(int)) == -1)
101 XDBG_ERROR (MXDBG, "failed: write write_len\n");
104 if (write (fd, &evinfo->time, sizeof(CARD32)) == -1)
106 XDBG_ERROR (MXDBG, "failed: write msec\n");
109 if (write (fd, &evinfo->type, sizeof(EvlogType)) == -1)
111 XDBG_ERROR (MXDBG, "failed: write type\n");
114 if (write (fd, &evinfo->mask, sizeof(int)) == -1)
116 XDBG_ERROR (MXDBG, "failed: write mask\n");
120 if (evinfo->mask & EVLOG_MASK_CLIENT)
121 if (write (fd, &evinfo->client, sizeof (EvlogClient)) == -1)
123 XDBG_ERROR (MXDBG, "failed: write client\n");
127 if (evinfo->mask & EVLOG_MASK_REQUEST)
129 if (write (fd, &evinfo->req, sizeof (EvlogRequest)) == -1)
131 XDBG_ERROR (MXDBG, "failed: write request\n");
134 if (write (fd, evinfo->req.ptr, (evinfo->req.length * 4)) == -1)
136 XDBG_ERROR (MXDBG, "failed: write request\n");
140 if (evinfo->mask & EVLOG_MASK_EVENT)
142 if (write (fd, &evinfo->evt, sizeof (EvlogEvent)) == -1)
144 XDBG_ERROR (MXDBG, "failed: write event\n");
147 if (write (fd, evinfo->evt.ptr, sizeof (xEvent)) == -1)
149 XDBG_ERROR (MXDBG, "failed: write event\n");
155 static void evtPrintF (int fd, EvlogInfo *evinfo)
158 int size = sizeof (log);
160 xDbgEvlogFillLog (evinfo, TRUE, log, &size);
165 dprintf (fd, "%s", log);
168 static void evtPrint (EvlogType type, ClientPtr client, xEvent *ev)
170 EvlogInfo evinfo = {0,};
178 ModuleClientInfo *info = GetClientInfo (client);
179 XDBG_RETURN_IF_FAIL (info != NULL);
181 evinfo.mask |= EVLOG_MASK_CLIENT;
182 evinfo.client.index = info->index;
183 evinfo.client.pid = info->pid;
184 evinfo.client.gid = info->gid;
185 evinfo.client.uid = info->uid;
186 strncpy (evinfo.client.command, info->command, strlen (info->command));
193 evinfo.mask |= EVLOG_MASK_REQUEST;
194 evinfo.req.id = stuff->reqType;
195 evinfo.req.length = client->req_len;
196 evinfo.req.ptr = client->requestBuffer;
198 if (stuff->reqType < EXTENSION_BASE)
199 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
200 LookupRequestName (stuff->reqType, 0));
202 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
203 LookupRequestName (stuff->reqType, stuff->data));
210 XDBG_RETURN_IF_FAIL (type == EVENT);
212 evinfo.mask |= EVLOG_MASK_EVENT;
214 snprintf (evinfo.evt.name, sizeof (evinfo.evt.name), "%s",
215 LookupEventName ((int)(ev->u.u.type)));
219 evinfo.time = GetTimeInMillis ();
221 if (!xDbgEvlogRuleValidate (&evinfo))
224 if (xev_trace_record_fd >= 0)
225 evtRecord (xev_trace_record_fd, &evinfo);
227 evtPrintF (xev_trace_fd, &evinfo);
232 _traceGetWindowName (ClientPtr client, Window window)
236 Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
239 static char winname[128];
242 rc = dixLookupWindow (&pWin, window, client, win_mode);
246 property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
249 rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
250 if (rc == Success && pProp->data)
252 datalen = (pProp->size>127) ?127:pProp->size;
253 strncpy (winname, pProp->data, datalen);
254 winname[datalen] = 0;
266 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
268 if (xev_trace_on == FALSE)
271 evtPrint (FLUSH, NULL, NULL);
275 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
277 if (xev_trace_on == FALSE)
280 ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
282 evtPrint (REPLY, pri->client, NULL);
286 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
288 EventInfoRec *pei = (EventInfoRec*)calldata;
290 ModuleClientInfo *info;
291 int ev; /* event index */
292 static int xi2_opcode = -1;
294 static char* ename[]=
302 XDBG_RETURN_IF_FAIL (pei != NULL);
304 pClient = pei->client;
305 XDBG_RETURN_IF_FAIL (pClient != NULL);
308 XDBG_RETURN_IF_FAIL (pev != NULL);
310 info = GetClientInfo (pClient);
311 XDBG_RETURN_IF_FAIL (info != NULL);
313 for (ev=0; ev < pei->count; ev++, pev++)
315 int type = pev->u.u.type & 0177;
317 if (type < LASTEvent)
323 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
324 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
325 , info->command, info->pid
326 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
327 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
328 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
333 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
334 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
335 , info->command, info->pid
336 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
337 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
338 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
341 if(!xi2_opcode) break;
344 ExtensionEntry *pExt = CheckExtension("XInputExtension");
345 if(!pExt) xi2_opcode = 0;
346 else xi2_opcode = pExt->base;
349 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
351 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
352 if(xidev->deviceid==2) break;
353 if(xidev->evtype==XI_ButtonPress)
354 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));
355 else if(xidev->evtype==XI_ButtonRelease)
356 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));
357 else if(xidev->evtype==XI_Motion)
358 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));
366 evtPrint (EVENT, pClient, pev);
371 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
373 if (xev_trace_on == FALSE)
376 XaceCoreDispatchRec *rec = calldata;
378 XDBG_RETURN_IF_FAIL (rec != NULL);
380 evtPrint (REQUEST, rec->client, NULL);
384 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
386 if (xev_trace_on == FALSE)
389 XaceExtAccessRec *rec = calldata;
391 XDBG_RETURN_IF_FAIL (rec != NULL);
393 evtPrint (REQUEST, rec->client, NULL);
397 _traceProperty (CallbackListPtr *pcbl, pointer unused, pointer calldata)
399 XacePropertyAccessRec *rec = calldata;
400 ModuleClientInfo *info = GetClientInfo (rec->client);
401 PropertyPtr pProp = *rec->ppProp;
402 Atom name = pProp->propertyName;
404 /* Don't care about the new content check */
405 if (rec->client == serverClient || rec->access_mode & DixPostAccess)
408 if (name == atom_client_pid && (rec->access_mode & DixWriteAccess))
410 XDBG_WARNING (MXDBG, "Invalid access X_CLINET_PID pid:%d, uid:%d\n", info->pid, info->uid);
411 rec->status = BadAccess;
415 rec->status = Success;
420 _traceResource (CallbackListPtr *pcbl, pointer unused, pointer calldata)
422 XaceResourceAccessRec *rec = calldata;
423 Mask access_mode = rec->access_mode;
424 ModuleClientInfo *info = GetClientInfo (rec->client);
426 /* Perform the background none check on windows */
427 if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW)
429 WindowPtr pWin = (WindowPtr) rec->res;
433 rc = dixChangeWindowProperty (serverClient,
434 pWin, atom_client_pid, XA_CARDINAL, 32,
435 PropModeReplace, 1, &pid, FALSE);
437 XDBG_ERROR (MXDBG, "failed : set X_CLIENT_PID to %d.\n", pid);
442 _traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata)
444 XaceReceiveAccessRec *rec = calldata;
446 if (rec->events->u.u.type != VisibilityNotify)
449 rec->status = BadAccess;
453 xDbgModuleEvlogInstallHooks (XDbgModule *pMod)
457 ret &= AddCallback (&EventCallback, _traceEvent, NULL);
458 ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
459 ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
461 /*Disable Visibility Event*/
462 ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
464 if (atom_client_pid == None)
465 atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
466 if (atom_rotate == None)
467 atom_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", 12, TRUE);
471 XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
475 if (pMod && pMod->evlog_path)
476 xDbgModuleEvlogSetEvlogPath (pMod, -1, pMod->evlog_path, NULL, NULL);
482 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
484 DeleteCallback (&EventCallback, _traceEvent, NULL);
485 XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
486 XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
490 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
494 on = (on)?TRUE:FALSE;
495 if (xev_trace_on == on)
505 for (i=1 ; i< currentMaxClients ; i++)
508 ModuleClientInfo *info;
510 pClient = clients[i];
514 info = GetClientInfo (pClient);
518 if (strlen (info->command) > 0 && strstr (client_name, info->command))
522 if (xev_trace_fd >= 0)
523 close (xev_trace_fd);
525 snprintf (fd_name, 256, "/proc/%d/fd/1", info->pid);
526 xev_trace_fd = open (fd_name, O_RDWR);
527 if (xev_trace_fd < 0)
528 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
532 ret &= AddCallback (&FlushCallback, _traceFlush, NULL);
533 ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
534 ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
535 ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
539 XDBG_REPLY ("failed: register one or more callbacks.\n");
545 DeleteCallback (&FlushCallback, _traceFlush, NULL);
546 DeleteCallback (&ReplyCallback, _traceAReply, NULL);
547 XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
548 XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
555 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
557 return xDbgEvlogRuleSet (argc, argv, reply, len);
561 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
563 char fd_name[XDBG_PATH_MAX];
565 if (!path || strlen (path) <= 0)
567 XDBG_REPLY ("failed: invalid path\n");
571 if (xev_trace_record_fd >= 0)
573 close (xev_trace_record_fd);
574 xev_trace_record_fd = -1;
577 if (!strcmp (path, "console"))
583 if (xev_trace_fd >= 0)
584 close (xev_trace_fd);
586 snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
588 xev_trace_fd = open (fd_name, O_RDWR);
589 if (xev_trace_fd < 0)
590 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
597 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
601 if (getcwd (cwd, sizeof (cwd)))
602 snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", cwd, path);
604 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
607 xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
608 if (xev_trace_record_fd < 0)
610 XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, strerror(errno));