]> git.tdb.fi Git - gldbg.git/commitdiff
Use a centralized packet framework
authorMikko Rasa <tdb@tdb.fi>
Thu, 18 Nov 2010 13:39:42 +0000 (13:39 +0000)
committerMikko Rasa <tdb@tdb.fi>
Thu, 18 Nov 2010 13:39:42 +0000 (13:39 +0000)
Use a linker script to hide all unnecessary symbols from glwrap.so

Makefile
flavors/gl/source/glwrap_funcs.c
flavors/gles2/source/glwrap_funcs.c
glwrap.ld [new file with mode: 0644]
source/gldecoder.c
source/gldecoder.funcs.t
source/glwrap.c
source/glwrap.funcs.t
source/glwrap.h
source/packet.c [new file with mode: 0644]
source/packet.h [new file with mode: 0644]

index af82389b32fc8ea45d37f7439743be8d0108f95d..3679ee7955bac9a976f952ef35928bd2b8f2a646 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,10 +17,13 @@ SOURCES_libgldbg := source/gldecoder.c \
        source/glprint.c \
        source/enums.c \
        source/arraysize.c \
-       source/tmpalloc.c
+       source/tmpalloc.c \
+       source/packet.c
 SOURCES_glwrap := source/glwrap.c \
        source/glwrap_funcs.c \
-       source/arraysize.c
+       source/arraysize.c \
+       source/packet.c \
+       source/tmpalloc.c
 SOURCES_gldump := source/gldump.c
 SOURCES_gldbg := source/gldbg.cpp \
        source/commandinterpreter.cpp \
@@ -65,8 +68,9 @@ DEPS_all := $(call deps,$(SOURCES_all) $(TEMPLATES))
 $(OBJECTS_gldbg): CXXFLAGS += $(shell pkg-config --cflags $(PACKAGES_gldbg))
 gldbg: LIBS += $(shell pkg-config --libs $(PACKAGES_gldbg)) -lreadline
 gldump gldbg: LIBS += ./libgldbg.a
+glwrap.so: LDFLAGS += -s
 
-glwrap.so: $(OBJECTS_glwrap)
+glwrap.so: $(OBJECTS_glwrap) glwrap.ld
        $(CC) -shared -o $@ $^ $(LIBS) $(LDFLAGS)
 
 gldump: $(OBJECTS_gldump) libgldbg.a
index 7fc5adfddf815d108ca98d15565f1970e0248725..38621f3b15d42f71e1b60322ce14db75eaff1b0c 100644 (file)
@@ -10,13 +10,14 @@ Distributed under the GPL
 #include "functions.h"
 #include "glwrap.h"
 #include "opengl.h"
+#include "packet.h"
 
