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,};
183 if (xev_trace_on == FALSE)
192 ModuleClientInfo *info = GetClientInfo (client);
193 XDBG_RETURN_IF_FAIL (info != NULL);
195 evinfo.mask |= EVLOG_MASK_CLIENT;
196 evinfo.client.index = info->index;
197 evinfo.client.pid = info->pid;
198 evinfo.client.gid = info->gid;
199 evinfo.client.uid = info->uid;
200 strncpy (evinfo.client.command, info->command, strlen (info->command));
207 evinfo.mask |= EVLOG_MASK_REQUEST;
208 evinfo.req.id = stuff->reqType;
209 evinfo.req.length = client->req_len;
210 evinfo.req.ptr = client->requestBuffer;
212 if (stuff->reqType < EXTENSION_BASE)
213 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
214 LookupRequestName (stuff->reqType, 0));
216 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
217 LookupRequestName (stuff->reqType, stuff->data));
224 XDBG_RETURN_IF_FAIL (type == EVENT);
226 evinfo.mask |= EVLOG_MASK_EVENT;
228 snprintf (evinfo.evt.name, sizeof (evinfo.evt.name), "%s",
229 LookupEventName ((int)(ev->u.u.type)));
233 evinfo.time = GetTimeInMillis ();
235 if (!xDbgEvlogRuleValidate (&evinfo))
238 if (xev_trace_record_fd >= 0)
239 evtRecord (xev_trace_record_fd, &evinfo);
241 evtPrintF (xev_trace_fd, &evinfo);
245 _traceGetWindowName (ClientPtr client, Window window)
249 Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
252 static char winname[128];
255 rc = dixLookupWindow (&pWin, window, client, win_mode);
259 property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
262 rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
263 if (rc == Success && pProp->data)
265 datalen = (pProp->size>127) ?127:pProp->size;
266 strncpy (winname, pProp->data, datalen);
267 winname[datalen] = 0;
279 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
281 evtPrint (FLUSH, NULL, NULL);
285 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
287 ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
289 evtPrint (REPLY, pri->client, NULL);
293 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
295 EventInfoRec *pei = (EventInfoRec*)calldata;
297 ModuleClientInfo *info;
298 int ev; /* event index */
299 static int xi2_opcode = -1;
301 static char* ename[]=
309 XDBG_RETURN_IF_FAIL (pei != NULL);
311 pClient = pei->client;
312 XDBG_RETURN_IF_FAIL (pClient != NULL);
315 XDBG_RETURN_IF_FAIL (pev != NULL);
317 info = GetClientInfo (pClient);
318 XDBG_RETURN_IF_FAIL (info != NULL);
320 for (ev=0; ev < pei->count; ev++, pev++)
322 int type = pev->u.u.type & 0177;
324 if (type < LASTEvent)
330 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
331 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
332 , info->command, info->pid
333 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
334 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
335 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
340 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
341 , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
342 , info->command, info->pid
343 , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
344 , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
345 , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
348 if(!xi2_opcode) break;
351 ExtensionEntry *pExt = CheckExtension("XInputExtension");
352 if(!pExt) xi2_opcode = 0;
353 else xi2_opcode = pExt->base;
356 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
358 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
359 if(xidev->deviceid==2) break;
360 if(xidev->evtype==XI_ButtonPress)
361 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));
362 else if(xidev->evtype==XI_ButtonRelease)
363 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));
364 else if(xidev->evtype==XI_Motion)
365 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));
372 evtPrint (EVENT, pClient, pev);
377 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
379 XaceCoreDispatchRec *rec = calldata;
381 XDBG_RETURN_IF_FAIL (rec != NULL);
383 evtPrint (REQUEST, rec->client, NULL);
387 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
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 &= AddCallback (&FlushCallback, _traceFlush, NULL);
459 ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
460 ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
461 ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
463 /*Disable Visibility Event*/
464 ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
466 if (atom_client_pid == None)
467 atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
468 if (atom_rotate == None)
469 atom_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", 12, TRUE);
473 XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
477 if (pMod && pMod->evlog_path)
478 xDbgModuleEvlogSetEvlogPath (pMod, -1, pMod->evlog_path, NULL, NULL);
484 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
486 DeleteCallback (&EventCallback, _traceEvent, NULL);
487 DeleteCallback (&FlushCallback, _traceFlush, NULL);
488 DeleteCallback (&ReplyCallback, _traceAReply, NULL);
489 XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
490 XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
494 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
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));
533 ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
534 ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
538 XDBG_REPLY ("failed: register one or more callbacks.\n");
544 XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
545 XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
552 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
554 return xDbgEvlogRuleSet (argc, argv, reply, len);
558 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
560 char fd_name[XDBG_PATH_MAX];
561 char *temp[3] = {"/", "./", "../"};
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));
596 for (i = 0; i < sizeof (temp) / sizeof (char*); i++)
597 if (path == strstr (path, temp[i]))
605 XDBG_REPLY ("failed: invalid path(%s)\n", path);
610 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
614 if (getcwd (cwd, sizeof (cwd)))
615 snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", cwd, path);
617 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
620 xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
621 if (xev_trace_record_fd < 0)
623 XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, strerror(errno));