Fix: race between lttng-ust getenv() and application setenv()
[lttng-ust.git] / liblttng-ust / lttng-ust-statedump.c
CommitLineData
cf73e0fe
AB
1/*
2 * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
3 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#define _LGPL_SOURCE
21#define _GNU_SOURCE
cf73e0fe 22
8e2aed3f 23#include <link.h>
cf73e0fe 24#include <limits.h>
cf73e0fe 25#include <stdio.h>
8e2aed3f
AB
26#include <stdint.h>
27#include <stdlib.h>
28#include <sys/types.h>
29#include <unistd.h>
cf73e0fe 30
8e2aed3f 31#include <lttng/ust-elf.h>
cf73e0fe
AB
32#include "lttng-tracer-core.h"
33#include "lttng-ust-statedump.h"
c452ee17 34#include "getenv.h"
cf73e0fe
AB
35
36#define TRACEPOINT_DEFINE
37#define TRACEPOINT_CREATE_PROBES
38#define TP_SESSION_CHECK
39#include "lttng-ust-statedump-provider.h"
40
41struct dl_iterate_data {
42 void *owner;
43 int exec_found;
44};
45
ee047a74 46struct bin_info_data {
cf73e0fe
AB
47 void *owner;
48 void *base_addr_ptr;
49 const char *resolved_path;
8e2aed3f
AB
50 char *dbg_file;
51 uint8_t *build_id;
52 uint64_t memsz;
53 size_t build_id_len;
cf73e0fe 54 int vdso;
8e2aed3f 55 uint32_t crc;
444da810 56 uint8_t is_pic;
a435064b
MD
57 uint8_t has_build_id;
58 uint8_t has_debug_link;
cf73e0fe
AB
59};
60
61typedef void (*tracepoint_cb)(struct lttng_session *session, void *priv);
62
63/*
64 * Trace statedump event into all sessions owned by the caller thread
65 * for which statedump is pending.
66 */
67static
68int trace_statedump_event(tracepoint_cb tp_cb, void *owner, void *priv)
69{
70 struct cds_list_head *sessionsp;
71 struct lttng_session *session;
72
cf73e0fe
AB
73 sessionsp = _lttng_get_sessions();
74 cds_list_for_each_entry(session, sessionsp, node) {
75 if (session->owner != owner)
76 continue;
77 if (!session->statedump_pending)
78 continue;
79 tp_cb(session, priv);
80 }
cf73e0fe
AB
81 return 0;
82}
83
84static
ee047a74 85void trace_bin_info_cb(struct lttng_session *session, void *priv)
cf73e0fe 86{
ee047a74 87 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
cf73e0fe 88
ee047a74
AB
89 tracepoint(lttng_ust_statedump, bin_info,
90 session, bin_data->base_addr_ptr,
a435064b
MD
91 bin_data->resolved_path, bin_data->memsz,
92 bin_data->is_pic, bin_data->has_build_id,
93 bin_data->has_debug_link);
8e2aed3f
AB
94}
95
96static
97void trace_build_id_cb(struct lttng_session *session, void *priv)
98{
ee047a74 99 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
8e2aed3f
AB
100
101 tracepoint(lttng_ust_statedump, build_id,
ee047a74
AB
102 session, bin_data->base_addr_ptr,
103 bin_data->build_id, bin_data->build_id_len);
8e2aed3f
AB
104}
105
106static
107void trace_debug_link_cb(struct lttng_session *session, void *priv)
108{
ee047a74 109 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
8e2aed3f
AB
110
111 tracepoint(lttng_ust_statedump, debug_link,
ee047a74
AB
112 session, bin_data->base_addr_ptr,
113 bin_data->dbg_file, bin_data->crc);
cf73e0fe
AB
114}
115
116static
117void trace_start_cb(struct lttng_session *session, void *priv)
118{
119 tracepoint(lttng_ust_statedump, start, session);
120}
121
122static
123void trace_end_cb(struct lttng_session *session, void *priv)
124{
125 tracepoint(lttng_ust_statedump, end, session);
126}
127
8e2aed3f 128static
a435064b
MD
129int get_elf_info(struct bin_info_data *bin_data)
130{
8e2aed3f 131 struct lttng_ust_elf *elf;
a435064b 132 int ret = 0, found;
8e2aed3f 133
ee047a74 134 elf = lttng_ust_elf_create(bin_data->resolved_path);
8e2aed3f
AB
135 if (!elf) {
136 ret = -1;
137 goto end;
138 }
139
ee047a74 140 ret = lttng_ust_elf_get_memsz(elf, &bin_data->memsz);
8e2aed3f
AB
141 if (ret) {
142 goto end;
143 }
144
a435064b 145 found = 0;
ee047a74 146 ret = lttng_ust_elf_get_build_id(elf, &bin_data->build_id,
a435064b
MD
147 &bin_data->build_id_len,
148 &found);
8e2aed3f
AB
149 if (ret) {
150 goto end;
151 }
a435064b
MD
152 bin_data->has_build_id = !!found;
153 found = 0;
ee047a74 154 ret = lttng_ust_elf_get_debug_link(elf, &bin_data->dbg_file,
a435064b
MD
155 &bin_data->crc,
156 &found);
8e2aed3f
AB
157 if (ret) {
158 goto end;
159 }
a435064b 160 bin_data->has_debug_link = !!found;
8e2aed3f 161
ee047a74 162 bin_data->is_pic = lttng_ust_elf_is_pic(elf);
444da810 163
8e2aed3f
AB
164end:
165 lttng_ust_elf_destroy(elf);
166 return ret;
167}
168
cf73e0fe 169static
ee047a74 170int trace_baddr(struct bin_info_data *bin_data)
cf73e0fe 171{
a435064b 172 int ret = 0;
8e2aed3f 173
ee047a74 174 if (!bin_data->vdso) {
a435064b 175 ret = get_elf_info(bin_data);
8e2aed3f
AB
176 if (ret) {
177 goto end;
178 }
179 } else {
ee047a74 180 bin_data->memsz = 0;
2bb51006
MD
181 bin_data->has_build_id = 0;
182 bin_data->has_debug_link = 0;
8e2aed3f
AB
183 }
184
ee047a74
AB
185 ret = trace_statedump_event(trace_bin_info_cb, bin_data->owner,
186 bin_data);
8e2aed3f
AB
187 if (ret) {
188 goto end;
189 }
cf73e0fe 190
a435064b 191 if (bin_data->has_build_id) {
8e2aed3f 192 ret = trace_statedump_event(
ee047a74
AB
193 trace_build_id_cb, bin_data->owner, bin_data);
194 free(bin_data->build_id);
8e2aed3f
AB
195 if (ret) {
196 goto end;
197 }
cf73e0fe
AB
198 }
199
a435064b 200 if (bin_data->has_debug_link) {
8e2aed3f 201 ret = trace_statedump_event(
ee047a74
AB
202 trace_debug_link_cb, bin_data->owner, bin_data);
203 free(bin_data->dbg_file);
8e2aed3f
AB
204 if (ret) {
205 goto end;
206 }
207 }
cf73e0fe 208
8e2aed3f
AB
209end:
210 return ret;
cf73e0fe
AB
211}
212
213static
214int trace_statedump_start(void *owner)
215{
216 return trace_statedump_event(trace_start_cb, owner, NULL);
217}
218
219static
220int trace_statedump_end(void *owner)
221{
222 return trace_statedump_event(trace_end_cb, owner, NULL);
223}
224
225static
ee047a74 226int extract_bin_info_events(struct dl_phdr_info *info, size_t size, void *_data)
cf73e0fe 227{
d34e6761 228 int j, ret = 0;
cf73e0fe
AB
229 struct dl_iterate_data *data = _data;
230
d34e6761
MD
231 /*
232 * UST lock nests within dynamic loader lock.
233 *
234 * Hold this lock across handling of the entire module to
235 * protect memory allocation at early process start, due to
236 * interactions with libc-wrapper lttng malloc instrumentation.
237 */
238 if (ust_lock()) {
239 goto end;
240 }
241
cf73e0fe 242 for (j = 0; j < info->dlpi_phnum; j++) {
ee047a74 243 struct bin_info_data bin_data;
cf73e0fe
AB
244 char resolved_path[PATH_MAX];
245 void *base_addr_ptr;
246
247 if (info->dlpi_phdr[j].p_type != PT_LOAD)
248 continue;
249
250 /* Calculate virtual memory address of the loadable segment */
251 base_addr_ptr = (void *) info->dlpi_addr +
252 info->dlpi_phdr[j].p_vaddr;
253
254 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)) {
255 /*
256 * Only the first phdr without a dlpi_name
257 * encountered is considered as the program
258 * executable. The rest are vdsos.
259 */
260 if (!data->exec_found) {
261 ssize_t path_len;
262 data->exec_found = 1;
263
264 /*
265 * Use /proc/self/exe to resolve the
266 * executable's full path.
267 */
268 path_len = readlink("/proc/self/exe",
269 resolved_path,
270 PATH_MAX - 1);
271 if (path_len <= 0)
272 break;
273
274 resolved_path[path_len] = '\0';
ee047a74 275 bin_data.vdso = 0;
cf73e0fe
AB
276 } else {
277 snprintf(resolved_path, PATH_MAX - 1, "[vdso]");
ee047a74 278 bin_data.vdso = 1;
cf73e0fe
AB
279 }
280 } else {
281 /*
282 * For regular dl_phdr_info entries check if
ee047a74 283 * the path to the binary really exists. If not,
cf73e0fe
AB
284 * treat as vdso and use dlpi_name as 'path'.
285 */
286 if (!realpath(info->dlpi_name, resolved_path)) {
287 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
288 info->dlpi_name);
ee047a74 289 bin_data.vdso = 1;
89be5359 290 } else {
ee047a74 291 bin_data.vdso = 0;
cf73e0fe
AB
292 }
293 }
294
ee047a74
AB
295 bin_data.owner = data->owner;
296 bin_data.base_addr_ptr = base_addr_ptr;
297 bin_data.resolved_path = resolved_path;
298 ret = trace_baddr(&bin_data);
d34e6761 299 break;
cf73e0fe 300 }
d34e6761
MD
301end:
302 ust_unlock();
303 return ret;
cf73e0fe
AB
304}
305
306/*
307 * Generate a statedump of base addresses of all shared objects loaded
308 * by the traced application, as well as for the application's
309 * executable itself.
310 */
311static
312int do_baddr_statedump(void *owner)
313{
314 struct dl_iterate_data data;
315
c452ee17 316 if (lttng_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
cf73e0fe
AB
317 return 0;
318
a3b964eb
MD
319 /*
320 * Fixup lttng-ust TLS when called from dlopen/dlclose
321 * instrumentation.
322 */
323 lttng_ust_fixup_tls();
324
cf73e0fe
AB
325 data.owner = owner;
326 data.exec_found = 0;
327 /*
328 * Iterate through the list of currently loaded shared objects and
329 * generate events for loadable segments using
ee047a74 330 * extract_bin_info_events.
cf73e0fe 331 */
ee047a74 332 dl_iterate_phdr(extract_bin_info_events, &data);
cf73e0fe
AB
333
334 return 0;
335}
336
337/*
338 * Generate a statedump of a given traced application. A statedump is
339 * delimited by start and end events. For a given (process, session)
340 * pair, begin/end events are serialized and will match. However, in a
341 * session, statedumps from different processes may be
342 * interleaved. The vpid context should be used to identify which
343 * events belong to which process.
246bb09a
MD
344 *
345 * Grab the ust_lock outside of the RCU read-side lock because we
346 * perform synchronize_rcu with the ust_lock held, which can trigger
347 * deadlocks otherwise.
cf73e0fe
AB
348 */
349int do_lttng_ust_statedump(void *owner)
350{
246bb09a 351 ust_lock_nocheck();
cf73e0fe 352 trace_statedump_start(owner);
246bb09a
MD
353 ust_unlock();
354
cf73e0fe 355 do_baddr_statedump(owner);
246bb09a
MD
356
357 ust_lock_nocheck();
cf73e0fe 358 trace_statedump_end(owner);
246bb09a 359 ust_unlock();
cf73e0fe
AB
360
361 return 0;
362}
363
364void lttng_ust_statedump_init(void)
365{
366 __tracepoints__init();
367 __tracepoints__ptrs_init();
368 __lttng_events_init__lttng_ust_statedump();
369}
370
371void lttng_ust_statedump_destroy(void)
372{
373 __lttng_events_exit__lttng_ust_statedump();
374 __tracepoints__ptrs_destroy();
375 __tracepoints__destroy();
376}
This page took 0.040114 seconds and 4 git commands to generate.