-int in_begin_block = 0;
-GLenum cur_error = GL_NO_ERROR;
+static int in_begin_block = 0;
+static GLenum cur_error = GL_NO_ERROR;
 
 static void check_error()
 {
-       GLenum (*orig_glGetError)() = 0;
+       static GLenum (*orig_glGetError)() = NULL;
        GLenum code;
 
        if(in_begin_block)
@@ -28,9 +29,11 @@ static void check_error()
        code = orig_glGetError();
        if(code!=GL_NO_ERROR)
        {
-               begin_packet(FUNC_GLDERROR);
-               write_int(code);
-               send_packet();
+               GlPacket *pkt;
+
+               pkt = packet_begin(FUNC_GLDERROR);
+               packet_write_int(pkt, code);
+               packet_send(pkt, get_out_fd());
 
                if(cur_error==GL_NO_ERROR)
                        cur_error = code;
@@ -39,27 +42,31 @@ static void check_error()
 
 void APIENTRY glBegin(GLenum mode)
 {
-       static void (*orig)(GLenum);
+       static void (*orig)(GLenum) = NULL;
+       GlPacket *pkt;
+
        if(!orig)
                orig = glsym("glBegin");
        orig(mode);
 
-       begin_packet(FUNC_GLBEGIN);
-       write_int(mode);
-       send_packet();
+       pkt = packet_begin(FUNC_GLBEGIN);
+       packet_write_int(pkt, mode);
+       packet_send(pkt, get_out_fd());
 
        in_begin_block = 1;
 }
 
 void APIENTRY glEnd()
 {
-       static void (*orig)();
+       static void (*orig)() = NULL;
+       GlPacket *pkt;
+
        if(!orig)
                orig = glsym("glEnd");
        orig();
 
-       begin_packet(FUNC_GLEND);
-       send_packet();
+       pkt = packet_begin(FUNC_GLEND);
+       packet_send(pkt, get_out_fd());
 
        in_begin_block = 0;
        check_error();
@@ -68,6 +75,7 @@ void APIENTRY glEnd()
 GLenum APIENTRY glGetError()
 {
        GLenum ret = GL_NO_ERROR;
+       GlPacket *pkt;
 
        if(in_begin_block)
        {
@@ -80,9 +88,9 @@ GLenum APIENTRY glGetError()
                cur_error = GL_NO_ERROR;
        }
 
-       begin_packet(FUNC_GLGETERROR);
-       write_int(ret);
-       send_packet();
+       pkt = packet_begin(FUNC_GLGETERROR);
+       packet_write_int(pkt, ret);
+       packet_send(pkt, get_out_fd());
 
        return ret;
 }
@@ -91,6 +99,7 @@ void (*glXGetProcAddress(const GLubyte *procname))(void)
 {
        void *handle = 0;
        void (*ret)() = 0;
+       GlPacket *pkt;
 
        if(glsym((const char *)procname))
        {
@@ -98,10 +107,10 @@ void (*glXGetProcAddress(const GLubyte *procname))(void)
                ret = dlsym(handle, (const char *)procname);
        }
 
-       begin_packet(FUNC_GLXGETPROCADDRESS);
-       write_string((const char *)procname);
-       write_pointer(ret);
-       send_packet();
+       pkt = packet_begin(FUNC_GLXGETPROCADDRESS);
+       packet_write_string(pkt, (const char *)procname);
+       packet_write_pointer(pkt, ret);
+       packet_send(pkt, get_out_fd());
 
        return ret;
 }
index c647753584930e4540739304de99070bd6bb84b3..e4f457abe6a5c7586832c660ca9a0bd9477cc4ec 100644 (file)
@@ -10,12 +10,13 @@ Distributed under the GPL
 #include "functions.h"
 #include "glwrap.h"
 #include "opengl.h"
+#include "packet.h"
 
 GLenum cur_error = GL_NO_ERROR;
 
 static void check_error()
 {
-       GLenum (*orig_glGetError)() = 0;
+       GLenum (*orig_glGetError)() = NULL;
        GLenum code;
 
        if(!orig_glGetError)
@@ -24,9 +25,11 @@ static void check_error()
        code = orig_glGetError();
        if(code!=GL_NO_ERROR)
        {
-               begin_packet(FUNC_GLDERROR);
-               write_int(code);
-               send_packet();
+               GlPacket *pkt;
+
+               pkt = packet_begin(FUNC_GLDERROR);
+               packet_write_int(pkt, code);
+               packet_send(pkt, get_out_fd());
 
                if(cur_error==GL_NO_ERROR)
                        cur_error = code;
@@ -37,18 +40,20 @@ GLenum APIENTRY glGetError()
 {
        GLenum ret = cur_error;
        cur_error = GL_NO_ERROR;
+       GlPacket *pkt;
 
-       begin_packet(FUNC_GLGETERROR);
-       write_int(ret);
-       send_packet();
+       pkt = packet_begin(FUNC_GLGETERROR);
+       packet_write_int(pkt, ret);
+       packet_send(pkt, get_out_fd());
 
        return ret;
 }
 
 void (*eglGetProcAddress(const char *procname))(void)
 {
-       void *handle = 0;
-       void (*ret)() = 0;
+       void *handle = NULL;
+       void (*ret)() = NULL;
+       GlPacket *pkt;
 
        if(glsym((const char *)procname))
        {
@@ -56,10 +61,10 @@ void (*eglGetProcAddress(const char *procname))(void)
                ret = dlsym(handle, (const char *)procname);
        }
 
-       begin_packet(FUNC_EGLGETPROCADDRESS);
-       write_pointer(ret);
-       write_string((const char *)procname);
-       send_packet();
+       pkt = packet_begin(FUNC_EGLGETPROCADDRESS);
+       packet_write_pointer(pkt, ret);
+       packet_write_string(pkt, (const char *)procname);
+       packet_send(pkt, get_out_fd());
 
        return ret;
 }
diff --git a/glwrap.ld b/glwrap.ld
new file mode 100644 (file)
index 0000000..15afadc
--- /dev/null
+++ b/glwrap.ld
@@ -0,0 +1,11 @@
+/* $Id$ */
+
+VERSION
+{
+       {
+               global:
+                       gl*;
+               local:
+                       *;
+       };
+}
index 6444fcaac8515b5054f7ea97a09ce354f6577f1b..999acccc9cec140d141f5db97f878af136282cdf 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of gldbg
-Copyright © 2009  Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the GPL
 */
 
@@ -9,17 +9,8 @@ Distributed under the GPL
 #include <string.h>
 #include "functions.h"
 #include "gldecoder.h"
-#include "tmpalloc.h"
+#include "packet.h"
 
-typedef struct sGlPacket
-{
-       const char *ptr;
-       unsigned chunk;
-       unsigned total;
-} GlPacket;
-
-static void read_short(short *, GlPacket *);
-static void read_int(int *, GlPacket *);
 static int decode_func(GlDecoder *, unsigned short, GlPacket *);
 static int decode_gldfunc(GlDecoder *, unsigned short, GlPacket *);
 
@@ -44,158 +35,28 @@ void gldecoder_delete(GlDecoder *dec)
 
 int gldecoder_decode(GlDecoder *dec, const char *data, unsigned len)
 {
+       GlPacket *pkt;
        unsigned short func;
-       GlPacket packet;
-
-       if(len<sizeof(int)+sizeof(short))
-               return -1;
-
-       packet.ptr = data;
-       packet.chunk = len;
-       read_int((int *)&packet.chunk, &packet);
-
-       if(packet.chunk&0x80000000)
-       {
-               packet.chunk &= 0x7FFFFFFF;
-               packet.total = packet.chunk;
-
-               while(1)
-               {
-                       if(len<packet.total+sizeof(int))
-                               return -1;
-
-                       GlPacket p = { packet.ptr+packet.total, len-packet.total, 0 };
-                       unsigned chunk;
-                       read_int((int *)&chunk, &p);
-                       packet.total += chunk&0x7FFFFFFF;
-                       if(!(chunk&0x80000000))
-                               break;
-               }
-       }
-       else
-               packet.total = packet.chunk;
 
-       if(len<packet.total)
+       pkt = packet_receive_str(data, &len);
+       if(!pkt)
                return -1;
 
-       read_short((short *)&func, &packet);
+       packet_read_short(pkt, (short *)&func);
 
        if(dec)
        {
                int ret = 0;
 
                if(func&0x8000)
-                       ret = decode_gldfunc(dec, func, &packet);
+                       ret = decode_gldfunc(dec, func, pkt);
                else
-                       ret = decode_func(dec, func, &packet);
+                       ret = decode_func(dec, func, pkt);
                if(ret<0)
                        return -1;
        }
 
-       return packet.ptr+packet.total-data;
-}
-
-static void next_chunk(GlPacket *pkt)
-{
-       if(pkt->total==0)
-               return;
-       pkt->chunk = pkt->total;
-       read_int((int *)&pkt->chunk, pkt);
-       pkt->chunk &= 0x7FFFFFFF;
-}
-
-static void read_generic(void *v, unsigned size, int byteswap, GlPacket *pkt)
-{
-       if(pkt->chunk==0)
-               next_chunk(pkt);
-
-       if(pkt->chunk>=size)
-       {
-               // TODO: Actually implement byteswap if needed
-               (void)byteswap;
-               memcpy(v, pkt->ptr, size);
-               pkt->ptr += size;
-               pkt->chunk -= size;
-               pkt->total -= size;
-       }
-       else
-       {
-               memset(v, 0, size);
-               pkt->total -= pkt->chunk;
-               pkt->chunk = 0;
-       }
-}
-
-static void read_char(char *v, GlPacket *pkt)
-{
-       read_generic(v, 1, 0, pkt);
-}
-
-static void read_short(short *v, GlPacket *pkt)
-{
-       read_generic(v, sizeof(short), 1, pkt);
-}
-
-static void read_int(int *v, GlPacket *pkt)
-{
-       read_generic(v, sizeof(int), 1, pkt);
-}
-
-static void read_long(long *v, GlPacket *pkt)
-{
-       read_generic(v, sizeof(long), 1, pkt);
-}
-
-static void read_long_long(long long *v, GlPacket *pkt)
-{
-       read_generic(v, sizeof(long long), 1, pkt);
-}
-
-static void read_float(float *v, GlPacket *pkt)
-{
-       read_generic(v, sizeof(float), 1, pkt);
-}
-
-static void read_double(double *v, GlPacket *pkt)
-{
-       read_generic(v, sizeof(double), 1, pkt);
-}
-
-typedef const void *pointer;
-
-static void read_pointer(pointer *v, GlPacket *pkt)
-{
-       read_generic(v, sizeof(pointer), 1, pkt);
-}
-
-static void read_data(pointer *v, GlPacket *pkt)
-{
-       int vlen;
-       read_int(&vlen, pkt);
-       if(vlen)
-               *v = pkt->ptr;
-       else
-               *v = NULL;
-       pkt->ptr += vlen;
-       pkt->chunk -= vlen;
-       pkt->total -= vlen;
-}
-
-typedef const char *string;
-
-static void read_string(string *v, GlPacket *pkt)
-{
-       read_data((pointer *)v, pkt);
-}
-
-static void read_string_array(string **v, GlPacket *pkt)
-{
-       int count;
-       int i;
-       read_int(&count, pkt);
-       *v = (string *)tmpalloc(count*sizeof(string));
-       for(i=0; i<count; ++i)
-               read_string(*v+i, pkt);
+       return len;
 }
 
 #include "gensrc/gldecoder.funcs"
@@ -203,7 +64,7 @@ static void read_string_array(string **v, GlPacket *pkt)
 static void decode_gldError(GlDecoder *dec, GlPacket *pkt)
 {
        GLenum code;
-       read_int((int *)&code, pkt);
+       packet_read_int(pkt, (int *)&code);
        if(dec->gldError)
                dec->gldError(dec->user_data, code);
 }
index 545f8b408522a652c5c72cddd3383149f5c34d9d..d4433aa6e9d942d79eee538530a19f820a64f138 100644 (file)
@@ -8,15 +8,15 @@ for p in params:
        wl('    %s p_%s;', p.ctype, p.name)
 for p in params:
        if p.kind=="value":
-               wl('    read_%s((%s *)&p_%s, pkt);', p.io[0].replace(' ', '_'), p.io[0], p.name)
+               wl('    packet_read_%s(pkt, (%s *)&p_%s);', p.io[0].replace(' ', '_'), p.io[0], p.name)
        elif p.kind=="array" and p.io and p.io[0]=="string":
-               wl('  read_string_array(&p_%s, pkt);', p.name)
+               wl('  packet_read_string_array(pkt, &p_%s);', p.name)
        elif p.csize:
-               wl('    read_data((pointer *)&p_%s, pkt);', p.name)
+               wl('    packet_read_data(pkt, (pointer *)&p_%s);', p.name)
        else:
-               wl('    read_pointer((pointer *)&p_%s, pkt);', p.name)
+               wl('    packet_read_pointer(pkt, (pointer *)&p_%s);', p.name)
 if ret.ctype!="void":
-       wl('    read_%s((%s *)&ret, pkt);', ret.io[0].replace(' ', '_'), ret.io[0])
+       wl('    packet_read_%s(pkt, (%s *)&ret);', ret.io[0].replace(' ', '_'), ret.io[0])
 wl('   if(dec->%s)', func.name)
 w('            dec->%s(dec->user_data', func.name)
 if ret.ctype!="void":
index f801a20aae2b71b3c4561215da9f250035df2240..10bfc77fcb12cd56f21149444593f8df57de8d52 100644 (file)
@@ -11,19 +11,16 @@ Distributed under the GPL
 #include <errno.h>
 #include <dlfcn.h>
 #include <fcntl.h>
-#include <sys/uio.h>
 
-#define INTERNAL __attribute__((visibility("internal")))
-
-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;
@@ -77,117 +74,7 @@ INTERNAL inline void *glsym(const char *name)
        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)
-{
-       if(write_pos!=cur_vec->iov_base)
-       {
-               cur_vec->iov_len = write_pos-(char *)cur_vec->iov_base;
-               length += cur_vec->iov_len;
-               ++cur_vec;
-               cur_vec->iov_base = write_pos;
-       }
-}
-
-INTERNAL inline void write_bytes(const char *ptr, unsigned size)
-{
-       unsigned i;
-       for(i=0; i<size; ++i)
-               *write_pos++ = *ptr++;
-}
-
-INTERNAL inline void write_char(char v)
-{
-       *write_pos++ = v;
-}
-
-INTERNAL inline void write_short(short v)
-{
-       write_bytes((char *)&v, sizeof(short));
-}
-
-INTERNAL inline void write_int(int v)
-{
-       write_bytes((char *)&v, sizeof(int));
-}
-
-INTERNAL inline void write_long(long v)
-{
-       write_bytes((char *)&v, sizeof(long));
-}
-
-INTERNAL inline void write_long_long(long long v)
-{
-       write_bytes((char *)&v, sizeof(long long));
-}
-
-INTERNAL inline void write_float(float v)
-{
-       write_bytes((char *)&v, sizeof(float));
-}
-
-INTERNAL inline void write_double(double v)
-{
-       write_bytes((char *)&v, sizeof(double));
-}
-
-INTERNAL inline void write_pointer(const void *p)
-{
-       write_bytes((char *)&p, sizeof(void *));
-}
-
-INTERNAL inline void write_data(const void *data, unsigned size)
-{
-       if(data)
-       {
-               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;
-       }
-       else
-               write_int(0);
-}
-
-INTERNAL inline void write_string(const char *s)
-{
-       write_data(s, strlen(s)+1);
-}
-
-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]);
-}
-
-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);
-}
-
-INTERNAL inline int get_out_fd(void)
+int get_out_fd(void)
 {
        static int fd = -1;
 
@@ -201,7 +88,7 @@ INTERNAL inline int get_out_fd(void)
                        var = getenv("GLWRAP_FILE");
                        if(var)
                        {
-                               fd = open(var, O_WRONLY|O_CREAT, 0644);
+                               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));
@@ -215,26 +102,3 @@ INTERNAL inline int get_out_fd(void)
 
        return fd;
 }
