]> git.cworth.org Git - apitrace/blob - glxtrace.py
Add shortcut to replay and lookup state.
[apitrace] / glxtrace.py
1 ##########################################################################
2 #
3 # Copyright 2008-2010 VMware, Inc.
4 # All Rights Reserved.
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23 #
24 ##########################################################################/
25
26
27 """GLX tracing generator."""
28
29
30 from stdapi import API
31 from glapi import glapi
32 from glxapi import glxapi
33 from gltrace import GlTracer
34 from dispatch import function_pointer_type, function_pointer_value
35
36
37 class GlxTracer(GlTracer):
38
39     def get_function_address(self, function):
40         return '__%s' % (function.name,)
41
42     def wrap_ret(self, function, instance):
43         if function.name in ("glXGetProcAddress", "glXGetProcAddressARB"):
44             print '    %s = __unwrap_proc_addr(procName, %s);' % (instance, instance)
45
46
47 if __name__ == '__main__':
48     print
49     print '#include <stdlib.h>'
50     print '#include <string.h>'
51     print
52     print '#ifndef _GNU_SOURCE'
53     print '#define _GNU_SOURCE // for dladdr'
54     print '#endif'
55     print '#include <dlfcn.h>'
56     print
57     print '#include "trace_write.hpp"'
58     print
59     print '#include "glproc.hpp"'
60     print '#include "glsize.hpp"'
61     print
62     print 'extern "C" {'
63     print
64     print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr);'
65     print
66
67     api = API()
68     api.add_api(glxapi)
69     api.add_api(glapi)
70     tracer = GlxTracer()
71     tracer.trace_api(api)
72
73     print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr) {'
74     print '    if (!procPtr) {'
75     print '        return procPtr;'
76     print '    }'
77     for f in api.functions:
78         ptype = function_pointer_type(f)
79         pvalue = function_pointer_value(f)
80         print '    if (!strcmp("%s", (const char *)procName)) {' % f.name
81         print '        %s = (%s)procPtr;' % (pvalue, ptype)
82         print '        return (__GLXextFuncPtr)&%s;' % (f.name,)
83         print '    }'
84     print '    return procPtr;'
85     print '}'
86     print
87     print r'''
88
89
90 static void *libgl_handle = NULL;
91
92
93 /*
94  * Invoke the true dlopen() function.
95  */
96 static void *__dlopen(const char *filename, int flag)
97 {
98     typedef void * (*PFNDLOPEN)(const char *, int);
99     static PFNDLOPEN dlopen_ptr = NULL;
100
101     if (!dlopen_ptr) {
102         dlopen_ptr = (PFNDLOPEN)dlsym(RTLD_NEXT, "dlopen");
103         if (!dlopen_ptr) {
104             OS::DebugMessage("error: dlsym(RTLD_NEXT, \"dlopen\") failed\n");
105             return NULL;
106         }
107     }
108
109     return dlopen_ptr(filename, flag);
110 }
111
112
113 /*
114  * Several applications, such as Quake3, use dlopen("libGL.so.1"), but
115  * LD_PRELOAD does not intercept symbols obtained via dlopen/dlsym, therefore
116  * we need to intercept the dlopen() call here, and redirect to our wrapper
117  * shared object.
118  */
119 void *dlopen(const char *filename, int flag)
120 {
121     void *handle;
122
123     handle = __dlopen(filename, flag);
124
125     if (filename && handle) {
126         if (0) {
127             OS::DebugMessage("warning: dlopen(\"%s\", 0x%x)\n", filename, flag);
128         }
129
130         // FIXME: handle absolute paths and other versions
131         if (strcmp(filename, "libGL.so") == 0 ||
132             strcmp(filename, "libGL.so.1") == 0) {
133             // Use the true libGL.so handle instead of RTLD_NEXT from now on
134             libgl_handle = handle;
135
136             // Get the file path for our shared object, and use it instead
137             static int dummy = 0xdeedbeef;
138             Dl_info info;
139             if (dladdr(&dummy, &info)) {
140                 OS::DebugMessage("apitrace: redirecting dlopen(\"%s\", 0x%x)\n", filename, flag);
141                 handle = __dlopen(info.dli_fname, flag);
142             } else {
143                 OS::DebugMessage("warning: dladdr() failed\n");
144             }
145         }
146     }
147
148     return handle;
149 }
150
151 } /* extern "C" */
152
153
154 /*
155  * Lookup a libGL symbol
156  */
157 static void * __dlsym(const char *symbol)
158 {
159     void *result;
160
161     if (!libgl_handle) {
162         /*
163          * Try to use whatever libGL.so the library is linked against.
164          */
165         result = dlsym(RTLD_NEXT, symbol);
166         if (result) {
167             libgl_handle = RTLD_NEXT;
168             return result;
169         }
170
171         /*
172          * The app doesn't directly link against libGL.so, nor does it directly
173          * dlopen it.  So we have to load it ourselves.
174          */
175         libgl_handle = __dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
176         if (!libgl_handle) {
177             OS::DebugMessage("error: couldn't find libGL.so\n");
178             return NULL;
179         }
180     }
181
182     return dlsym(libgl_handle, symbol);
183 }
184
185
186 '''