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"
24 #include "common/events.h"
26 /* Include link.h last else it conflicts with ust-dlfcn. */
29 #define TRACEPOINT_DEFINE
32 static void *(*__lttng_ust_plibc_dlopen
)(const char *filename
, int flags
);
34 static void *(*__lttng_ust_plibc_dlmopen
)(Lmid_t nsid
, const char *filename
,
37 static int (*__lttng_ust_plibc_dlclose
)(void *handle
);
40 void *_lttng_ust_dl_libc_dlopen(const char *filename
, int flags
)
42 if (!__lttng_ust_plibc_dlopen
) {
43 __lttng_ust_plibc_dlopen
= dlsym(RTLD_NEXT
, "dlopen");
44 if (!__lttng_ust_plibc_dlopen
) {
45 fprintf(stderr
, "%s\n", dlerror());
49 return __lttng_ust_plibc_dlopen(filename
, flags
);
54 void *_lttng_ust_dl_libc_dlmopen(Lmid_t nsid
, const char *filename
,
57 if (!__lttng_ust_plibc_dlmopen
) {
58 __lttng_ust_plibc_dlmopen
= dlsym(RTLD_NEXT
, "dlmopen");
59 if (!__lttng_ust_plibc_dlmopen
) {
60 fprintf(stderr
, "%s\n", dlerror());
64 return __lttng_ust_plibc_dlmopen(nsid
, filename
, flags
);
69 int _lttng_ust_dl_libc_dlclose(void *handle
)
71 if (!__lttng_ust_plibc_dlclose
) {
72 __lttng_ust_plibc_dlclose
= dlsym(RTLD_NEXT
, "dlclose");
73 if (!__lttng_ust_plibc_dlclose
) {
74 fprintf(stderr
, "%s\n", dlerror());
78 return __lttng_ust_plibc_dlclose(handle
);
82 void lttng_ust_dl_dlopen(void *so_base
, const char *so_name
,
85 char resolved_path
[PATH_MAX
];
86 struct lttng_ust_elf
*elf
;
88 uint8_t *build_id
= NULL
;
90 char *dbg_file
= NULL
;
92 int has_build_id
= 0, has_debug_link
= 0;
95 if (!realpath(so_name
, resolved_path
)) {
96 ERR("could not resolve path '%s'", so_name
);
100 elf
= lttng_ust_elf_create(resolved_path
);
102 ERR("could not access file %s", resolved_path
);
106 ret
= lttng_ust_elf_get_memsz(elf
, &memsz
);
110 ret
= lttng_ust_elf_get_build_id(
111 elf
, &build_id
, &build_id_len
, &has_build_id
);
115 ret
= lttng_ust_elf_get_debug_link(
116 elf
, &dbg_file
, &crc
, &has_debug_link
);
121 tracepoint(lttng_ust_dl
, dlopen
,
122 ip
, so_base
, resolved_path
, flags
, memsz
,
123 has_build_id
, has_debug_link
);
126 tracepoint(lttng_ust_dl
, build_id
,
127 ip
, so_base
, build_id
, build_id_len
);
130 if (has_debug_link
) {
131 tracepoint(lttng_ust_dl
, debug_link
,
132 ip
, so_base
, dbg_file
, crc
);
138 lttng_ust_elf_destroy(elf
);
144 void lttng_ust_dl_dlmopen(void *so_base
, Lmid_t nsid
, const char *so_name
,
147 char resolved_path
[PATH_MAX
];
148 struct lttng_ust_elf
*elf
;
150 uint8_t *build_id
= NULL
;
152 char *dbg_file
= NULL
;
154 int has_build_id
= 0, has_debug_link
= 0;
157 if (!realpath(so_name
, resolved_path
)) {
158 ERR("could not resolve path '%s'", so_name
);
162 elf
= lttng_ust_elf_create(resolved_path
);
164 ERR("could not access file %s", resolved_path
);
168 ret
= lttng_ust_elf_get_memsz(elf
, &memsz
);
172 ret
= lttng_ust_elf_get_build_id(
173 elf
, &build_id
, &build_id_len
, &has_build_id
);
177 ret
= lttng_ust_elf_get_debug_link(
178 elf
, &dbg_file
, &crc
, &has_debug_link
);
183 tracepoint(lttng_ust_dl
, dlmopen
,
184 ip
, so_base
, nsid
, resolved_path
, flags
, memsz
,
185 has_build_id
, has_debug_link
);
188 tracepoint(lttng_ust_dl
, build_id
,
189 ip
, so_base
, build_id
, build_id_len
);
192 if (has_debug_link
) {
193 tracepoint(lttng_ust_dl
, debug_link
,
194 ip
, so_base
, dbg_file
, crc
);
200 lttng_ust_elf_destroy(elf
);
205 void *dlopen(const char *filename
, int flags
)
209 handle
= _lttng_ust_dl_libc_dlopen(filename
, flags
);
210 if (__tracepoint_ptrs_registered
&& handle
) {
211 struct link_map
*p
= NULL
;
214 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
215 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
216 lttng_ust_dl_dlopen((void *) p
->l_addr
,
217 p
->l_name
, flags
, LTTNG_UST_CALLER_IP());
220 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
225 void *dlmopen(Lmid_t nsid
, const char *filename
, int flags
)
229 handle
= _lttng_ust_dl_libc_dlmopen(nsid
, filename
, flags
);
230 if (__tracepoint_ptrs_registered
&& handle
) {
231 struct link_map
*p
= NULL
;
234 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
235 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
236 lttng_ust_dl_dlmopen((void *) p
->l_addr
,
237 nsid
, p
->l_name
, flags
,
238 LTTNG_UST_CALLER_IP());
241 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
247 int dlclose(void *handle
)
251 if (__tracepoint_ptrs_registered
) {
252 struct link_map
*p
= NULL
;
254 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
255 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
256 tracepoint(lttng_ust_dl
, dlclose
,
257 LTTNG_UST_CALLER_IP(),
261 ret
= _lttng_ust_dl_libc_dlclose(handle
);
262 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());