-
-INTERNAL inline void send_partial_packet(void)
-{
-       next_vec();
-       write_pos = buffer;
-       write_int(length|0x80000000);
-       writev(get_out_fd(), iovecs, cur_vec-iovecs);
-
-       write_pos = buffer;
-       cur_vec = iovecs;
-       cur_vec->iov_base = write_pos;
-       length = 0;
-
-       write_int(0);
-}
-
-INTERNAL inline void send_packet(void)
-{
-       next_vec();
-       write_pos = buffer;
-       write_int(length);
-       writev(get_out_fd(), iovecs, cur_vec-iovecs);
-}
index 6770ec780c7a169e661c0b0f3197a246e2ce83a9..bcee77166ec5053ad5238f25b60dd1e4d0f71075 100644 (file)
@@ -7,40 +7,42 @@
 !handcode eglGetProcAddress
 wl('%s APIENTRY %s(%s)', ret.ctype, func.name, ", ".join([p.ctype+" "+p.name for p in params]))
 wl('{')
-wl('   static %s (*orig)(%s);', ret.ctype, ", ".join([p.ctype for p in params]))
+wl('   static %s (*orig)(%s) = NULL;', ret.ctype, ", ".join([p.ctype for p in params]))
+wl('   GlPacket *pkt;')
 if ret.ctype!='void':
        wl('    %s ret;', ret.ctype)
 wl('   if(!orig)')
 wl('           orig = glsym("%s");', func.name)
