dl instrumentation: add dlmopen event, trace dlopen flags
[lttng-ust.git] / liblttng-ust-dl / lttng-ust-dl.c
CommitLineData
b13d93c2
PW
1/*
2 * Copyright (C) 2013 Paul Woegerer <paul.woegerer@mentor.com>
8e2aed3f 3 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
97c7c238 4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
b13d93c2
PW
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; version 2.1 of
9 * the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#define _GNU_SOURCE
1ddceb36 22#define _LGPL_SOURCE
13436238 23#include <limits.h>
8e2aed3f 24#include <stdio.h>
13436238 25#include <sys/types.h>
8e2aed3f
AB
26#include <unistd.h>
27
28#include <lttng/ust-dlfcn.h>
29#include <lttng/ust-elf.h>
97c7c238 30#include <lttng/ust-events.h>
171fcc6f 31#include <helper.h>
eb2b066f 32#include "usterr-signal-safe.h"
b13d93c2 33
8e2aed3f
AB
34/* Include link.h last else it conflicts with ust-dlfcn. */
35#include <link.h>
b13d93c2 36
13436238 37#define TRACEPOINT_DEFINE
6d4658aa 38#include "ust_dl.h"
13436238 39
7b0fdd83
MD
40static void *(*__lttng_ust_plibc_dlopen)(const char *filename, int flags);
41static void *(*__lttng_ust_plibc_dlmopen)(Lmid_t nsid, const char *filename,
42 int flags);
b13d93c2 43static int (*__lttng_ust_plibc_dlclose)(void *handle);
b13d93c2
PW
44
45static
7b0fdd83 46void *_lttng_ust_dl_libc_dlopen(const char *filename, int flags)
b13d93c2
PW
47{
48 if (!__lttng_ust_plibc_dlopen) {
49 __lttng_ust_plibc_dlopen = dlsym(RTLD_NEXT, "dlopen");
8e2aed3f 50 if (!__lttng_ust_plibc_dlopen) {
b13d93c2
PW
51 fprintf(stderr, "%s\n", dlerror());
52 return NULL;
53 }
54 }
7b0fdd83
MD
55 return __lttng_ust_plibc_dlopen(filename, flags);
56}
57
58static
59void *_lttng_ust_dl_libc_dlmopen(Lmid_t nsid, const char *filename,
60 int flags)
61{
62 if (!__lttng_ust_plibc_dlmopen) {
63 __lttng_ust_plibc_dlmopen = dlsym(RTLD_NEXT, "dlmopen");
64 if (!__lttng_ust_plibc_dlmopen) {
65 fprintf(stderr, "%s\n", dlerror());
66 return NULL;
67 }
68 }
69 return __lttng_ust_plibc_dlmopen(nsid, filename, flags);
b13d93c2
PW
70}
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) {
106 ERR("could not acces 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
7b0fdd83
MD
146static
147void lttng_ust_dl_dlmopen(void *so_base, Lmid_t nsid, const char *so_name,
148 int flags, void *ip)
149{
150 char resolved_path[PATH_MAX];
151 struct lttng_ust_elf *elf;
152 uint64_t memsz;
153 uint8_t *build_id = NULL;
154 size_t build_id_len;
155 char *dbg_file = NULL;
156 uint32_t crc;
157 int has_build_id = 0, has_debug_link = 0;
158 int ret;
159
160 if (!realpath(so_name, resolved_path)) {
161 ERR("could not resolve path '%s'", so_name);
162 return;
163 }
164
165 elf = lttng_ust_elf_create(resolved_path);
166 if (!elf) {
167 ERR("could not acces file %s", resolved_path);
168 return;
169 }
170
171 ret = lttng_ust_elf_get_memsz(elf, &memsz);
172 if (ret) {
173 goto end;
174 }
175 ret = lttng_ust_elf_get_build_id(
176 elf, &build_id, &build_id_len, &has_build_id);
177 if (ret) {
178 goto end;
179 }
180 ret = lttng_ust_elf_get_debug_link(
181 elf, &dbg_file, &crc, &has_debug_link);
182 if (ret) {
183 goto end;
184 }
185
186 tracepoint(lttng_ust_dl, dlmopen,
187 ip, so_base, nsid, resolved_path, flags, memsz,
188 has_build_id, has_debug_link);
189
190 if (has_build_id) {
191 tracepoint(lttng_ust_dl, build_id,
192 ip, so_base, build_id, build_id_len);
193 }
194
195 if (has_debug_link) {
196 tracepoint(lttng_ust_dl, debug_link,
197 ip, so_base, dbg_file, crc);
198 }
199
200end:
201 free(dbg_file);
202 free(build_id);
203 lttng_ust_elf_destroy(elf);
204 return;
205}
206
207void *dlopen(const char *filename, int flags)
b13d93c2 208{
8e2aed3f
AB
209 void *handle;
210
7b0fdd83 211 handle = _lttng_ust_dl_libc_dlopen(filename, flags);
bd703713 212 if (__tracepoint_ptrs_registered && handle) {
b13d93c2 213 struct link_map *p = NULL;
8e2aed3f
AB
214 int ret;
215
216 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
217 if (ret != -1 && p != NULL && p->l_addr != 0) {
97c7c238 218 lttng_ust_dl_dlopen((void *) p->l_addr,
7b0fdd83
MD
219 p->l_name, flags, LTTNG_UST_CALLER_IP());
220 }
221 }
222 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
223 return handle;
224}
225
226void *dlmopen(Lmid_t nsid, const char *filename, int flags)
227{
228 void *handle;
229
230 handle = _lttng_ust_dl_libc_dlmopen(nsid, filename, flags);
231 if (__tracepoint_ptrs_registered && handle) {
232 struct link_map *p = NULL;
233 int ret;
234
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,
171fcc6f 239 LTTNG_UST_CALLER_IP());
8e2aed3f 240 }
b13d93c2 241 }
97c7c238 242 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
b13d93c2 243 return handle;
7b0fdd83 244
b13d93c2
PW
245}
246
247int dlclose(void *handle)
248{
97c7c238
MD
249 int ret;
250
e7953e6e 251 if (__tracepoint_ptrs_registered) {
b13d93c2 252 struct link_map *p = NULL;
8e2aed3f
AB
253
254 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
255 if (ret != -1 && p != NULL && p->l_addr != 0) {
256 tracepoint(lttng_ust_dl, dlclose,
171fcc6f 257 LTTNG_UST_CALLER_IP(),
8e2aed3f
AB
258 (void *) p->l_addr);
259 }
b13d93c2 260 }
97c7c238
MD
261 ret = _lttng_ust_dl_libc_dlclose(handle);
262 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
263 return ret;
b13d93c2 264}
This page took 0.034756 seconds and 4 git commands to generate.