#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <errno.h>
#include <dlfcn.h>
-#include <sys/uio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include "breakpoint.h"
+#include "functions.h"
+#include "packet.h"
-#define INTERNAL __attribute__((visibility("internal")))
+static unsigned char breakpoints[N_FUNCS] = { };
+static char break_any = 0;
+static char hold = 0;
-INTERNAL inline const char *get_lib_names(void)
+static const char *get_lib_names(void)
{
const char *env = getenv("GLWRAP_LIBS");
if(env)
return env;
- return "libGL.so";
+ return "libGL.so.1";
}
-INTERNAL inline void *glsym(const char *name)
+void *glsym(const char *name)
{
static void **gl_libs = NULL;
unsigned i;
return NULL;
}
-INTERNAL char *buffer = 0;
-INTERNAL char *write_pos;
-INTERNAL struct iovec *iovecs = 0;
-INTERNAL struct iovec *cur_vec;
-INTERNAL unsigned length;
-
-INTERNAL inline void next_vec(void)
+int get_out_fd(void)
{
- if(write_pos!=cur_vec->iov_base)
+ static int fd = -1;
+
+ if(fd<0)
{
- cur_vec->iov_len = write_pos-(char *)cur_vec->iov_base;
- length += cur_vec->iov_len;
- ++cur_vec;
- cur_vec->iov_base = write_pos;
+ const char *var = getenv("GLWRAP_FD");
+ if(var)
+ fd = strtol(var, NULL, 0);
+ else
+ {
+ var = getenv("GLWRAP_FILE");
+ if(var)
+ {
+ fd = open(var, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if(fd==-1)
+ {
+ fprintf(stderr, "Couldn't open dumpfile %s for output: %s", var, strerror(errno));
+ abort();
+ }
+ }
+ else
+ fd = 2;
+ }
}
-}
-INTERNAL inline void write_bytes(const char *ptr, unsigned size)
-{
- unsigned i;
- for(i=0; i<size; ++i)
- *write_pos++ = *ptr++;
+ return fd;
}
-INTERNAL inline void write_char(char v)
+int get_in_fd(void)
{
- *write_pos++ = v;
-}
+ static int fd = -1;
-INTERNAL inline void write_short(short v)
-{
- write_bytes((char *)&v, sizeof(short));
-}
+ if(fd<0)
+ {
+ const char *var = getenv("GLWRAP_CTRL_FD");
+ if(var)
+ fd = strtol(var, NULL, 0);
+ else
+ fd = 0;
+ }
-INTERNAL inline void write_int(int v)
-{
- write_bytes((char *)&v, sizeof(int));
+ return fd;
}
-INTERNAL inline void write_long(long v)
+static void receive_gldBreak(GlPacket *pkt)
{
- write_bytes((char *)&v, sizeof(long));
-}
+ unsigned short func;
+ unsigned char flags_set;
+ unsigned char flags_clr;
-INTERNAL inline void write_long_long(long long v)
-{
- write_bytes((char *)&v, sizeof(long long));
-}
+ packet_read_short(pkt, (short *)&func);
+ packet_read_char(pkt, (char *)&flags_set);
+ packet_read_char(pkt, (char *)&flags_clr);
-INTERNAL inline void write_float(float v)
-{
- write_bytes((char *)&v, sizeof(float));
+ if(func)
+ {
+ breakpoints[func] &= ~flags_clr;
+ breakpoints[func] |= flags_set;
+ }
+ else
+ break_any = flags_set;
}
-INTERNAL inline void write_double(double v)
+static void receive_gldHold(GlPacket *pkt __attribute__((unused)))
{
- write_bytes((char *)&v, sizeof(double));
+ hold = 1;
}
-INTERNAL inline void write_pointer(const void *p)
+static void receive(void)
{
- write_bytes((char *)&p, sizeof(void *));
-}
+ GlPacket *pkt;
-INTERNAL inline void write_data(const void *data, unsigned size)
-{
- if(data)
+ while((pkt = packet_receive(get_in_fd())))
{
- write_int(size);
- next_vec();
- cur_vec->iov_base = (void *)data;
- cur_vec->iov_len = size;
- length += size;
- ++cur_vec;
- cur_vec->iov_base = write_pos;
+ unsigned short func;
+
+ packet_read_short(pkt, (short *)&func);
+ switch(func)
+ {
+ case FUNC_GLDBREAK: receive_gldBreak(pkt); break;
+ case FUNC_GLDHOLD: receive_gldHold(pkt); break;
+ default:;
+ }
}
- else
- write_int(0);
}
-INTERNAL inline void write_string(const char *s)
+void tracepoint(unsigned short func, int flag)
{
- write_data(s, strlen(s)+1);
-}
+ receive();
-INTERNAL inline void write_string_array(const char **sa, unsigned size)
-{
- unsigned i;
- size /= sizeof(const char *);
- write_int(size);
- for(i=0; i<size; ++i)
- write_string(sa[i]);
-}
+ if((breakpoints[func]|break_any)&flag)
+ {
+ GlPacket *pkt;
-INTERNAL inline void begin_packet(int func)
-{
- if(!buffer)
- buffer = (char *)malloc(1024);
- if(!iovecs)
- iovecs = (struct iovec *)malloc(16*sizeof(struct iovec));
- write_pos = buffer;
- cur_vec = iovecs;
- cur_vec->iov_base = write_pos;
- length = 0;
- write_int(0);
- write_short(func);
-}
+ pkt = packet_begin(FUNC_GLDBREAK);
+ packet_write_short(pkt, func);
+ packet_send(pkt, get_out_fd());
-INTERNAL inline void send_packet(void)
-{
- static int fd = -1;
- if(fd<0)
- {
- const char *var = getenv("GLWRAP_FD");
- if(var)
- fd = strtol(var, NULL, 0);
- else
- fd = 2;
+ break_any = 0;
+
+ while(1)
+ {
+ hold = 0;
+ raise(SIGTRAP);
+ receive();
+ if(!hold)
+ break;
+ }
}
- next_vec();
- write_pos = buffer;
- write_int(length);
- writev(fd, iovecs, cur_vec-iovecs);
}