ust-elf.h should be private, with public symbols
[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
ae4b659d 16#include <ust-dlfcn.h>
2adb7ad2 17#include <ust-elf.h>
97c7c238 18#include <lttng/ust-events.h>
864a1eda 19#include <ust-helper.h>
eb2b066f 20#include "usterr-signal-safe.h"
b13d93c2 21
cbba5e04
MJ
22#include "../liblttng-ust/ust-events-internal.h"
23
8e2aed3f
AB
24/* Include link.h last else it conflicts with ust-dlfcn. */
25#include <link.h>
b13d93c2 26
13436238 27#define TRACEPOINT_DEFINE
6d4658aa 28#include "ust_dl.h"
13436238 29
7b0fdd83 30static void *(*__lttng_ust_plibc_dlopen)(const char *filename, int flags);
42330adc 31#ifdef HAVE_DLMOPEN
7b0fdd83
MD
32static void *(*__lttng_ust_plibc_dlmopen)(Lmid_t nsid, const char *filename,
33 int flags);
42330adc 34#endif
b13d93c2 35static int (*__lttng_ust_plibc_dlclose)(void *handle);
b13d93c2 36
2b6f4374
MJ
37static __attribute__((constructor))
38void _lttng_ust_dl_init(void)
39{
40 ust_err_init();
41}
42
b13d93c2 43static
7b0fdd83 44void *_lttng_ust_dl_libc_dlopen(const char *filename, int flags)
b13d93c2
PW
45{
46 if (!__lttng_ust_plibc_dlopen) {
47 __lttng_ust_plibc_dlopen = dlsym(RTLD_NEXT, "dlopen");
8e2aed3f 48 if (!__lttng_ust_plibc_dlopen) {
b13d93c2
PW
49 fprintf(stderr, "%s\n", dlerror());
50 return NULL;
51 }
52 }
7b0fdd83
MD
53 return __lttng_ust_plibc_dlopen(filename, flags);
54}
55
42330adc 56#ifdef HAVE_DLMOPEN
7b0fdd83
MD
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);
b13d93c2 69}
42330adc 70#endif
b13d93c2
PW
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");
8e2aed3f 77 if (!__lttng_ust_plibc_dlclose) {
b13d93c2
PW
78 fprintf(stderr, "%s\n", dlerror());
79 return -1;
80 }
81 }
82 return __lttng_ust_plibc_dlclose(handle);
83}
84
85static
7b0fdd83
MD
86void lttng_ust_dl_dlopen(void *so_base, const char *so_name,
87 int flags, void *ip)
b13d93c2 88{
13436238 89 char resolved_path[PATH_MAX];
8e2aed3f
AB
90 struct lttng_ust_elf *elf;
91 uint64_t memsz;
83215d66 92 uint8_t *build_id = NULL;
8e2aed3f 93 size_t build_id_len;
83215d66 94 char *dbg_file = NULL;
8e2aed3f
AB
95 uint32_t crc;
96 int has_build_id = 0, has_debug_link = 0;
97 int ret;
b13d93c2 98
13436238
PW
99 if (!realpath(so_name, resolved_path)) {
100 ERR("could not resolve path '%s'", so_name);
101 return;
b13d93c2 102 }
b13d93c2 103
8e2aed3f
AB
104 elf = lttng_ust_elf_create(resolved_path);
105 if (!elf) {
09026ccf 106 ERR("could not access file %s", resolved_path);
13436238 107 return;
b13d93c2 108 }
13436238 109
8e2aed3f
AB
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
6d4658aa 125 tracepoint(lttng_ust_dl, dlopen,
7b0fdd83 126 ip, so_base, resolved_path, flags, memsz,
c5c4fd82 127 has_build_id, has_debug_link);
8e2aed3f
AB
128
129 if (has_build_id) {
130 tracepoint(lttng_ust_dl, build_id,
131 ip, so_base, build_id, build_id_len);
8e2aed3f
AB
132 }
133
134 if (has_debug_link) {
135 tracepoint(lttng_ust_dl, debug_link,
136 ip, so_base, dbg_file, crc);
8e2aed3f
AB
137 }
138
139end:
83215d66
MD
140 free(dbg_file);
141 free(build_id);
8e2aed3f 142 lttng_ust_elf_destroy(elf);
13436238 143 return;
b13d93c2
PW
144}
145
42330adc 146#ifdef HAVE_DLMOPEN
7b0fdd83
MD
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) {
09026ccf 168 ERR("could not access file %s", resolved_path);
7b0fdd83
MD
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}
42330adc 207#endif
7b0fdd83
MD
208
209void *dlopen(const char *filename, int flags)
b13d93c2 210{
8e2aed3f
AB
211 void *handle;
212
7b0fdd83 213 handle = _lttng_ust_dl_libc_dlopen(filename, flags);
bd703713 214 if (__tracepoint_ptrs_registered && handle) {
b13d93c2 215 struct link_map *p = NULL;
8e2aed3f
AB
216 int ret;
217
218 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
219 if (ret != -1 && p != NULL && p->l_addr != 0) {
97c7c238 220 lttng_ust_dl_dlopen((void *) p->l_addr,
7b0fdd83
MD
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
42330adc 228#ifdef HAVE_DLMOPEN
7b0fdd83
MD
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,
171fcc6f 242 LTTNG_UST_CALLER_IP());
8e2aed3f 243 }
b13d93c2 244 }
97c7c238 245 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
b13d93c2 246 return handle;
7b0fdd83 247
b13d93c2 248}
42330adc 249#endif
b13d93c2
PW
250
251int dlclose(void *handle)
252{
97c7c238
MD
253 int ret;
254
e7953e6e 255 if (__tracepoint_ptrs_registered) {
b13d93c2 256 struct link_map *p = NULL;
8e2aed3f
AB
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,
171fcc6f 261 LTTNG_UST_CALLER_IP(),
8e2aed3f
AB
262 (void *) p->l_addr);
263 }
b13d93c2 264 }
97c7c238
MD
265 ret = _lttng_ust_dl_libc_dlclose(handle);
266 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
267 return ret;
b13d93c2 268}
This page took 0.039131 seconds and 4 git commands to generate.