nspluginwrapper/utils/xtrace.c

493 lines
16 KiB
C

#define _GNU_SOURCE 1 /* RTLD_NEXT */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <unistd.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
static int g_debug_level = 1;
static FILE *g_log_file = NULL;
void npw_printf(const char *format, ...)
{
#if 0
if (g_debug_level < 0) {
g_debug_level = 0;
const char *debug_str = getenv("NPW_DEBUG");
if (debug_str) {
errno = 0;
long v = strtol(debug_str, NULL, 10);
if ((v != LONG_MIN && v != LONG_MAX) || errno != ERANGE)
g_debug_level = v;
}
}
if (g_log_file == NULL) {
const char *log_file = getenv("NPW_LOG");
if (log_file)
g_log_file = fopen(log_file, "w");
if (log_file == NULL)
g_log_file = stderr;
}
#else
g_log_file = stderr;
#endif
if (g_debug_level > 0) {
va_list args;
va_start(args, format);
vfprintf(g_log_file, format, args);
va_end(args);
}
}
#define PREPARE_FUNC(NAME, RET, ARGS) \
static RET (*lib_##NAME) ARGS; \
if (lib_##NAME == NULL) \
lib_##NAME = dlsym(RTLD_NEXT, #NAME); \
assert(lib_##NAME != NULL)
#if 0
char *getenv(const char *name)
{
PREPARE_FUNC(getenv, char *, (const char *));
char *str = lib_getenv(name);
npw_printf("getenv '%s' => '%s'\n", name ? name : "<null>", str ? str : "<null>");
return str;
}
int putenv(char *string)
{
PREPARE_FUNC(putenv, int, (char *));
npw_printf("putenv '%s'\n", string ? string : "<null>");
return lib_putenv(string);
}
#endif
int XSetClassHints(Display *display, Window w, XClassHint *class_hints)
{
PREPARE_FUNC(XSetClassHints, int, (Display *, Window, XClassHint *));
npw_printf("XSetClassHints(window %p, class_hints { %s, '%s' }\n", w, class_hints->res_name, class_hints->res_class);
return lib_XSetClassHints(display, w, class_hints);
}
static void print_backtrace(void)
{
#if 0
#define N_LEVELS 64
void *trace[N_LEVELS];
int n_levels = backtrace(trace, sizeof(trace)/sizeof(trace[0]));
backtrace_symbols_fd(trace, n_levels, STDERR_FILENO);
#endif
}
Status XSendEvent(Display *display, Window w, Bool propagate, long event_mask, XEvent *event_send)
{
PREPARE_FUNC(XSendEvent, Status, (Display *, Window, Bool, long, XEvent *));
if (event_send && (1 || ((XAnyEvent *)event_send)->send_event)) {
npw_printf("XSendEvent(window %p, propagate %d, event_mask %08x, event type %d, SendEvent %x)\n",
w, propagate, event_mask, event_send->type, event_send->xany.send_event);
}
print_backtrace();
if (event_send->xclient.message_type == XInternAtom(display, "_XEMBED", False))
npw_printf("[X11] Handle XEMBED message %d for window %p\n", event_send->xclient.data.l[1], event_send->xany.window);
return lib_XSendEvent(display, w, propagate, event_mask, event_send);
}
#if 0
Window XCreateWindow(Display *display, Window parent, int x, int y,
unsigned int width, unsigned int height,
unsigned int border_width, int depth, unsigned int class, Visual *visual,
unsigned long valuemask, XSetWindowAttributes *attributes)
{
PREPARE_FUNC(XCreateWindow, Window, (Display *, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, Visual *, unsigned long, XSetWindowAttributes *));
Window ret = lib_XCreateWindow(display, parent, x, y, width, height,
border_width, depth, class, visual,
valuemask, attributes);
npw_printf("[X11] XCreateWindow() -> %p\n", ret);
return ret;
}
#endif
#if 0
int XChangeProperty(Display *display, Window w, Atom property, Atom type,
int format, int mode, const unsigned char *data, int nelements)
{
PREPARE_FUNC(XChangeProperty, int, (Display *, Window, Atom, Atom, int, int, const unsigned char *, int));
const char *property_str = XGetAtomName(display, property);
const char *type_str = XGetAtomName(display, type);
npw_printf("XChangeProperty(window %p, property %s, type %s, format %d, mode %d)\n",
w, property_str, type_str, format, mode);
int ret = lib_XChangeProperty(display, w, property, type, format, mode, data, nelements);
if (property == XInternAtom(display, "WM_HINTS", False) && format == 32) {
XWMHints *hints = XGetWMHints(display, w);
if (hints) {
npw_printf(" InputHint %d\n", hints->input);
XFree((void *)hints);
}
}
return ret;
}
#endif
void XtConfigureWidget(Widget w, Position x, Position y, Dimension width, Dimension height, Dimension border_width)
{
PREPARE_FUNC(XtConfigureWidget, void, (Widget, Position, Position, Dimension, Dimension, Dimension));
lib_XtConfigureWidget(w, x, y, width, height, border_width);
}
#if 0
Atom XInternAtom(Display *display, const char *atom_name, Bool only_if_exists)
{
static Atom (*x_XInternAtom)(Display *, const char *, Bool) = NULL;
if (x_XInternAtom == NULL)
x_XInternAtom = dlsym(RTLD_NEXT, "XInternAtom");
npw_printf("[X11] XInternAtom(display=%p, atom_name='%s', only_if_exists=%d)\n", display, atom_name, only_if_exists);
Atom ret = x_XInternAtom(display, atom_name, only_if_exists);
return ret;
}
#endif
typedef struct {
void *client_data;
XtEventHandler event_handler;
} fake_event_handler_data;
static void fake_event_handler(Widget w, XtPointer client_data, XEvent *event, Boolean *cont)
{
fake_event_handler_data *pdata = (fake_event_handler_data *)client_data;
switch (event->type) {
case ButtonPress:
npw_printf("ButtonPress\n");
break;
case ButtonRelease:
npw_printf("ButtonRelease\n");
break;
case KeyPress:
npw_printf("KeyPress\n");
break;
case KeyRelease:
npw_printf("KeyRelease\n");
break;
case FocusIn:
npw_printf("[X11] FocusIn for window %p\n", event->xfocus.window);
break;
case FocusOut:
npw_printf("[X11] FocusOut for window %p\n", event->xfocus.window);
break;
}
pdata->event_handler(w, pdata->client_data, event, cont);
}
static const char *dlname(void *addr)
{
static Dl_info dlinfo;
if (dladdr(addr, &dlinfo) < 0)
return NULL;
return dlinfo.dli_sname;
}
static void print_event_mask(EventMask event_mask)
{
#define P(EVENT) if (event_mask & (EVENT##Mask)) npw_printf(" " #EVENT "\n")
P(KeyPress);
P(KeyRelease);
P(ButtonPress);
P(ButtonRelease);
P(EnterWindow);
P(LeaveWindow);
P(PointerMotion);
P(PointerMotionHint);
P(Button1Motion);
P(Button2Motion);
P(Button3Motion);
P(Button4Motion);
P(Button5Motion);
P(ButtonMotion);
P(KeymapState);
P(Exposure);
P(VisibilityChange);
P(StructureNotify);
P(ResizeRedirect);
P(SubstructureNotify);
P(SubstructureRedirect);
P(FocusChange);
P(PropertyChange);
P(ColormapChange);
P(OwnerGrabButton);
}
#if 1
void XtAddEventHandler(Widget w, EventMask event_mask, Bool nonmaskable,
XtEventHandler proc, XtPointer client_data)
{
static void (*x_XtAddEventHandler)(Widget, EventMask, Bool, XtEventHandler, XtPointer) = NULL;
if (x_XtAddEventHandler == NULL)
x_XtAddEventHandler = dlsym(RTLD_NEXT, "XtAddEventHandler");
if (0 || (event_mask & (KeyPressMask|KeyReleaseMask))) {
npw_printf("[X11] XtAddEventHandler(Widget=%p[0x%08x], event_mask=%x, nonmaskable=%d, proc=%p[%s])\n",
w, XtWindow(w), event_mask, nonmaskable, proc, dlname(proc));
print_event_mask(event_mask);
}
#if 1
if (event_mask & (KeyPressMask|KeyReleaseMask)) {
fake_event_handler_data *pdata = malloc(sizeof(*pdata));
pdata->client_data = client_data;
pdata->event_handler = proc;
proc = fake_event_handler;
client_data = pdata;
}
#endif
x_XtAddEventHandler(w, event_mask, nonmaskable, proc, client_data);
#if 0
if (event_mask & (KeyPressMask|KeyReleaseMask))
x_XtAddEventHandler(w, event_mask, nonmaskable, fake_event_handler, client_data);
#endif
}
#endif
#if 0
void XtAddCallback(Widget w, _Xconst _XtString callback_name, XtCallbackProc callback, XtPointer client_data)
{
static void (*x_XtAddCallback)(Widget, _Xconst _XtString, XtCallbackProc, XtPointer);
if (x_XtAddCallback == NULL)
x_XtAddCallback = dlsym(RTLD_NEXT, "XtAddCallback");
npw_printf("[X11] XtAddCallback(widget %p[0x%08x], callback_name '%s', callback %p[%s], client_data %p)\n",
w, XtWindow(w), callback_name, callback, dlname(callback), client_data);
x_XtAddCallback(w, callback_name, callback, client_data);
}
#endif
#if 0
int XtGrabKeyboard(Widget w, _XtBoolean owner_events, int pointer_mode, int keyboard_mode, Time time)
{
static int (*x_XtGrabKeyboard)(Widget, _XtBoolean, int, int, Time);
if (x_XtGrabKeyboard == NULL)
x_XtGrabKeyboard = dlsym(RTLD_NEXT, "XtGrabKeyboard");
npw_printf("[X11] XtGrabKeyboard(widget %p[0x%08x], owner_events %08x, pointer_mode %08x, keyboard_mode %08x, time %d)\n",
w, XtWindow(w), owner_events, pointer_mode, keyboard_mode, time);
int rc = x_XtGrabKeyboard(w, owner_events, pointer_mode, keyboard_mode, time);
npw_printf(" returns %d\n", rc);
return rc;
}
void XtUngrabKeyboard(Widget w, Time time)
{
static void (*x_XtUngrabKeyboard)(Widget, Time);
if (x_XtUngrabKeyboard == NULL)
x_XtUngrabKeyboard = dlsym(RTLD_NEXT, "XtUngrabKeyboard");
npw_printf("[X11] XtUngrabKeyboard(widget %p[%08x], time %d)\n", w, XtWindow(w), time);
x_XtUngrabKeyboard(w, time);
}
#endif
#if 0
XtIntervalId XtAppAddTimeOut(XtAppContext app_context, unsigned long
interval, XtTimerCallbackProc proc, XtPointer client_data)
{
static XtIntervalId (*x_XtAppAddTimeOut)(XtAppContext, unsigned long, XtTimerCallbackProc, XtPointer) = NULL;
if (x_XtAppAddTimeOut == NULL)
x_XtAppAddTimeOut = dlsym(RTLD_NEXT, "XtAppAddTimeOut");
static int once = 1;
if (once)
npw_printf("[X11] XtAppAddTimeout(ctx=%p, interval=%d, proc=%p[%s], client_data=%p)\n",
app_context, interval, proc, dlname(proc), client_data);
XtIntervalId ret = x_XtAppAddTimeOut(app_context, interval, proc, client_data);
if (once)
npw_printf(" return: %d\n", ret);
if (1)
once = 0;
return ret;
}
int XSetForeground(Display *display, GC gc, unsigned long foreground)
{
static int (*x_XSetForeground)(Display *, GC, unsigned long) = NULL;
if (x_XSetForeground == NULL)
x_XSetForeground = dlsym(RTLD_NEXT, "XSetForeground");
npw_printf("[X11] XSetForeground(display=%p, gc=%p, foreground=%06x)\n", display, gc, foreground);
int ret = x_XSetForeground(display, gc, foreground);
npw_printf(" return: %d\n", ret);
return ret;
}
Status XGetWindowAttributes(Display *display, Window w, XWindowAttributes *attr)
{
static Status (*x_XGetWindowAttributes)(Display *, Window, XWindowAttributes *) = NULL;
if (x_XGetWindowAttributes == NULL)
x_XGetWindowAttributes = dlsym(RTLD_NEXT, "XGetWindowAttributes");
npw_printf("[X11] XGetWindowAttributes(display=%p, window=0x%08x)\n", display, w);
Status ret = x_XGetWindowAttributes(display, w, attr);
npw_printf(" return: %d\n", ret);
npw_printf(" pos=(%d, %d), size=%dx%d, border=%d\n",
attr->x, attr->y, attr->width, attr->height, attr->border_width);
return ret;
}
#endif
#if 1
Widget XtCreatePopupShell(const char *name, WidgetClass widget_class, Widget
parent, ArgList args, Cardinal num_args)
{
static Widget (*x_XtCreatePopupShell)(const char *, WidgetClass, Widget, ArgList, Cardinal) = NULL;
if (x_XtCreatePopupShell == NULL)
x_XtCreatePopupShell = dlsym(RTLD_NEXT, "XtCreatePopupShell");
npw_printf("[X11] XtCreatePopupShell(name='%s', widget_class=%p, parent=%p[0x%08x])\n", name, widget_class, parent, XtWindow(parent));
int i;
for (i = 0; i < num_args; i++)
npw_printf(" %d: '%s' => %d\n", i, args[i].name, args[i].value);
Widget ret = x_XtCreatePopupShell(name, widget_class, parent, args, num_args);
npw_printf(" return: %p [0x%08x]\n", ret, XtWindow(ret));
return ret;
}
#endif
#if 0
Status XQueryTree(Display *display, Window w, Window *root_return, Window *parent_return,
Window **children_return, unsigned int *nchildren_return)
{
static Status (*x_XQueryTree)(Display *, Window, Window *, Window *, Window **, unsigned int *) = NULL;
if (x_XQueryTree == NULL)
x_XQueryTree = dlsym(RTLD_NEXT, "XQueryTree");
npw_printf("[X11] XQueryTree(display=%p, window=0x%08x)\n", display, w);
Status ret = x_XQueryTree(display, w, root_return, parent_return, children_return, nchildren_return);
npw_printf(" return: %d\n", ret);
npw_printf(" + parent_window=0x%08x, root_window=0x%08x\n", root_return ? *root_return : 0, parent_return ? *parent_return : 0);
if (children_return && nchildren_return) {
Window *children = *children_return;
int i, n = *nchildren_return;
for (i = 0; i < n; i++)
npw_printf(" + child 0x%08x\n", children[i]);
}
return ret;
}
Bool XQueryPointer(Display *display, Window w, Window *root_return,
Window *child_return, int *root_x_return, int *root_y_return,
int *win_x_return, int *win_y_return, unsigned int *mask_return)
{
static Bool (*x_XQueryPointer)(Display *, Window, Window *, Window *, int *, int *, int *, int *, unsigned int *) = NULL;
if (x_XQueryPointer == NULL)
x_XQueryPointer = dlsym(RTLD_NEXT, "XQueryPointer");
npw_printf("[X11] XQueryPointer(display=%p, window=0x%08x)\n", display, w);
Bool ret = x_XQueryPointer(display, w, root_return, child_return, root_x_return, root_y_return, win_x_return, win_y_return, mask_return);
npw_printf(" return: %d\n", ret);
if (ret) {
if (win_x_return && win_y_return)
npw_printf(" + pos = (%d, %d)\n", *win_x_return, *win_y_return);
if (child_return)
npw_printf(" + child = 0x%08x\n", *child_return);
}
return ret;
}
#endif
#if 0
Widget XtWindowToWidget(Display *display, Window window)
{
static Widget (*fn)(Display *, Window) = NULL;
if (fn == NULL)
fn = dlsym(RTLD_NEXT, "XtWindowToWidget");
npw_printf("[X11] XtWindowToWidget(display=%p, window=0x%08x)\n", display, window);
Widget ret = fn(display, window);
npw_printf(" return: %p\n", ret);
return ret;
}
Widget XtParent(Widget w)
{
static Widget (*fn)(Widget) = NULL;
if (fn == NULL)
fn = dlsym(RTLD_NEXT, "XtParent");
npw_printf("[X11] XtParent(widget=0x%08x)\n", w);
Widget ret = fn(w);
npw_printf(" return: 0x%08x\n", ret);
return ret;
}
#endif
#if 0
static XErrorHandler app_error_handler = NULL;
static int fake_error_handler(Display *display, XErrorEvent *error_event)
{
npw_printf("[X11] ERROR code=%d\n", error_event->error_code);
int ret = app_error_handler(display, error_event);
return ret;
}
XErrorHandler XSetErrorHandler(XErrorHandler handler)
{
static XErrorHandler (*fn)(XErrorHandler) = NULL;
if (fn == NULL)
fn = dlsym(RTLD_NEXT, "XSetErrorHandler");
app_error_handler = handler;
XErrorHandler ret = fn(fake_error_handler);
return ret;
}
#endif
#if 0
int XPutImage(Display *display, Drawable d, GC gc, XImage *image,
int src_x, int src_y, int dest_x, int dest_y, unsigned int width,
unsigned int height)
{
static int (*fn)(Display *, Drawable, GC, XImage *, int, int, int, int, unsigned int, unsigned int) = NULL;
if (fn == NULL)
fn = dlsym(RTLD_NEXT, "XPutImage");
npw_printf("[X11] XPutImage(display=%p, drawable=0x%08x, src @ (%d, %d), dst @ (%d, %d), size = %dx%d)\n",
display, d, src_x, src_y, dest_x, dest_y, width, height);
int ret = fn(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);
npw_printf(" return: %d\n", ret);
if (src_x == dest_x && src_x == 16 && src_y == dest_y && src_y == 17) {
npw_printf("about to trap into debugger\n");
getchar();
asm volatile ("int3");
}
return ret;
}
Status XShmPutImage(Display *display, Drawable d, GC gc, XImage *image,
int src_x, int src_y, int dest_x, int dest_y, unsigned int width,
unsigned int height, Bool send_event)
{
static int (*fn)(Display *, Drawable, GC, XImage *, int, int, int, int, unsigned int, unsigned int, Bool) = NULL;
if (fn == NULL)
fn = dlsym(RTLD_NEXT, "XShmPutImage");
npw_printf("[X11] XShmPutImage(display=%p, drawable=0x%08x, src @ (%d, %d), dst @ (%d, %d), size = %dx%d)\n",
display, d, src_x, src_y, dest_x, dest_y, width, height);
int ret = fn(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height, send_event);
npw_printf(" return: %d\n", ret);
return ret;
}
#endif