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