-wl('   begin_packet(FUNC_%s);', func.name.upper())
+wl('   pkt = packet_begin(FUNC_%s);', func.name.upper())
 head_sent = False
 for p in params:
        if p.direction=="out" and not head_sent:
-               wl('    send_partial_packet();')
+               wl('    packet_send_partial(pkt, get_out_fd());')
                w('     ')
                if ret.ctype!='void':
                        w('ret = ')
                wl('orig(%s);', ", ".join([q.name for q in params]))
                head_sent = True
        if p.kind=="value":
-               wl('    write_%s(%s);', p.io[0].replace(' ', '_'), p.name)
+               wl('    packet_write_%s(pkt, %s);', p.io[0].replace(' ', '_'), p.name)
        elif p.kind=="array" and p.io and p.io[0]=="string":
-               wl('    write_string_array(%s, %s);', p.name, p.csize)
+               wl('    packet_write_string_array(pkt, %s, %s);', p.name, p.csize)
        elif p.csize:
-               wl('    write_data(%s, %s);', p.name, p.csize)
+               wl('    packet_write_data(pkt, %s, %s);', p.name, p.csize)
        else:
-               wl('    write_pointer(%s);', p.name)
+               wl('    packet_write_pointer(pkt, %s);', p.name)
 if ret.ctype!='void':
        if not head_sent:
