]> git.tdb.fi Git - gldbg.git/blob - source/glwrap.c
Enable bidirectional communication between gldbg and glwrap.so
[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 <errno.h>
12 #include <dlfcn.h>
13 #include <fcntl.h>
14 #include <signal.h>
15 #include "breakpoint.h"
16 #include "functions.h"
17 #include "packet.h"
18
19 static unsigned char breakpoints[N_FUNCS] = { };
20 static char break_any = 0;
21 static char hold = 0;
22
23 static const char *get_lib_names(void)
24 {
25         const char *env = getenv("GLWRAP_LIBS");
26         if(env)
27                 return env;
28         return "libGL.so.1";
29 }
30
31 void *glsym(const char *name)
32 {
33         static void **gl_libs = NULL;
34         unsigned i;
35
36         if(!gl_libs)
37         {
38                 char *lib_names = strdup(get_lib_names());
39                 unsigned n_libs = 1;
40                 unsigned j;
41
42                 for(i=0; lib_names[i]; ++i)
43                         if(lib_names[i]==':')
44                                 ++n_libs;
45
46                 gl_libs = (void **)malloc((n_libs+1)*sizeof(void *));
47                 i = 0;
48                 n_libs = 0;
49                 for(j=0;; ++j)
50                 {
51                         if(lib_names[j]==':' || lib_names[j]==0)
52                         {
53                                 int at_end = (lib_names[j]==0);
54                                 lib_names[j] = 0;
55
56                                 gl_libs[n_libs] = dlopen(lib_names+i, RTLD_NOW);
57                                 if(!gl_libs[n_libs])
58                                 {
59                                         fprintf(stderr, "Could not open %s: %s\n", lib_names+i, dlerror());
60                                         abort();
61                                 }
62
63                                 i = j+1;
64                                 ++n_libs;
65
66                                 if(at_end)
67                                         break;
68                         }
69                 }
70
71                 gl_libs[n_libs] = 0;
72                 free(lib_names);
73         }
74
75         for(i=0; gl_libs[i]; ++i)
76         {
77                 void *sym = dlsym(gl_libs[i], name);
78                 if(sym)
79                         return sym;
80         }
81
82         return NULL;
83 }
84
85 int get_out_fd(void)
86 {
87         static int fd = -1;
88
89         if(fd<0)
90         {
91                 const char *var = getenv("GLWRAP_FD");
92                 if(var)
93                         fd = strtol(var, NULL, 0);
94                 else
95                 {
96                         var = getenv("GLWRAP_FILE");
97                         if(var)
98                         {
99                                 fd = open(var, O_WRONLY|O_CREAT|O_TRUNC, 0644);
100                                 if(fd==-1)
101                                 {
102                                         fprintf(stderr, "Couldn't open dumpfile %s for output: %s", var, strerror(errno));
103                                         abort();
104                                 }
105                         }
106                         else
107                                 fd = 2;
108                 }
109         }
110
111         return fd;
112 }
113
114 int get_in_fd(void)
115 {
116         static int fd = -1;
117
118         if(fd<0)
119         {
120                 const char *var = getenv("GLWRAP_CTRL_FD");
121                 if(var)
122                         fd = strtol(var, NULL, 0);
123                 else
124                         fd = 0;
125         }
126
127         return fd;
128 }
129
130 static void receive_gldBreak(GlPacket *pkt)
131 {
132         unsigned short func;
133         unsigned char flags_set;
134         unsigned char flags_clr;
135
136         packet_read_short(pkt, (short *)&func);
137         packet_read_char(pkt, (char *)&flags_set);
138         packet_read_char(pkt, (char *)&flags_clr);
139
140         if(func)
141         {
142                 breakpoints[func] &= ~flags_clr;
143                 breakpoints[func] |= flags_set;
144         }
145         else
146                 break_any = flags_set;
147 }
148
149 static void receive_gldHold(GlPacket *pkt __attribute__((unused)))
150 {
151         hold = 1;
152 }
153
154 static void receive(void)
155 {
156         GlPacket *pkt;
157
158         while((pkt = packet_receive(get_in_fd())))
159         {
160                 unsigned short func;
161
162                 packet_read_short(pkt, (short *)&func);
163                 switch(func)
164                 {
165                 case FUNC_GLDBREAK: receive_gldBreak(pkt); break;
166                 case FUNC_GLDHOLD: receive_gldHold(pkt); break;
167                 default:;
168                 }
169         }
170 }
171
172 void tracepoint(unsigned short func, int flag)
173 {
174         receive();
175
176         if((breakpoints[func]|break_any)&flag)
177         {
178                 GlPacket *pkt;
179
180                 pkt = packet_begin(FUNC_GLDBREAK);
181                 packet_write_short(pkt, func);
182                 packet_send(pkt, get_out_fd());
183
184                 break_any = 0;
185
186                 while(1)
187                 {
188                         hold = 0;
189                         raise(SIGTRAP);
190                         receive();
191                         if(!hold)
192                                 break;
193                 }
194         }
195 }