Fix: baddr deadlock with lttng-ust destructor
[lttng-ust.git] / liblttng-ust / lttng-ust-baddr.c
1 /*
2 * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #define _GNU_SOURCE
20 #include <dlfcn.h>
21 #include <link.h>
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <stdint.h>
30 #include <stddef.h>
31 #include <stdio.h>
32
33 #include <usterr-signal-safe.h>
34 #include "lttng-tracer-core.h"
35 #include "lttng-ust-baddr.h"
36
37 #define TRACEPOINT_DEFINE
38 #include "ust_baddr_statedump.h"
39
40 static
41 int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *data)
42 {
43 int j;
44 int num_loadable_segment = 0;
45 void *owner = data;
46 struct cds_list_head *sessionsp;
47
48 for (j = 0; j < info->dlpi_phnum; j++) {
49 char resolved_path[PATH_MAX];
50 struct stat sostat;
51 void *base_addr_ptr;
52 struct lttng_session *session;
53
54 if (info->dlpi_phdr[j].p_type != PT_LOAD)
55 continue;
56
57 /* Calculate virtual memory address of the loadable segment */
58 base_addr_ptr = (void *) info->dlpi_addr
59 + info->dlpi_phdr[j].p_vaddr;
60
61 num_loadable_segment += 1;
62 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)
63 && num_loadable_segment == 1) {
64 /*
65 * If the iterated element is the executable itself we
66 * have to use Dl_info to determine its full path
67 */
68 Dl_info dl_info = { 0 };
69 if (!dladdr(base_addr_ptr, &dl_info))
70 return 0;
71 if (!realpath(dl_info.dli_fname, resolved_path))
72 return 0;
73 } else {
74 /*
75 * For regular dl_phdr_info entries we have to check if
76 * the path to the shared object really exists
77 */
78 if (!realpath(info->dlpi_name, resolved_path)) {
79 /* Found vDSO, put the 'path' into brackets */
80 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
81 info->dlpi_name);
82 }
83 }
84
85 if (stat(resolved_path, &sostat)) {
86 sostat.st_size = 0;
87 sostat.st_mtime = -1;
88 }
89
90 /*
91 * UST lock needs to be nested within dynamic loader
92 * lock.
93 */
94 if (ust_lock()) {
95 /*
96 * Stop iteration on headers if need to exit.
97 */
98 ust_unlock();
99 return 1;
100 }
101
102 sessionsp = _lttng_get_sessions();
103 cds_list_for_each_entry(session, sessionsp, node) {
104 if (session->owner != owner)
105 continue;
106 if (!session->statedump_pending)
107 continue;
108 tracepoint(ust_baddr_statedump, soinfo,
109 session, base_addr_ptr,
110 resolved_path, sostat.st_size,
111 sostat.st_mtime);
112 }
113 ust_unlock();
114 /*
115 * We are only interested in the base address (lowest virtual
116 * address associated with the memory image), skip the rest
117 */
118 break;
119 }
120 return 0;
121 }
122
123 int lttng_ust_baddr_statedump(void *owner)
124 {
125 if (getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
126 return 0;
127 /*
128 * Iterate through the list of currently loaded shared objects and
129 * generate events for loadable segments using
130 * extract_soinfo_events.
131 */
132 dl_iterate_phdr(extract_soinfo_events, owner);
133 return 0;
134 }
This page took 0.03167 seconds and 4 git commands to generate.