]> git.tdb.fi Git - gldbg.git/blob - source/glwrap.c
52c6552e1f5c0c007939e62f07a31e233ba8e587
[gldbg.git] / source / glwrap.c
1 /* $Id$
2
3 This file is part of gldbg
4 Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
5 Distributed under the GPL
6 */
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <dlfcn.h>
12 #include <sys/uio.h>
13
14 #define INTERNAL __attribute__((visibility("internal")))
15
16 INTERNAL inline const char *get_lib_names(void)
17 {
18         const char *env = getenv("GLWRAP_LIBS");
19         if(env)
20                 return env;
21         return "libGL.so";
22 }
23
24 INTERNAL inline void *glsym(const char *name)
25 {
26         static void **gl_libs = NULL;
27         unsigned i;
28
29         if(!gl_libs)
30         {
31                 char *lib_names = strdup(get_lib_names());
32                 unsigned n_libs = 1;
33                 unsigned j;
34
35                 for(i=0; lib_names[i]; ++i)
36                         if(lib_names[i]==':')
37                                 ++n_libs;
38
39                 gl_libs = (void **)malloc((n_libs+1)*sizeof(void *));
40                 i = 0;
41                 n_libs = 0;
42                 for(j=0;; ++j)
43                 {
44                         if(lib_names[j]==':' || lib_names[j]==0)
45                         {
46                                 int at_end = (lib_names[j]==0);
47                                 lib_names[j] = 0;
48
49                                 gl_libs[n_libs] = dlopen(lib_names+i, RTLD_NOW);
50                                 if(!gl_libs[n_libs])
51                                 {
52                                         fprintf(stderr, "Could not open %s: %s\n", lib_names+i, dlerror());
53                                         abort();
54                                 }
55
56                                 i = j+1;
57                                 ++n_libs;
58
59                                 if(at_end)
60                                         break;
61                         }
62                 }
63
64                 gl_libs[n_libs] = 0;
65                 free(lib_names);
66         }
67
68         for(i=0; gl_libs[i]; ++i)
69         {
70                 void *sym = dlsym(gl_libs[i], name);
71                 if(sym)
72                         return sym;
73         }
74
75         return NULL;
76 }
77
78 INTERNAL char *buffer = 0;
79 INTERNAL char *write_pos;
80 INTERNAL struct iovec *iovecs = 0;
81 INTERNAL struct iovec *cur_vec;
82 INTERNAL unsigned length;
83
84 INTERNAL inline void next_vec(void)
85 {
86         if(write_pos!=cur_vec->iov_base)
87         {
88                 cur_vec->iov_len = write_pos-(char *)cur_vec->iov_base;
89                 length += cur_vec->iov_len;
90                 ++cur_vec;
91                 cur_vec->iov_base = write_pos;
92         }
93 }
94
95 INTERNAL inline void write_bytes(const char *ptr, unsigned size)
96 {
97         unsigned i;
98         for(i=0; i<size; ++i)
99                 *write_pos++ = *ptr++;
100 }
101
102 INTERNAL inline void write_char(char v)
103 {
104         *write_pos++ = v;
105 }
106
107 INTERNAL inline void write_short(short v)
108 {
109         write_bytes((char *)&v, sizeof(short));
110 }
111
112 INTERNAL inline void write_int(int v)
113 {
114         write_bytes((char *)&v, sizeof(int));
115 }
116
117 INTERNAL inline void write_long(long v)
118 {
119         write_bytes((char *)&v, sizeof(long));
120 }
121
122 INTERNAL inline void write_long_long(long long v)
123 {
124         write_bytes((char *)&v, sizeof(long long));
125 }
126
127 INTERNAL inline void write_float(float v)
128 {
129         write_bytes((char *)&v, sizeof(float));
130 }
131
132 INTERNAL inline void write_double(double v)
133 {
134         write_bytes((char *)&v, sizeof(double));
135 }
136
137 INTERNAL inline void write_pointer(const void *p)
138 {
139         write_bytes((char *)&p, sizeof(void *));
140 }
141
142 INTERNAL inline void write_data(const void *data, unsigned size)
143 {
144         if(data)
145         {
146                 write_int(size);
147                 next_vec();
148                 cur_vec->iov_base = (void *)data;
149                 cur_vec->iov_len = size;
150                 length += size;
151                 ++cur_vec;
152                 cur_vec->iov_base = write_pos;
153         }
154         else
155                 write_int(0);
156 }
157
158 INTERNAL inline void write_string(const char *s)
159 {
160         write_data(s, strlen(s)+1);
161 }
162
163 INTERNAL inline void write_string_array(const char **sa, unsigned size)
164 {
165         unsigned i;
166         size /= sizeof(const char *);
167         write_int(size);
168         for(i=0; i<size; ++i)
169                 write_string(sa[i]);
170 }
171
172 INTERNAL inline void begin_packet(int func)
173 {
174         if(!buffer)
175                 buffer = (char *)malloc(1024);
176         if(!iovecs)
177                 iovecs = (struct iovec *)malloc(16*sizeof(struct iovec));
178         write_pos = buffer;
179         cur_vec = iovecs;
180         cur_vec->iov_base = write_pos;
181         length = 0;
182         write_int(0);
183         write_short(func);
184 }
185
186 INTERNAL inline void send_packet(void)
187 {
188         static int fd = -1;
189         if(fd<0)
190         {
191                 const char *var = getenv("GLWRAP_FD");
192                 if(var)
193                         fd = strtol(var, NULL, 0);
194                 else
195                         fd = 2;
196         }
197         next_vec();
198         write_pos = buffer;
199         write_int(length);
200         writev(fd, iovecs, cur_vec-iovecs);
201 }