blob: 456fcc42e24c91a0d4eefa669ec7fbab6efb207c [file] [log] [blame]
José Fonseca1cfd89b2011-12-01 21:09:57 +00001/**************************************************************************
2 *
3 * Copyright 2011 Jose Fonseca
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#include "glproc.hpp"
José Fonsecae91f5bc2014-07-17 20:42:35 +010028#include "os.hpp"
Rolan Reznik3ca4dff2016-02-13 22:47:18 +020029#include "os_string.hpp"
José Fonseca1cfd89b2011-12-01 21:09:57 +000030
31
32#if !defined(_WIN32)
José Fonseca2dc8ebe2011-12-03 11:00:32 +000033#include <unistd.h> // for symlink
Alexander Monakovd6aa74c2013-05-03 21:03:27 +040034#include "dlopen.hpp"
José Fonseca1cfd89b2011-12-01 21:09:57 +000035#endif
36
37
38/*
39 * Handle to the true OpenGL library.
40 */
41#if defined(_WIN32)
José Fonseca3947e362012-04-20 21:04:43 +010042HMODULE _libGlHandle = NULL;
José Fonseca1cfd89b2011-12-01 21:09:57 +000043#else
José Fonseca632a78d2012-04-19 07:18:59 +010044void *_libGlHandle = NULL;
José Fonseca1cfd89b2011-12-01 21:09:57 +000045#endif
46
47
48
49#if defined(_WIN32)
50
51void *
José Fonseca632a78d2012-04-19 07:18:59 +010052_getPublicProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +000053{
José Fonseca632a78d2012-04-19 07:18:59 +010054 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +000055 char szDll[MAX_PATH] = {0};
56
57 if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
58 return NULL;
59 }
60
José Fonseca1a24faa2014-05-23 11:16:41 +010061 strcat(szDll, "\\opengl32.dll");
José Fonseca1cfd89b2011-12-01 21:09:57 +000062
José Fonseca632a78d2012-04-19 07:18:59 +010063 _libGlHandle = LoadLibraryA(szDll);
64 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +000065 os::log("apitrace: error: couldn't load %s\n", szDll);
66 return NULL;
67 }
68 }
69
José Fonseca632a78d2012-04-19 07:18:59 +010070 return (void *)GetProcAddress(_libGlHandle, procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +000071}
72
73
74void *
José Fonseca632a78d2012-04-19 07:18:59 +010075_getPrivateProcAddress(const char *procName) {
76 return (void *)_wglGetProcAddress(procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +000077}
78
79
80#elif defined(__APPLE__)
81
82
83/*
84 * Path to the true OpenGL framework
85 */
86static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework/OpenGL";
87
88
89/*
90 * Lookup a libGL symbol
91 */
José Fonseca632a78d2012-04-19 07:18:59 +010092void * _libgl_sym(const char *symbol)
José Fonseca1cfd89b2011-12-01 21:09:57 +000093{
94 void *result;
95
José Fonseca632a78d2012-04-19 07:18:59 +010096 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +000097 /*
98 * Unfortunately we can't just dlopen the true dynamic library because
99 * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for
100 * absolute paths. So we create a temporary symlink, and dlopen that
101 * instead.
102 */
103
Rolan Reznik3ca4dff2016-02-13 22:47:18 +0200104 os::String temp_template = os::getTemporaryDirectoryPath();
105 temp_template.append("tmp.XXXXXX");
106 char *temp_filename = temp_template.buf(temp_template.length() + 1);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000107
108 if (mktemp(temp_filename) != NULL) {
109 if (symlink(libgl_filename, temp_filename) == 0) {
José Fonseca632a78d2012-04-19 07:18:59 +0100110 _libGlHandle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000111 remove(temp_filename);
112 }
113 }
114
José Fonseca632a78d2012-04-19 07:18:59 +0100115 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +0000116 os::log("apitrace: error: couldn't load %s\n", libgl_filename);
117 os::abort();
118 return NULL;
119 }
120 }
121
José Fonseca632a78d2012-04-19 07:18:59 +0100122 result = dlsym(_libGlHandle, symbol);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000123
José Fonseca39879632012-04-14 22:26:09 +0100124#if 0
125 if (result && result == dlsym(RTLD_SELF, symbol)) {
José Fonseca1cfd89b2011-12-01 21:09:57 +0000126 os::log("apitrace: error: symbol lookup recursion\n");
127 os::abort();
128 return NULL;
129 }
José Fonseca39879632012-04-14 22:26:09 +0100130#endif
José Fonseca1cfd89b2011-12-01 21:09:57 +0000131
132 return result;
133}
134
135
136void *
José Fonseca632a78d2012-04-19 07:18:59 +0100137_getPublicProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000138{
José Fonseca632a78d2012-04-19 07:18:59 +0100139 return _libgl_sym(procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000140}
141
142void *
José Fonseca632a78d2012-04-19 07:18:59 +0100143_getPrivateProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000144{
José Fonseca632a78d2012-04-19 07:18:59 +0100145 return _libgl_sym(procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000146}
147
148
149#else
150
Gleb Mazovetskiyf917a322019-12-13 13:39:19 +0000151#ifndef RTLD_DEEPBIND
152#define RTLD_DEEPBIND 0
153#endif
José Fonseca1cfd89b2011-12-01 21:09:57 +0000154
José Fonseca7700f742013-06-15 11:31:53 +0100155static inline void
156logSymbol(const char *name, void *ptr) {
157 if (0) {
158 if (ptr) {
159 Dl_info info;
160 if (ptr && dladdr(ptr, &info)) {
161 os::log("apitrace: %s -> \"%s\"\n", name, info.dli_fname);
162 }
163 } else {
164 os::log("apitrace: %s -> NULL\n", name);
165 }
166 }
167}
168
169
José Fonseca1cfd89b2011-12-01 21:09:57 +0000170/*
José Fonseca1cfd89b2011-12-01 21:09:57 +0000171 * Lookup a libGL symbol
172 */
José Fonseca632a78d2012-04-19 07:18:59 +0100173void * _libgl_sym(const char *symbol)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000174{
175 void *result;
176
José Fonseca632a78d2012-04-19 07:18:59 +0100177 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +0000178 /*
179 * The app doesn't directly link against libGL.so, nor does it directly
180 * dlopen it. So we have to load it ourselves.
181 */
182
183 const char * libgl_filename = getenv("TRACE_LIBGL");
184
185 if (!libgl_filename) {
186 /*
187 * Try to use whatever libGL.so the library is linked against.
188 */
189
190 result = dlsym(RTLD_NEXT, symbol);
191 if (result) {
José Fonseca632a78d2012-04-19 07:18:59 +0100192 _libGlHandle = RTLD_NEXT;
José Fonseca1cfd89b2011-12-01 21:09:57 +0000193 return result;
194 }
195
196 libgl_filename = "libGL.so.1";
197 }
198
199 /*
200 * It would have been preferable to use RTLD_LOCAL to ensure that the
201 * application can never access libGL.so symbols directly, but this
202 * won't work, given libGL.so often loads a driver specific SO and
203 * exposes symbols to it.
204 */
205
George Kyriazis63194b22017-06-01 16:23:16 +0100206 _libGlHandle = _dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY | RTLD_DEEPBIND);
José Fonseca632a78d2012-04-19 07:18:59 +0100207 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +0000208 os::log("apitrace: error: couldn't find libGL.so\n");
209 return NULL;
210 }
211 }
212
José Fonseca0e725472014-05-23 23:24:13 +0100213 result = dlsym(_libGlHandle, symbol);
José Fonseca7700f742013-06-15 11:31:53 +0100214
215 logSymbol(symbol, result);
216
217 return result;
José Fonseca1cfd89b2011-12-01 21:09:57 +0000218}
219
220
221void *
José Fonseca632a78d2012-04-19 07:18:59 +0100222_getPublicProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000223{
José Fonseca632a78d2012-04-19 07:18:59 +0100224 return _libgl_sym(procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000225}
226
227void *
José Fonseca632a78d2012-04-19 07:18:59 +0100228_getPrivateProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000229{
José Fonseca632a78d2012-04-19 07:18:59 +0100230 return (void *)_glXGetProcAddressARB((const GLubyte *)procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000231}
232
233
234#endif
235