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