5509597e0b293a46bbb7623d7b61235d09d74ee7
[lttng-ust.git] / liblttng-ust-dl / lttng-ust-dl.c
1 /*
2 * Copyright (C) 2013 Paul Woegerer <paul.woegerer@mentor.com>
3 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; version 2.1 of
9 * the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #define _LGPL_SOURCE
22 #include <limits.h>
23 #include <stdio.h>
24 #include <stdint.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include <lttng/ust-dlfcn.h>
29 #include <lttng/ust-elf.h>
30 #include <lttng/ust-events.h>
31 #include <helper.h>
32 #include "usterr-signal-safe.h"
33
34 /* Include link.h last else it conflicts with ust-dlfcn. */
35 #include <link.h>
36
37 #define TRACEPOINT_DEFINE
38 #include "ust_dl.h"
39
40 static void *(*__lttng_ust_plibc_dlopen)(const char *filename, int flags);
41 #ifdef HAVE_DLMOPEN
42 static void *(*__lttng_ust_plibc_dlmopen)(Lmid_t nsid, const char *filename,
43 int flags);
44 #endif
45 static int (*__lttng_ust_plibc_dlclose)(void *handle);
46
47 static
48 void *_lttng_ust_dl_libc_dlopen(const char *filename, int flags)
49 {
50 if (!__lttng_ust_plibc_dlopen) {
51 __lttng_ust_plibc_dlopen = dlsym(RTLD_NEXT, "dlopen");
52 if (!__lttng_ust_plibc_dlopen) {
53 fprintf(stderr, "%s\n", dlerror());
54 return NULL;
55 }
56 }
57 return __lttng_ust_plibc_dlopen(filename, flags);
58 }
59
60 #ifdef HAVE_DLMOPEN
61 static
62 void *_lttng_ust_dl_libc_dlmopen(Lmid_t nsid, const char *filename,
63 int flags)
64 {
65 if (!__lttng_ust_plibc_dlmopen) {
66 __lttng_ust_plibc_dlmopen = dlsym(RTLD_NEXT, "dlmopen");
67 if (!__lttng_ust_plibc_dlmopen) {
68 fprintf(stderr, "%s\n", dlerror());
69 return NULL;
70 }
71 }
72 return __lttng_ust_plibc_dlmopen(nsid, filename, flags);
73 }
74 #endif
75
76 static
77 int _lttng_ust_dl_libc_dlclose(void *handle)
78 {
79 if (!__lttng_ust_plibc_dlclose) {
80 __lttng_ust_plibc_dlclose = dlsym(RTLD_NEXT, "dlclose");
81 if (!__lttng_ust_plibc_dlclose) {
82 fprintf(stderr, "%s\n", dlerror());
83 return -1;
84 }
85 }
86 return __lttng_ust_plibc_dlclose(handle);
87 }
88
89 static
90 void lttng_ust_dl_dlopen(void *so_base, const char *so_name,
91 int flags, void *ip)
92 {
93 char resolved_path[PATH_MAX];
94 struct lttng_ust_elf *elf;
95 uint64_t memsz;
96 uint8_t *build_id = NULL;
97 size_t build_id_len;
98 char *dbg_file = NULL;
99 uint32_t crc;
100 int has_build_id = 0, has_debug_link = 0;
101 int ret;
102
103 if (!realpath(so_name, resolved_path)) {
104 ERR("could not resolve path '%s'", so_name);
105 return;
106 }
107
108 elf = lttng_ust_elf_create(resolved_path);
109 if (!elf) {
110 ERR("could not access file %s", resolved_path);
111 return;
112 }
113
114 ret = lttng_ust_elf_get_memsz(elf, &memsz);
115 if (ret) {
116 goto end;
117 }
118 ret = lttng_ust_elf_get_build_id(
119 elf, &build_id, &build_id_len, &has_build_id);
120 if (ret) {
121 goto end;
122 }
123 ret = lttng_ust_elf_get_debug_link(
124 elf, &dbg_file, &crc, &has_debug_link);
125 if (ret) {
126 goto end;
127 }
128
129 tracepoint(lttng_ust_dl, dlopen,
130 ip, so_base, resolved_path, flags, memsz,
131 has_build_id, has_debug_link);
132
133 if (has_build_id) {
134 tracepoint(lttng_ust_dl, build_id,
135 ip, so_base, build_id, build_id_len);
136 }
137
138 if (has_debug_link) {
139 tracepoint(lttng_ust_dl, debug_link,
140 ip, so_base, dbg_file, crc);
141 }
142
143 end:
144 free(dbg_file);
145 free(build_id);
146 lttng_ust_elf_destroy(elf);
147 return;
148 }
149
150 #ifdef HAVE_DLMOPEN
151 static
152 void lttng_ust_dl_dlmopen(void *so_base, Lmid_t nsid, const char *so_name,
153 int flags, void *ip)
154 {
155 char resolved_path[PATH_MAX];
156 struct lttng_ust_elf *elf;
157 uint64_t memsz;
158 uint8_t *build_id = NULL;
159 size_t build_id_len;
160 char *dbg_file = NULL;
161 uint32_t crc;
162 int has_build_id = 0, has_debug_link = 0;
163 int ret;
164
165 if (!realpath(so_name, resolved_path)) {
166 ERR("could not resolve path '%s'", so_name);
167 return;
168 }
169
170 elf = lttng_ust_elf_create(resolved_path);
171 if (!elf) {
172 ERR("could not access file %s", resolved_path);
173 return;
174 }
175
176 ret = lttng_ust_elf_get_memsz(elf, &memsz);
177 if (ret) {
178 goto end;
179 }
180 ret = lttng_ust_elf_get_build_id(
181 elf, &build_id, &build_id_len, &has_build_id);
182 if (ret) {
183 goto end;
184 }
185 ret = lttng_ust_elf_get_debug_link(
186 elf, &dbg_file, &crc, &has_debug_link);
187 if (ret) {
188 goto end;
189 }
190
191 tracepoint(lttng_ust_dl, dlmopen,
192 ip, so_base, nsid, resolved_path, flags, memsz,
193 has_build_id, has_debug_link);
194
195 if (has_build_id) {
196 tracepoint(lttng_ust_dl, build_id,
197 ip, so_base, build_id, build_id_len);
198 }
199
200 if (has_debug_link) {
201 tracepoint(lttng_ust_dl, debug_link,
202 ip, so_base, dbg_file, crc);
203 }
204
205 end:
206 free(dbg_file);
207 free(build_id);
208 lttng_ust_elf_destroy(elf);
209 return;
210 }
211 #endif
212
213 void *dlopen(const char *filename, int flags)
214 {
215 void *handle;
216
217 handle = _lttng_ust_dl_libc_dlopen(filename, flags);
218 if (__tracepoint_ptrs_registered && handle) {
219 struct link_map *p = NULL;
220 int ret;
221
222 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
223 if (ret != -1 && p != NULL && p->l_addr != 0) {
224 lttng_ust_dl_dlopen((void *) p->l_addr,
225 p->l_name, flags, LTTNG_UST_CALLER_IP());
226 }
227 }
228 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
229 return handle;
230 }
231
232 #ifdef HAVE_DLMOPEN
233 void *dlmopen(Lmid_t nsid, const char *filename, int flags)
234 {
235 void *handle;
236
237 handle = _lttng_ust_dl_libc_dlmopen(nsid, filename, flags);
238 if (__tracepoint_ptrs_registered && handle) {
239 struct link_map *p = NULL;
240 int ret;
241
242 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
243 if (ret != -1 && p != NULL && p->l_addr != 0) {
244 lttng_ust_dl_dlmopen((void *) p->l_addr,
245 nsid, p->l_name, flags,
246 LTTNG_UST_CALLER_IP());
247 }
248 }
249 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
250 return handle;
251
252 }
253 #endif
254
255 int dlclose(void *handle)
256 {
257 int ret;
258
259 if (__tracepoint_ptrs_registered) {
260 struct link_map *p = NULL;
261
262 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
263 if (ret != -1 && p != NULL && p->l_addr != 0) {
264 tracepoint(lttng_ust_dl, dlclose,
265 LTTNG_UST_CALLER_IP(),
266 (void *) p->l_addr);
267 }
268 }
269 ret = _lttng_ust_dl_libc_dlclose(handle);
270 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
271 return ret;
272 }
This page took 0.033469 seconds and 3 git commands to generate.