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>
11 /* Has to be included first to override dlfcn.h */
12 #include <common/compat/dlfcn.h>
17 #include <sys/types.h>
20 #include "common/elf.h"
21 #include <lttng/ust-events.h>
22 #include "common/macros.h"
23 #include "common/logging.h"
25 #include "lib/lttng-ust/ust-events-internal.h"
27 /* Include link.h last else it conflicts with ust-dlfcn. */
30 #define TRACEPOINT_DEFINE
33 static void *(*__lttng_ust_plibc_dlopen
)(const char *filename
, int flags
);
35 static void *(*__lttng_ust_plibc_dlmopen
)(Lmid_t nsid
, const char *filename
,
38 static int (*__lttng_ust_plibc_dlclose
)(void *handle
);
41 void _lttng_ust_dl_init(void)
42 __attribute__((constructor
));
44 void _lttng_ust_dl_init(void)
50 void *_lttng_ust_dl_libc_dlopen(const char *filename
, int flags
)
52 if (!__lttng_ust_plibc_dlopen
) {
53 __lttng_ust_plibc_dlopen
= dlsym(RTLD_NEXT
, "dlopen");
54 if (!__lttng_ust_plibc_dlopen
) {
55 fprintf(stderr
, "%s\n", dlerror());
59 return __lttng_ust_plibc_dlopen(filename
, flags
);
64 void *_lttng_ust_dl_libc_dlmopen(Lmid_t nsid
, const char *filename
,
67 if (!__lttng_ust_plibc_dlmopen
) {
68 __lttng_ust_plibc_dlmopen
= dlsym(RTLD_NEXT
, "dlmopen");
69 if (!__lttng_ust_plibc_dlmopen
) {
70 fprintf(stderr
, "%s\n", dlerror());
74 return __lttng_ust_plibc_dlmopen(nsid
, filename
, flags
);
79 int _lttng_ust_dl_libc_dlclose(void *handle
)
81 if (!__lttng_ust_plibc_dlclose
) {
82 __lttng_ust_plibc_dlclose
= dlsym(RTLD_NEXT
, "dlclose");
83 if (!__lttng_ust_plibc_dlclose
) {
84 fprintf(stderr
, "%s\n", dlerror());
88 return __lttng_ust_plibc_dlclose(handle
);
92 void lttng_ust_dl_dlopen(void *so_base
, const char *so_name
,
95 char resolved_path
[PATH_MAX
];
96 struct lttng_ust_elf
*elf
;
98 uint8_t *build_id
= NULL
;
100 char *dbg_file
= NULL
;
102 int has_build_id
= 0, has_debug_link
= 0;
105 if (!realpath(so_name
, resolved_path
)) {
106 ERR("could not resolve path '%s'", so_name
);
110 elf
= lttng_ust_elf_create(resolved_path
);
112 ERR("could not access file %s", resolved_path
);
116 ret
= lttng_ust_elf_get_memsz(elf
, &memsz
);
120 ret
= lttng_ust_elf_get_build_id(
121 elf
, &build_id
, &build_id_len
, &has_build_id
);
125 ret
= lttng_ust_elf_get_debug_link(
126 elf
, &dbg_file
, &crc
, &has_debug_link
);
131 tracepoint(lttng_ust_dl
, dlopen
,
132 ip
, so_base
, resolved_path
, flags
, memsz
,
133 has_build_id
, has_debug_link
);
136 tracepoint(lttng_ust_dl
, build_id
,
137 ip
, so_base
, build_id
, build_id_len
);
140 if (has_debug_link
) {
141 tracepoint(lttng_ust_dl
, debug_link
,
142 ip
, so_base
, dbg_file
, crc
);
148 lttng_ust_elf_destroy(elf
);
154 void lttng_ust_dl_dlmopen(void *so_base
, Lmid_t nsid
, const char *so_name
,
157 char resolved_path
[PATH_MAX
];
158 struct lttng_ust_elf
*elf
;
160 uint8_t *build_id
= NULL
;
162 char *dbg_file
= NULL
;
164 int has_build_id
= 0, has_debug_link
= 0;
167 if (!realpath(so_name
, resolved_path
)) {
168 ERR("could not resolve path '%s'", so_name
);
172 elf
= lttng_ust_elf_create(resolved_path
);
174 ERR("could not access file %s", resolved_path
);
178 ret
= lttng_ust_elf_get_memsz(elf
, &memsz
);
182 ret
= lttng_ust_elf_get_build_id(
183 elf
, &build_id
, &build_id_len
, &has_build_id
);
187 ret
= lttng_ust_elf_get_debug_link(
188 elf
, &dbg_file
, &crc
, &has_debug_link
);
193 tracepoint(lttng_ust_dl
, dlmopen
,
194 ip
, so_base
, nsid
, resolved_path
, flags
, memsz
,
195 has_build_id
, has_debug_link
);
198 tracepoint(lttng_ust_dl
, build_id
,
199 ip
, so_base
, build_id
, build_id_len
);
202 if (has_debug_link
) {
203 tracepoint(lttng_ust_dl
, debug_link
,
204 ip
, so_base
, dbg_file
, crc
);
210 lttng_ust_elf_destroy(elf
);
215 void *dlopen(const char *filename
, int flags
)
219 handle
= _lttng_ust_dl_libc_dlopen(filename
, flags
);
220 if (__tracepoint_ptrs_registered
&& handle
) {
221 struct link_map
*p
= NULL
;
224 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
225 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
226 lttng_ust_dl_dlopen((void *) p
->l_addr
,
227 p
->l_name
, flags
, LTTNG_UST_CALLER_IP());
230 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
235 void *dlmopen(Lmid_t nsid
, const char *filename
, int flags
)
239 handle
= _lttng_ust_dl_libc_dlmopen(nsid
, filename
, flags
);
240 if (__tracepoint_ptrs_registered
&& handle
) {
241 struct link_map
*p
= NULL
;
244 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
245 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
246 lttng_ust_dl_dlmopen((void *) p
->l_addr
,
247 nsid
, p
->l_name
, flags
,
248 LTTNG_UST_CALLER_IP());
251 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
257 int dlclose(void *handle
)
261 if (__tracepoint_ptrs_registered
) {
262 struct link_map
*p
= NULL
;
264 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
265 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
266 tracepoint(lttng_ust_dl
, dlclose
,
267 LTTNG_UST_CALLER_IP(),
271 ret
= _lttng_ust_dl_libc_dlclose(handle
);
272 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());