Move getenv to libcommon
[lttng-ust.git] / src / lib / lttng-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
9d315d6d
MJ
10
11/* Has to be included first to override dlfcn.h */
12#include <common/compat/dlfcn.h>
13
13436238 14#include <limits.h>
8e2aed3f 15#include <stdio.h>
fb31eb73 16#include <stdint.h>
13436238 17#include <sys/types.h>
8e2aed3f
AB
18#include <unistd.h>
19
9d315d6d 20#include "common/elf.h"
97c7c238 21#include <lttng/ust-events.h>
9d315d6d
MJ
22#include "common/macros.h"
23#include "common/logging.h"
b13d93c2 24
6339062a 25#include "lib/lttng-ust/ust-events-internal.h"
cbba5e04 26
8e2aed3f
AB
27/* Include link.h last else it conflicts with ust-dlfcn. */
28#include <link.h>
b13d93c2 29
13436238 30#define TRACEPOINT_DEFINE
6d4658aa 31#include "ust_dl.h"
13436238 32
7b0fdd83 33static void *(*__lttng_ust_plibc_dlopen)(const char *filename, int flags);
42330adc 34#ifdef HAVE_DLMOPEN
7b0fdd83
MD
35static void *(*__lttng_ust_plibc_dlmopen)(Lmid_t nsid, const char *filename,
36 int flags);
42330adc 37#endif
b13d93c2 38static int (*__lttng_ust_plibc_dlclose)(void *handle);
b13d93c2 39
465a0d04
MJ
40static
41void _lttng_ust_dl_init(void)
42 __attribute__((constructor));
43static
2b6f4374
MJ
44void _lttng_ust_dl_init(void)
45{
c6e6343c 46 lttng_ust_logging_init();
2b6f4374
MJ
47}
48
b13d93c2 49static
7b0fdd83 50void *_lttng_ust_dl_libc_dlopen(const char *filename, int flags)
b13d93c2
PW
51{
52 if (!__lttng_ust_plibc_dlopen) {
53 __lttng_ust_plibc_dlopen = dlsym(RTLD_NEXT, "dlopen");
8e2aed3f 54 if (!__lttng_ust_plibc_dlopen) {
b13d93c2
PW
55 fprintf(stderr, "%s\n", dlerror());
56 return NULL;
57 }
58 }
7b0fdd83
MD
59 return __lttng_ust_plibc_dlopen(filename, flags);
60}
61
42330adc 62#ifdef HAVE_DLMOPEN
7b0fdd83
MD
63static
64void *_lttng_ust_dl_libc_dlmopen(Lmid_t nsid, const char *filename,
65 int flags)
66{
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());
71 return NULL;
72 }
73 }
74 return __lttng_ust_plibc_dlmopen(nsid, filename, flags);
b13d93c2 75}
42330adc 76#endif
b13d93c2
PW
77
78static
79int _lttng_ust_dl_libc_dlclose(void *handle)
80{
81 if (!__lttng_ust_plibc_dlclose) {
82 __lttng_ust_plibc_dlclose = dlsym(RTLD_NEXT, "dlclose");
8e2aed3f 83 if (!__lttng_ust_plibc_dlclose) {
b13d93c2
PW
84 fprintf(stderr, "%s\n", dlerror());
85 return -1;
86 }
87 }
88 return __lttng_ust_plibc_dlclose(handle);
89}
90
91static
7b0fdd83
MD
92void lttng_ust_dl_dlopen(void *so_base, const char *so_name,
93 int flags, void *ip)
b13d93c2 94{
13436238 95 char resolved_path[PATH_MAX];
8e2aed3f
AB
96 struct lttng_ust_elf *elf;
97 uint64_t memsz;
83215d66 98 uint8_t *build_id = NULL;
8e2aed3f 99 size_t build_id_len;
83215d66 100 char *dbg_file = NULL;
8e2aed3f
AB
101 uint32_t crc;
102 int has_build_id = 0, has_debug_link = 0;
103 int ret;
b13d93c2 104
13436238
PW
105 if (!realpath(so_name, resolved_path)) {
106 ERR("could not resolve path '%s'", so_name);
107 return;
b13d93c2 108 }
b13d93c2 109
8e2aed3f
AB
110 elf = lttng_ust_elf_create(resolved_path);
111 if (!elf) {
09026ccf 112 ERR("could not access file %s", resolved_path);
13436238 113 return;
b13d93c2 114 }
13436238 115
8e2aed3f
AB
116 ret = lttng_ust_elf_get_memsz(elf, &memsz);
117 if (ret) {
118 goto end;
119 }
120 ret = lttng_ust_elf_get_build_id(
121 elf, &build_id, &build_id_len, &has_build_id);
122 if (ret) {
123 goto end;
124 }
125 ret = lttng_ust_elf_get_debug_link(
126 elf, &dbg_file, &crc, &has_debug_link);
127 if (ret) {
128 goto end;
129 }
130
6d4658aa 131 tracepoint(lttng_ust_dl, dlopen,
7b0fdd83 132 ip, so_base, resolved_path, flags, memsz,
c5c4fd82 133 has_build_id, has_debug_link);
8e2aed3f
AB
134
135 if (has_build_id) {
136 tracepoint(lttng_ust_dl, build_id,
137 ip, so_base, build_id, build_id_len);
8e2aed3f
AB
138 }
139
140 if (has_debug_link) {
141 tracepoint(lttng_ust_dl, debug_link,
142 ip, so_base, dbg_file, crc);
8e2aed3f
AB
143 }
144
145end:
83215d66
MD
146 free(dbg_file);
147 free(build_id);
8e2aed3f 148 lttng_ust_elf_destroy(elf);
13436238 149 return;
b13d93c2
PW
150}
151
42330adc 152#ifdef HAVE_DLMOPEN
7b0fdd83
MD
153static
154void lttng_ust_dl_dlmopen(void *so_base, Lmid_t nsid, const char *so_name,
155 int flags, void *ip)
156{
157 char resolved_path[PATH_MAX];
158 struct lttng_ust_elf *elf;
159 uint64_t memsz;
160 uint8_t *build_id = NULL;
161 size_t build_id_len;
162 char *dbg_file = NULL;
163 uint32_t crc;
164 int has_build_id = 0, has_debug_link = 0;
165 int ret;
166
167 if (!realpath(so_name, resolved_path)) {
168 ERR("could not resolve path '%s'", so_name);
169 return;
170 }
171
172 elf = lttng_ust_elf_create(resolved_path);
173 if (!elf) {
09026ccf 174 ERR("could not access file %s", resolved_path);
7b0fdd83
MD
175 return;
176 }
177
178 ret = lttng_ust_elf_get_memsz(elf, &memsz);
179 if (ret) {
180 goto end;
181 }
182 ret = lttng_ust_elf_get_build_id(
183 elf, &build_id, &build_id_len, &has_build_id);
184 if (ret) {
185 goto end;
186 }
187 ret = lttng_ust_elf_get_debug_link(
188 elf, &dbg_file, &crc, &has_debug_link);
189 if (ret) {
190 goto end;
191 }
192
193 tracepoint(lttng_ust_dl, dlmopen,
194 ip, so_base, nsid, resolved_path, flags, memsz,
195 has_build_id, has_debug_link);
196
197 if (has_build_id) {
198 tracepoint(lttng_ust_dl, build_id,
199 ip, so_base, build_id, build_id_len);
200 }
201
202 if (has_debug_link) {
203 tracepoint(lttng_ust_dl, debug_link,
204 ip, so_base, dbg_file, crc);
205 }
206
207end:
208 free(dbg_file);
209 free(build_id);
210 lttng_ust_elf_destroy(elf);
211 return;
212}
42330adc 213#endif
7b0fdd83
MD
214
215void *dlopen(const char *filename, int flags)
b13d93c2 216{
8e2aed3f
AB
217 void *handle;
218
7b0fdd83 219 handle = _lttng_ust_dl_libc_dlopen(filename, flags);
bd703713 220 if (__tracepoint_ptrs_registered && handle) {
b13d93c2 221 struct link_map *p = NULL;
8e2aed3f
AB
222 int ret;
223
224 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
225 if (ret != -1 && p != NULL && p->l_addr != 0) {
97c7c238 226 lttng_ust_dl_dlopen((void *) p->l_addr,
7b0fdd83
MD
227 p->l_name, flags, LTTNG_UST_CALLER_IP());
228 }
229 }
230 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
231 return handle;
232}
233
42330adc 234#ifdef HAVE_DLMOPEN
7b0fdd83
MD
235void *dlmopen(Lmid_t nsid, const char *filename, int flags)
236{
237 void *handle;
238
239 handle = _lttng_ust_dl_libc_dlmopen(nsid, filename, flags);
240 if (__tracepoint_ptrs_registered && handle) {
241 struct link_map *p = NULL;
242 int ret;
243
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,
171fcc6f 248 LTTNG_UST_CALLER_IP());
8e2aed3f 249 }
b13d93c2 250 }
97c7c238 251 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
b13d93c2 252 return handle;
7b0fdd83 253
b13d93c2 254}
42330adc 255#endif
b13d93c2
PW
256
257int dlclose(void *handle)
258{
97c7c238
MD
259 int ret;
260
e7953e6e 261 if (__tracepoint_ptrs_registered) {
b13d93c2 262 struct link_map *p = NULL;
8e2aed3f
AB
263
264 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
265 if (ret != -1 && p != NULL && p->l_addr != 0) {
266 tracepoint(lttng_ust_dl, dlclose,
171fcc6f 267 LTTNG_UST_CALLER_IP(),
8e2aed3f
AB
268 (void *) p->l_addr);
269 }
b13d93c2 270 }
97c7c238
MD
271 ret = _lttng_ust_dl_libc_dlclose(handle);
272 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
273 return ret;
b13d93c2 274}
This page took 0.04279 seconds and 4 git commands to generate.