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