blob: 118110f2362bac0431ab57fa0fac6f6d8d3ea084 [file] [log] [blame]
José Fonseca0e725472014-05-23 23:24:13 +01001/**************************************************************************
2 *
3 * Copyright 2014 VMware, Inc.
4 * Copyright 2011 Jose Fonseca
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 **************************************************************************/
26
27
28#include "os.hpp"
29
30
31#ifdef __GLIBC__
32
33
34#include <dlfcn.h>
35
36extern "C" void * __libc_dlopen_mode(const char * filename, int flag);
37extern "C" void * __libc_dlsym(void * handle, const char * symbol);
38
39
40/*
41 * Protect against dlsym interception.
42 *
43 * We implement the whole API, so we don't need to intercept dlsym -- dlopen is
44 * enough. However we need to protect against other dynamic libraries
45 * intercepting dlsym, to prevent infinite recursion,
46 *
47 * In particular the Steam Community Overlay exports dlsym. See also
48 * http://lists.freedesktop.org/archives/apitrace/2013-March/000573.html
49 */
50PRIVATE
51void *
52dlsym(void * handle, const char * symbol)
53{
54 /*
55 * We rely on glibc's internal __libc_dlsym. See also
56 * http://www.linuxforu.com/2011/08/lets-hook-a-library-function/
57 *
58 * Use use it to obtain the true dlsym. We don't use __libc_dlsym directly
59 * because it does not support things such as RTLD_NEXT.
60 */
61 typedef void * (*PFN_DLSYM)(void *, const char *);
62 static PFN_DLSYM dlsym_ptr = NULL;
63 if (!dlsym_ptr) {
64 void *libdl_handle = __libc_dlopen_mode("libdl.so.2", RTLD_LOCAL | RTLD_NOW);
65 if (libdl_handle) {
66 dlsym_ptr = (PFN_DLSYM)__libc_dlsym(libdl_handle, "dlsym");
67 }
68 if (!dlsym_ptr) {
69 os::log("apitrace: error: failed to look up real dlsym\n");
70 return NULL;
71 }
72 }
73
74 return dlsym_ptr(handle, symbol);
75}
76
77
78
79#endif /* __GLIBC__ */