-               wl('    send_partial_packet();')
+               wl('    packet_send_partial(pkt, get_out_fd());')
                wl('    ret = orig(%s);', ", ".join([p.name for p in params]))
                head_sent = True
-       wl('    write_%s(ret);', ret.io[0].replace(' ', '_'))
-wl('   send_packet();')
+       wl('    packet_write_%s(pkt, ret);', ret.io[0].replace(' ', '_'))
+wl('   packet_send(pkt, get_out_fd());')
 if not head_sent:
        wl('    orig(%s);', ", ".join([p.name for p in params]))
 if not func.name.startswith("glX"):
        wl('    check_error();')
+#wl('  receive_packet();')
 if ret.ctype!='void':
        wl('    return ret;')
 wl('}')
index 04d8f37ab2b193719aea76f0a83013b2d284c19a..f8422a53b21bf4bfb942ede7049be52c810f971d 100644 (file)
@@ -9,19 +9,6 @@ Distributed under the GPL
 #define GLWRAP_H_
 
 void *glsym(const char *);
-void write_char(char);
-void write_short(short);
-void write_int(int);
-void write_long(long);
-void write_long_long(long long);
-void write_float(float);
-void write_double(double);
-void write_pointer(const void *);
-void write_data(const void *, unsigned);
-void write_string(const char *);
-void write_string_array(const char **, unsigned);
-void begin_packet(int);
-void send_partial_packet(void);
-void send_packet(void);
+int get_out_fd(void);
 
 #endif
