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 LTTNG_UST_TRACEPOINT_HIDDEN_DEFINITION
30 #define LTTNG_UST_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_libc_dlopen(const char *filename
, int flags
)
43 if (!__lttng_ust_plibc_dlopen
) {
44 __lttng_ust_plibc_dlopen
= dlsym(RTLD_NEXT
, "dlopen");
45 if (!__lttng_ust_plibc_dlopen
) {
46 fprintf(stderr
, "%s\n", dlerror());
50 return __lttng_ust_plibc_dlopen(filename
, flags
);
55 void *_lttng_ust_dl_libc_dlmopen(Lmid_t nsid
, const char *filename
,
58 if (!__lttng_ust_plibc_dlmopen
) {
59 __lttng_ust_plibc_dlmopen
= dlsym(RTLD_NEXT
, "dlmopen");
60 if (!__lttng_ust_plibc_dlmopen
) {
61 fprintf(stderr
, "%s\n", dlerror());
65 return __lttng_ust_plibc_dlmopen(nsid
, filename
, flags
);
70 int _lttng_ust_dl_libc_dlclose(void *handle
)
72 if (!__lttng_ust_plibc_dlclose
) {
73 __lttng_ust_plibc_dlclose
= dlsym(RTLD_NEXT
, "dlclose");
74 if (!__lttng_ust_plibc_dlclose
) {
75 fprintf(stderr
, "%s\n", dlerror());
79 return __lttng_ust_plibc_dlclose(handle
);
83 void lttng_ust_dl_dlopen(void *so_base
, const char *so_name
,
86 char resolved_path
[PATH_MAX
];
87 struct lttng_ust_elf
*elf
;
89 uint8_t *build_id
= NULL
;
91 char *dbg_file
= NULL
;
93 int has_build_id
= 0, has_debug_link
= 0;
96 if (!realpath(so_name
, resolved_path
)) {
97 ERR("could not resolve path '%s'", so_name
);
101 elf
= lttng_ust_elf_create(resolved_path
);
103 ERR("could not access file %s", resolved_path
);
107 ret
= lttng_ust_elf_get_memsz(elf
, &memsz
);
111 ret
= lttng_ust_elf_get_build_id(
112 elf
, &build_id
, &build_id_len
, &has_build_id
);
116 ret
= lttng_ust_elf_get_debug_link(
117 elf
, &dbg_file
, &crc
, &has_debug_link
);
122 lttng_ust_tracepoint(lttng_ust_dl
, dlopen
,
123 ip
, so_base
, resolved_path
, flags
, memsz
,
124 has_build_id
, has_debug_link
);
127 lttng_ust_tracepoint(lttng_ust_dl
, build_id
,
128 ip
, so_base
, build_id
, build_id_len
);
131 if (has_debug_link
) {
132 lttng_ust_tracepoint(lttng_ust_dl
, debug_link
,
133 ip
, so_base
, dbg_file
, crc
);
139 lttng_ust_elf_destroy(elf
);
145 void lttng_ust_dl_dlmopen(void *so_base
, Lmid_t nsid
, const char *so_name
,
148 char resolved_path
[PATH_MAX
];
149 struct lttng_ust_elf
*elf
;
151 uint8_t *build_id
= NULL
;
153 char *dbg_file
= NULL
;
155 int has_build_id
= 0, has_debug_link
= 0;
158 if (!realpath(so_name
, resolved_path
)) {
159 ERR("could not resolve path '%s'", so_name
);
163 elf
= lttng_ust_elf_create(resolved_path
);
165 ERR("could not access file %s", resolved_path
);
169 ret
= lttng_ust_elf_get_memsz(elf
, &memsz
);
173 ret
= lttng_ust_elf_get_build_id(
174 elf
, &build_id
, &build_id_len
, &has_build_id
);
178 ret
= lttng_ust_elf_get_debug_link(
179 elf
, &dbg_file
, &crc
, &has_debug_link
);
184 lttng_ust_tracepoint(lttng_ust_dl
, dlmopen
,
185 ip
, so_base
, nsid
, resolved_path
, flags
, memsz
,
186 has_build_id
, has_debug_link
);
189 lttng_ust_tracepoint(lttng_ust_dl
, build_id
,
190 ip
, so_base
, build_id
, build_id_len
);
193 if (has_debug_link
) {
194 lttng_ust_tracepoint(lttng_ust_dl
, debug_link
,
195 ip
, so_base
, dbg_file
, crc
);
201 lttng_ust_elf_destroy(elf
);
206 void *dlopen(const char *filename
, int flags
)
210 handle
= _lttng_ust_dl_libc_dlopen(filename
, flags
);
211 if (lttng_ust_tracepoint_ptrs_registered
&& handle
) {
212 struct link_map
*p
= NULL
;
215 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
216 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
217 lttng_ust_dl_dlopen((void *) p
->l_addr
,
218 p
->l_name
, flags
, LTTNG_UST_CALLER_IP());
221 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
226 void *dlmopen(Lmid_t nsid
, const char *filename
, int flags
)
230 handle
= _lttng_ust_dl_libc_dlmopen(nsid
, filename
, flags
);
231 if (lttng_ust_tracepoint_ptrs_registered
&& handle
) {
232 struct link_map
*p
= NULL
;
235 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
236 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
237 lttng_ust_dl_dlmopen((void *) p
->l_addr
,
238 nsid
, p
->l_name
, flags
,
239 LTTNG_UST_CALLER_IP());
242 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
248 int dlclose(void *handle
)
252 if (lttng_ust_tracepoint_ptrs_registered
) {
253 struct link_map
*p
= NULL
;
255 ret
= dlinfo(handle
, RTLD_DI_LINKMAP
, &p
);
256 if (ret
!= -1 && p
!= NULL
&& p
->l_addr
!= 0) {
257 lttng_ust_tracepoint(lttng_ust_dl
, dlclose
,
258 LTTNG_UST_CALLER_IP(),
262 ret
= _lttng_ust_dl_libc_dlclose(handle
);
263 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());