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