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