Fix: pass private data to context callbacks
[lttng-ust.git] / liblttng-ust-dl / lttng-ust-dl.c
CommitLineData
b13d93c2 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-only
b13d93c2 3 *
c0c0989a
MJ
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>
b13d93c2
PW
7 */
8
1ddceb36 9#define _LGPL_SOURCE
13436238 10#include <limits.h>
8e2aed3f 11#include <stdio.h>
fb31eb73 12#include <stdint.h>
13436238 13#include <sys/types.h>
8e2aed3f
AB
14#include <unistd.h>
15
ae4b659d 16#include <ust-dlfcn.h>
2adb7ad2 17#include <ust-elf.h>
97c7c238 18#include <lttng/ust-events.h>
864a1eda 19#include <ust-helper.h>
eb2b066f 20#include "usterr-signal-safe.h"
b13d93c2 21
cbba5e04
MJ
22#include "../liblttng-ust/ust-events-internal.h"
23
8e2aed3f
AB
24/* Include link.h last else it conflicts with ust-dlfcn. */
25#include <link.h>
b13d93c2 26
13436238 27#define TRACEPOINT_DEFINE
6d4658aa 28#include "ust_dl.h"
13436238 29
7b0fdd83 30static void *(*__lttng_ust_plibc_dlopen)(const char *filename, int flags);
42330adc 31#ifdef HAVE_DLMOPEN
7b0fdd83
MD
32static void *(*__lttng_ust_plibc_dlmopen)(Lmid_t nsid, const char *filename,
33 int flags);
42330adc 34#endif
b13d93c2 35static int (*__lttng_ust_plibc_dlclose)(void *handle);
b13d93c2 36
465a0d04
MJ
37static
38void _lttng_ust_dl_init(void)
39 __attribute__((constructor));
40static
2b6f4374
MJ
41void _lttng_ust_dl_init(void)
42{
43 ust_err_init();
44}
45
b13d93c2 46static
7b0fdd83 47void *_lttng_ust_dl_libc_dlopen(const char *filename, int flags)
b13d93c2
PW
48{
49 if (!__lttng_ust_plibc_dlopen) {
50 __lttng_ust_plibc_dlopen = dlsym(RTLD_NEXT, "dlopen");
8e2aed3f 51 if (!__lttng_ust_plibc_dlopen) {
b13d93c2
PW
52 fprintf(stderr, "%s\n", dlerror());
53 return NULL;
54 }
55 }
7b0fdd83
MD
56 return __lttng_ust_plibc_dlopen(filename, flags);
57}
58
42330adc 59#ifdef HAVE_DLMOPEN
7b0fdd83
MD
60static
61void *_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);
b13d93c2 72}
42330adc 73#endif
b13d93c2
PW
74
75static
76int _lttng_ust_dl_libc_dlclose(void *handle)
77{
78 if (!__lttng_ust_plibc_dlclose) {
79 __lttng_ust_plibc_dlclose = dlsym(RTLD_NEXT, "dlclose");
8e2aed3f 80 if (!__lttng_ust_plibc_dlclose) {
b13d93c2
PW
81 fprintf(stderr, "%s\n", dlerror());
82 return -1;
83 }
84 }
85 return __lttng_ust_plibc_dlclose(handle);
86}
87
88static
7b0fdd83
MD
89void lttng_ust_dl_dlopen(void *so_base, const char *so_name,
90 int flags, void *ip)
b13d93c2 91{
13436238 92 char resolved_path[PATH_MAX];
8e2aed3f
AB
93 struct lttng_ust_elf *elf;
94 uint64_t memsz;
83215d66 95 uint8_t *build_id = NULL;
8e2aed3f 96 size_t build_id_len;
83215d66 97 char *dbg_file = NULL;
8e2aed3f
AB
98 uint32_t crc;
99 int has_build_id = 0, has_debug_link = 0;
100 int ret;
b13d93c2 101
13436238
PW
102 if (!realpath(so_name, resolved_path)) {
103 ERR("could not resolve path '%s'", so_name);
104 return;
b13d93c2 105 }
b13d93c2 106
8e2aed3f
AB
107 elf = lttng_ust_elf_create(resolved_path);
108 if (!elf) {
09026ccf 109 ERR("could not access file %s", resolved_path);
13436238 110 return;
b13d93c2 111 }
13436238 112
8e2aed3f
AB
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
6d4658aa 128 tracepoint(lttng_ust_dl, dlopen,
7b0fdd83 129 ip, so_base, resolved_path, flags, memsz,
c5c4fd82 130 has_build_id, has_debug_link);
8e2aed3f
AB
131
132 if (has_build_id) {
133 tracepoint(lttng_ust_dl, build_id,
134 ip, so_base, build_id, build_id_len);
8e2aed3f
AB
135 }
136
137 if (has_debug_link) {
138 tracepoint(lttng_ust_dl, debug_link,
139 ip, so_base, dbg_file, crc);
8e2aed3f
AB
140 }
141
142end:
83215d66
MD
143 free(dbg_file);
144 free(build_id);
8e2aed3f 145 lttng_ust_elf_destroy(elf);
13436238 146 return;
b13d93c2
PW
147}
148
42330adc 149#ifdef HAVE_DLMOPEN
7b0fdd83
MD
150static
151void 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) {
09026ccf 171 ERR("could not access file %s", resolved_path);
7b0fdd83
MD
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
204end:
205 free(dbg_file);
206 free(build_id);
207 lttng_ust_elf_destroy(elf);
208 return;
209}
42330adc 210#endif
7b0fdd83
MD
211
212void *dlopen(const char *filename, int flags)
b13d93c2 213{
8e2aed3f
AB
214 void *handle;
215
7b0fdd83 216 handle = _lttng_ust_dl_libc_dlopen(filename, flags);
bd703713 217 if (__tracepoint_ptrs_registered && handle) {
b13d93c2 218 struct link_map *p = NULL;
8e2aed3f
AB
219 int ret;
220
221 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
222 if (ret != -1 && p != NULL && p->l_addr != 0) {
97c7c238 223 lttng_ust_dl_dlopen((void *) p->l_addr,
7b0fdd83
MD
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
42330adc 231#ifdef HAVE_DLMOPEN
7b0fdd83
MD
232void *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,
171fcc6f 245 LTTNG_UST_CALLER_IP());
8e2aed3f 246 }
b13d93c2 247 }
97c7c238 248 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
b13d93c2 249 return handle;
7b0fdd83 250
b13d93c2 251}
42330adc 252#endif
b13d93c2
PW
253
254int dlclose(void *handle)
255{
97c7c238
MD
256 int ret;
257
e7953e6e 258 if (__tracepoint_ptrs_registered) {
b13d93c2 259 struct link_map *p = NULL;
8e2aed3f
AB
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,
171fcc6f 264 LTTNG_UST_CALLER_IP(),
8e2aed3f
AB
265 (void *) p->l_addr);
266 }
b13d93c2 267 }
97c7c238
MD
268 ret = _lttng_ust_dl_libc_dlclose(handle);
269 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
270 return ret;
b13d93c2 271}
This page took 0.039195 seconds and 4 git commands to generate.