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