8baf9ee3ca2f58ab84bc0a8a8fcc55bfda2c4e25
[lttng-ust.git] / liblttng-ust-dl / ustdl.c
1 /*
2 * Copyright (C) 2013 Paul Woegerer <paul.woegerer@mentor.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; version 2.1 of
7 * the License.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #define _GNU_SOURCE
20 #include <inttypes.h>
21 #include <dlfcn.h>
22 #include <link.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <signal.h>
26 #include <sched.h>
27 #include <stdarg.h>
28 #include "usterr.h"
29
30 #include <lttng/ust-compiler.h>
31 #include <lttng/ust.h>
32
33 static void *(*__lttng_ust_plibc_dlopen)(const char *filename, int flag);
34 static int (*__lttng_ust_plibc_dlclose)(void *handle);
35 static void *__lttng_ust_baddr_handle;
36
37 static
38 void *_lttng_ust_dl_libc_dlopen(const char *filename, int flag)
39 {
40 if (!__lttng_ust_plibc_dlopen) {
41 __lttng_ust_plibc_dlopen = dlsym(RTLD_NEXT, "dlopen");
42 if (__lttng_ust_plibc_dlopen == NULL) {
43 fprintf(stderr, "%s\n", dlerror());
44 return NULL;
45 }
46 }
47 return __lttng_ust_plibc_dlopen(filename, flag);
48 }
49
50 static
51 int _lttng_ust_dl_libc_dlclose(void *handle)
52 {
53 if (!__lttng_ust_plibc_dlclose) {
54 __lttng_ust_plibc_dlclose = dlsym(RTLD_NEXT, "dlclose");
55 if (__lttng_ust_plibc_dlclose == NULL) {
56 fprintf(stderr, "%s\n", dlerror());
57 return -1;
58 }
59 }
60 return __lttng_ust_plibc_dlclose(handle);
61 }
62
63 static
64 void *lttng_ust_baddr_handle(void)
65 {
66 if (!__lttng_ust_baddr_handle) {
67 __lttng_ust_baddr_handle = _lttng_ust_dl_libc_dlopen(
68 "liblttng-ust-baddr.so.0", RTLD_NOW | RTLD_GLOBAL);
69 if (__lttng_ust_baddr_handle == NULL)
70 fprintf(stderr, "%s\n", dlerror());
71 }
72 return __lttng_ust_baddr_handle;
73 }
74
75 static
76 int lttng_ust_baddr_push(void *so_base, const char *so_name)
77 {
78 static int
79 (*lttng_ust_baddr_push_fn)(void *so_base, const char *so_name);
80 if (!lttng_ust_baddr_push_fn) {
81 void *baddr_handle = lttng_ust_baddr_handle();
82 if (baddr_handle) {
83 lttng_ust_baddr_push_fn = dlsym(baddr_handle,
84 "lttng_ust_push_baddr");
85 if (lttng_ust_baddr_push_fn == NULL)
86 fprintf(stderr, "%s\n", dlerror());
87 }
88 if (!lttng_ust_baddr_push_fn)
89 return -1;
90 }
91 return lttng_ust_baddr_push_fn(so_base, so_name);
92 }
93
94 static
95 int lttng_ust_baddr_pop(void *so_base)
96 {
97 static int
98 (*lttng_ust_baddr_pop_fn)(void *so_base);
99 if (!lttng_ust_baddr_pop_fn) {
100 void *baddr_handle = lttng_ust_baddr_handle();
101 if (baddr_handle) {
102 lttng_ust_baddr_pop_fn = dlsym(baddr_handle,
103 "lttng_ust_pop_baddr");
104 if (lttng_ust_baddr_pop_fn == NULL)
105 fprintf(stderr, "%s\n", dlerror());
106 }
107 if (!lttng_ust_baddr_pop_fn)
108 return -1;
109 }
110 return lttng_ust_baddr_pop_fn(so_base);
111 }
112
113 void *dlopen(const char *filename, int flag)
114 {
115 void *handle = _lttng_ust_dl_libc_dlopen(filename, flag);
116 if (handle) {
117 struct link_map *p = NULL;
118 if (dlinfo(handle, RTLD_DI_LINKMAP, &p) != -1 && p != NULL
119 && p->l_addr != 0)
120 lttng_ust_baddr_push((void *) p->l_addr, p->l_name);
121 }
122 return handle;
123 }
124
125 int dlclose(void *handle)
126 {
127 if (handle) {
128 struct link_map *p = NULL;
129 if (dlinfo(handle, RTLD_DI_LINKMAP, &p) != -1 && p != NULL
130 && p->l_addr != 0)
131 lttng_ust_baddr_pop((void *) p->l_addr);
132 }
133 return _lttng_ust_dl_libc_dlclose(handle);
134 }
135
136 static void __attribute__((destructor))
137 lttng_ust_baddr_handle_fini(void);
138 static void
139 lttng_ust_baddr_handle_fini(void)
140 {
141 if (__lttng_ust_baddr_handle) {
142 int ret = _lttng_ust_dl_libc_dlclose(__lttng_ust_baddr_handle);
143 if (ret)
144 fprintf(stderr, "%s\n", dlerror());
145 }
146 }
This page took 0.032569 seconds and 3 git commands to generate.