2 * SPDX-License-Identifier: LGPL-2.1-only
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>
13 #include <sys/types.h>
16 #include <ust-dlfcn.h>
17 #include <lttng/ust-elf.h>
18 #include <lttng/ust-events.h>
19 #include <ust-helper.h>
20 #include "usterr-signal-safe.h"
22 /* Include link.h last else it conflicts with ust-dlfcn. */
25 #define TRACEPOINT_DEFINE
28 static void *(*__lttng_ust_plibc_dlopen
)(const char *filename
, int flags
);
30 static void *(*__lttng_ust_plibc_dlmopen
)(Lmid_t nsid
, const char *filename
,
33 static int (*__lttng_ust_plibc_dlclose
)(void *handle
);
36 void *_lttng_ust_dl_libc_dlopen(const char *filename
, int flags
)
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());
45 return __lttng_ust_plibc_dlopen(filename
, flags
);
50 void *_lttng_ust_dl_libc_dlmopen(Lmid_t nsid
, const char *filename
,
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());
60 return __lttng_ust_plibc_dlmopen(nsid
, filename
, flags
);
65 int _lttng_ust_dl_libc_dlclose(void *handle
)
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());
74 return __lttng_ust_plibc_dlclose(handle
);
78 void lttng_ust_dl_dlopen(void *so_base
, const char *so_name
,
81 char resolved_path
[PATH_MAX
];
82 struct lttng_ust_elf
*elf
;
84 uint8_t *build_id
= NULL
;
86 char *dbg_file
= NULL
;
88 int has_build_id
= 0, has_debug_link
= 0;
91 if (!realpath(so_name
, resolved_path
)) {
92 ERR("could not resolve path '%s'", so_name
);
96 elf
= lttng_ust_elf_create(resolved_path
);
98 ERR("could not access file %s", resolved_path
);
102 ret
= lttng_ust_elf_get_memsz(elf
, &memsz
);
106 ret
= lttng_ust_elf_get_build_id(
107 elf
, &build_id
, &build_id_len
, &has_build_id
);
111 ret
= lttng_ust_elf_get_debug_link(
112 elf
, &dbg_file
, &crc
, &has_debug_link
);
117 tracepoint(lttng_ust_dl
, dlopen
,
118 ip
, so_base
, resolved_path
, flags
, memsz
,
119 has_build_id
, has_debug_link
);
122 tracepoint(lttng_ust_dl
, build_id
,
123 ip
, so_base
, build_id
, build_id_len
);
126 if (has_debug_link
) {
127 tracepoint(lttng_ust_dl
, debug_link
,
128 ip
, so_base
, dbg_file
, crc
);
134 lttng_ust_elf_destroy(elf
);
140 void lttng_ust_dl_dlmopen(void *so_base
, Lmid_t nsid
, const char *so_name
,
143 char resolved_path
[PATH_MAX
];
144 struct lttng_ust_elf
*elf
;
146 uint8_t *build_id
= NULL
;
148 char *dbg_file
= NULL
;
150 int has_build_id
= 0, has_debug_link
= 0;
153 if (!realpath(so_name
, resolved_path
)) {
154 ERR("could not resolve path '%s'", so_name
);
158 elf
= lttng_ust_elf_create(resolved_path
);
160 ERR("could not access file %s", resolved_path
);
164 ret
= lttng_ust_elf_get_memsz(elf
, &memsz
);
168 ret
= lttng_ust_elf_get_build_id(
169 elf
, &build_id
, &build_id_len
, &has_build_id
);
173 ret
= lttng_ust_elf_get_debug_link(
174 elf
, &dbg_file
, &crc
, &has_debug_link
);
179 tracepoint(lttng_ust_dl
, dlmopen
,
180 ip
, so_base
, nsid
, resolved_path
, flags
, memsz
,
181 has_build_id
, has_debug_link
);
184 tracepoint(lttng_ust_dl
, build_id
,
185 ip
, so_base
, build_id
, build_id_len
);
188 if (has_debug_link
) {
189 tracepoint(lttng_ust_dl
, debug_link
,
190 ip
, so_base
, dbg_file
, crc
);
196 lttng_ust_elf_destroy(elf
);
201 void *dlopen(const char *filename
, int flags
)
205 handle
= _lttng_ust_dl_libc_dlopen(filename
, flags
);
206 if (__tracepoint_ptrs_registered
&& handle
) {
207 struct link_map
*p
= NULL
;
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());
216 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
221 void *dlmopen(Lmid_t nsid
, const char *filename
, int flags
)
225 handle
= _lttng_ust_dl_libc_dlmopen(nsid
, filename
, flags
);
226 if (__tracepoint_ptrs_registered
&& handle
) {
227 struct link_map
*p
= NULL
;
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());
237 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
243 int dlclose(void *handle
)
247 if (__tracepoint_ptrs_registered
) {
248 struct link_map
*p
= NULL
;
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(),
257 ret
= _lttng_ust_dl_libc_dlclose(handle
);
258 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());