diff --git a/source/packet.c b/source/packet.c
new file mode 100644 (file)
index 0000000..465f118
--- /dev/null
@@ -0,0 +1,389 @@
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include "packet.h"
+#include "tmpalloc.h"
+
+struct GlOutPacket
+{
+       char *ptr;
+       unsigned length;
+       struct iovec *vec;
+};
+
+struct GlInPacket
+{
+       const char *ptr;
+       unsigned length;
+       unsigned chunk;
+};
+
+typedef struct GlOutPacket GlOutPacket;
+typedef struct GlInPacket GlInPacket;
+
+struct GlPacket
+{
+       union
+       {
+               GlOutPacket out;
+               GlInPacket in;
+       };
+};
+
+// XXX Should make this stuff truly re-entrant
+static char *out_buffer = 0;
+static struct iovec *iovecs = 0;
+static GlPacket packet;
+/*static char *in_buffer = 0;
+static unsigned in_length;*/
+
+static void next_vec(GlPacket *pkt)
+{
+       GlOutPacket *out = &pkt->out;
+
+       if(out->ptr!=out->vec->iov_base)
+       {
+               out->vec->iov_len = out->ptr-(char *)out->vec->iov_base;
+               out->length += out->vec->iov_len;
+               ++out->vec;
+               out->vec->iov_base = out->ptr;
+       }
+}
+
+static void reset(GlPacket *pkt)
+{
+       GlOutPacket *out = &pkt->out;
+
+       out->ptr = out_buffer;
+       out->vec = iovecs;
+       out->vec->iov_base = out->ptr;
+       out->length = 0;
+}
+
+GlPacket *packet_begin(unsigned short func)
+{
+       GlPacket *pkt;
+
+       if(!out_buffer)
+               out_buffer = (char *)malloc(1024);
+       if(!iovecs)
+               iovecs = (struct iovec *)malloc(16*sizeof(struct iovec));
+
+       pkt = &packet;
+       reset(pkt);
+
+       packet_write_int(pkt, 0);
+       packet_write_short(pkt, func);
+
+       return pkt;
+}
+
+void packet_send_partial(GlPacket *pkt, int fd)
+{
+       GlOutPacket *out = &pkt->out;
+
+       out->length |= 0x80000000;
+       packet_send(pkt, fd);
+
+       reset(pkt);
+
+       packet_write_int(pkt, 0);
+}
+
+void packet_send(GlPacket *pkt, int fd)
+{
+       GlOutPacket *out = &pkt->out;
+       struct iovec *v;
+
+       next_vec(pkt);
+       out->ptr = out_buffer;
+       packet_write_int(pkt, out->length);
+
+       for(v=iovecs; v!=out->vec; )
+       {
+               int ret;
+
+               ret = writev(fd, v, out->vec-v);
+               if(ret<0)
+                       return;
+
+               while(v!=out->vec && (unsigned)ret>=v->iov_len)
+               {
+                       ret -= v->iov_len;
+                       ++v;
+               }
+
+               if(v!=out->vec)
+               {
+                       v->iov_base += ret;
+                       v->iov_len -= ret;
+               }
+       }
+}
+
+static void write_raw(GlPacket *pkt, const char *ptr, unsigned size, int byteswap)
+{
+       GlOutPacket *out = &pkt->out;
+       unsigned i;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       if(byteswap)
+       {
+               ptr += size;
+               for(i=0; i<size; ++i)
+                       *out->ptr++ = *--ptr;
+       }
+       else
+#endif
+       {
+               for(i=0; i<size; ++i)
+                       *out->ptr++ = *ptr++;
+       }
+}
+
+void packet_write_char(GlPacket *pkt, char v)
+{
+       GlOutPacket *out = &pkt->out;
+       *out->ptr++ = v;
+}
+
+void packet_write_short(GlPacket *pkt, short v)
+{
+       write_raw(pkt, (char *)&v, sizeof(short), 1);
+}
+
+void packet_write_int(GlPacket *pkt, int v)
+{
+       write_raw(pkt, (char *)&v, sizeof(int), 1);
+}
+
+void packet_write_long(GlPacket *pkt, long v)
+{
+       write_raw(pkt, (char *)&v, sizeof(long), 1);
+}
+
+void packet_write_long_long(GlPacket *pkt, long long v)
+{
+       write_raw(pkt, (char *)&v, sizeof(long long), 1);
+}
+
+void packet_write_float(GlPacket *pkt, float v)
+{
+       write_raw(pkt, (char *)&v, sizeof(float), 1);
+}
+
+void packet_write_double(GlPacket *pkt, double v)
+{
+       write_raw(pkt, (char *)&v, sizeof(double), 1);
+}
+
+void packet_write_pointer(GlPacket *pkt, const void *p)
+{
+       write_raw(pkt, (char *)&p, sizeof(void *), 1);
+}
+
+void packet_write_data(GlPacket *pkt, const void *data, unsigned size)
+{
+       if(data)
+       {
+               GlOutPacket *out = &pkt->out;
+
+               packet_write_int(pkt, size);
+               next_vec(pkt);
+               out->vec->iov_base = (void *)data;
+               out->vec->iov_len = size;
+               out->length += size;
+               ++out->vec;
+               out->vec->iov_base = out->ptr;
+       }
+       else
+               packet_write_int(pkt, 0);
+}
+
+void packet_write_string(GlPacket *pkt, const char *s)
+{
+       packet_write_data(pkt, s, strlen(s)+1);
+}
+
+void packet_write_string_array(GlPacket *pkt, const char **sa, unsigned size)
+{
+       unsigned i;
+       size /= sizeof(const char *);
+       packet_write_int(pkt, size);
+       for(i=0; i<size; ++i)
+               packet_write_string(pkt, sa[i]);
+}
+
+GlPacket *packet_receive_str(const char *data, unsigned *len)
+{
+       const char *end = data+*len;
+       GlPacket *pkt;
+       GlInPacket *in;
+
+       if(*len<sizeof(int)+sizeof(short))
+               return 0;
+
+       pkt = &packet;
+       in = &pkt->in;
+       in->ptr = data;
+       in->chunk = *len;
+
+       packet_read_int(pkt, (int *)&in->chunk);
+
+       if(in->chunk&0x80000000)
+       {
+               in->chunk &= 0x7FFFFFFF;
+               in->length = in->chunk;
+
+               while(1)
+               {
+                       if(end<in->ptr+in->length+sizeof(int))
+                               return NULL;
+
+                       GlPacket p;
+                       p.in.ptr = in->ptr+in->length;
+                       p.in.chunk = p.in.length = end-p.in.ptr;
+
+                       unsigned chunk;
+                       packet_read_int(&p, (int *)&chunk);
+
+                       in->length += chunk&0x7FFFFFFF;
+                       if(!(chunk&0x80000000))
+                               break;
+               }
+       }
+       else
+               in->length = in->chunk;
+
+       if(end<in->ptr+in->length)
+               return NULL;
+
+       *len = in->ptr+in->length-data;
+
+       return pkt;
+}
+
+static void next_chunk(GlPacket *pkt)
+{
+       GlInPacket *in = &pkt->in;
+
+       if(in->length==0)
+               return;
+
+       in->chunk = in->length;
+       packet_read_int(pkt, (int *)&in->chunk);
+       in->chunk &= 0x7FFFFFFF;
+}
+
+static void read_raw(GlPacket *pkt, char *ptr, unsigned size, int byteswap)
+{
+       GlInPacket *in = &pkt->in;
+
+       if(in->chunk==0)
+               next_chunk(pkt);
+
+       if(in->chunk>=size)
+       {
+               unsigned i;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+               if(byteswap)
+               {
+                       ptr += size;
+                       for(i=0; i<size; ++i)
+                               *--ptr = *in->ptr++;
+               }
+               else
+#endif
+               {
+                       for(i=0; i<size; ++i)
+                               *ptr++ = *in->ptr++;
+               }
+
+               in->length -= size;
+               in->chunk -= size;
+       }
+       else
+       {
+               memset(ptr, 0, size);
+               in->length -= in->chunk;
+               in->chunk = 0;
+       }
+}
+
+void packet_read_char(GlPacket *pkt, char *v)
+{
+       read_raw(pkt, v, 1, 0);
+}
+
+void packet_read_short(GlPacket *pkt, short *v)
+{
+       read_raw(pkt, (char *)v, sizeof(short), 1);
+}
+
+void packet_read_int(GlPacket *pkt, int *v)
+{
+       read_raw(pkt, (char *)v, sizeof(int), 1);
+}
+
+void packet_read_long(GlPacket *pkt, long *v)
+{
+       read_raw(pkt, (char *)v, sizeof(long), 1);
+}
+
+void packet_read_long_long(GlPacket *pkt, long long *v)
+{
+       read_raw(pkt, (char *)v, sizeof(long long), 1);
+}
+
+void packet_read_float(GlPacket *pkt, float *v)
+{
+       read_raw(pkt, (char *)v, sizeof(float), 1);
+}
+
+void packet_read_double(GlPacket *pkt, double *v)
+{
+       read_raw(pkt, (char *)v, sizeof(double), 1);
+}
+
+void packet_read_pointer(GlPacket *pkt, pointer *v)
+{
+       read_raw(pkt, (char *)v, sizeof(pointer), 1);
+}
+
+void packet_read_data(GlPacket *pkt, pointer *v)
+{
+       GlInPacket *in = &pkt->in;
+       int vlen;
+
+       packet_read_int(pkt, &vlen);
+       if(vlen)
+               *v = in->ptr;
+       else
+               *v = NULL;
+       in->ptr += vlen;
+       in->chunk -= vlen;
+       in->length -= vlen;
+}
+
+void packet_read_string(GlPacket *pkt, string *v)
+{
+       packet_read_data(pkt, (pointer *)v);
+}
+
+void packet_read_string_array(GlPacket *pkt, string **v)
+{
+       int count;
+       int i;
+       packet_read_int(pkt, &count);
+       *v = (string *)tmpalloc(count*sizeof(string));
+       for(i=0; i<count; ++i)
+               packet_read_string(pkt, *v+i);
+}
diff --git a/source/packet.h b/source/packet.h
new file mode 100644 (file)
index 0000000..deacca0
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#ifndef PACKET_H_
+#define PACKET_H_
+
+struct GlPacket;
+typedef struct GlPacket GlPacket;
+
+GlPacket *packet_begin(unsigned short);
+void packet_send_partial(GlPacket *, int);
+void packet_send(GlPacket *, int);
+
+// XXX Should use something with fixed sizes
+
+void packet_write_char(GlPacket *, char);
+void packet_write_short(GlPacket *, short);
+void packet_write_int(GlPacket *, int);
+void packet_write_long(GlPacket *, long);
+void packet_write_long_long(GlPacket *, long long);
+void packet_write_float(GlPacket *, float);
+void packet_write_double(GlPacket *, double);
+void packet_write_pointer(GlPacket *, const void *);
+void packet_write_data(GlPacket *, const void *, unsigned);
+void packet_write_string(GlPacket *, const char *);
+void packet_write_string_array(GlPacket *, const char **, unsigned);
+
+GlPacket *packet_receive_str(const char *, unsigned *);
+
+void packet_read_char(GlPacket *, char *);
+void packet_read_short(GlPacket *, short *);
+void packet_read_int(GlPacket *, int *);
+void packet_read_long(GlPacket *, long *);
+void packet_read_long_long(GlPacket *, long long *);
+void packet_read_float(GlPacket *, float *);
+void packet_read_double(GlPacket *, double *);
+typedef const void *pointer;
+void packet_read_pointer(GlPacket *, pointer *);
+void packet_read_data(GlPacket *, pointer *);
+typedef const char *string;
+void packet_read_string(GlPacket *, string *);
+void packet_read_string_array(GlPacket *, string **);
+
+#endif