baddr statedump: hold ust lock around allocations
[lttng-ust.git] / liblttng-ust / lttng-ust-statedump.c
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
22
23 #include <link.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30
31 #include <lttng/ust-elf.h>
32 #include "lttng-tracer-core.h"
33 #include "lttng-ust-statedump.h"
34
35 #define TRACEPOINT_DEFINE
36 #define TRACEPOINT_CREATE_PROBES
37 #define TP_SESSION_CHECK
38 #include "lttng-ust-statedump-provider.h"
39
40 struct dl_iterate_data {
41 void *owner;
42 int exec_found;
43 };
44
45 struct soinfo_data {
46 void *owner;
47 void *base_addr_ptr;
48 const char *resolved_path;
49 char *dbg_file;
50 uint8_t *build_id;
51 uint64_t memsz;
52 size_t build_id_len;
53 int vdso;
54 uint32_t crc;
55 };
56
57 typedef void (*tracepoint_cb)(struct lttng_session *session, void *priv);
58
59 /*
60 * Trace statedump event into all sessions owned by the caller thread
61 * for which statedump is pending.
62 */
63 static
64 int trace_statedump_event(tracepoint_cb tp_cb, void *owner, void *priv)
65 {
66 struct cds_list_head *sessionsp;
67 struct lttng_session *session;
68
69 sessionsp = _lttng_get_sessions();
70 cds_list_for_each_entry(session, sessionsp, node) {
71 if (session->owner != owner)
72 continue;
73 if (!session->statedump_pending)
74 continue;
75 tp_cb(session, priv);
76 }
77 return 0;
78 }
79
80 static
81 void trace_soinfo_cb(struct lttng_session *session, void *priv)
82 {
83 struct soinfo_data *so_data = (struct soinfo_data *) priv;
84
85 tracepoint(lttng_ust_statedump, soinfo,
86 session, so_data->base_addr_ptr,
87 so_data->resolved_path, so_data->memsz);
88 }
89
90 static
91 void trace_build_id_cb(struct lttng_session *session, void *priv)
92 {
93 struct soinfo_data *so_data = (struct soinfo_data *) priv;
94
95 tracepoint(lttng_ust_statedump, build_id,
96 session, so_data->base_addr_ptr,
97 so_data->build_id, so_data->build_id_len);
98 }
99
100 static
101 void trace_debug_link_cb(struct lttng_session *session, void *priv)
102 {
103 struct soinfo_data *so_data = (struct soinfo_data *) priv;
104
105 tracepoint(lttng_ust_statedump, debug_link,
106 session, so_data->base_addr_ptr,
107 so_data->dbg_file, so_data->crc);
108 }
109
110 static
111 void trace_start_cb(struct lttng_session *session, void *priv)
112 {
113 tracepoint(lttng_ust_statedump, start, session);
114 }
115
116 static
117 void trace_end_cb(struct lttng_session *session, void *priv)
118 {
119 tracepoint(lttng_ust_statedump, end, session);
120 }
121
122 static
123 int get_elf_info(struct soinfo_data *so_data, int *has_build_id,
124 int *has_debug_link) {
125 struct lttng_ust_elf *elf;
126 int ret = 0;
127
128 elf = lttng_ust_elf_create(so_data->resolved_path);
129 if (!elf) {
130 ret = -1;
131 goto end;
132 }
133
134 ret = lttng_ust_elf_get_memsz(elf, &so_data->memsz);
135 if (ret) {
136 goto end;
137 }
138
139 ret = lttng_ust_elf_get_build_id(elf, &so_data->build_id,
140 &so_data->build_id_len, has_build_id);
141 if (ret) {
142 goto end;
143 }
144 ret = lttng_ust_elf_get_debug_link(elf, &so_data->dbg_file,
145 &so_data->crc, has_debug_link);
146 if (ret) {
147 goto end;
148 }
149
150 end:
151 lttng_ust_elf_destroy(elf);
152 return ret;
153 }
154
155 static
156 int trace_baddr(struct soinfo_data *so_data)
157 {
158 int ret = 0, has_build_id = 0, has_debug_link = 0;
159
160 if (!so_data->vdso) {
161 ret = get_elf_info(so_data, &has_build_id, &has_debug_link);
162 if (ret) {
163 goto end;
164 }
165 } else {
166 so_data->memsz = 0;
167 }
168
169 ret = trace_statedump_event(trace_soinfo_cb, so_data->owner, so_data);
170 if (ret) {
171 goto end;
172 }
173
174 if (has_build_id) {
175 ret = trace_statedump_event(
176 trace_build_id_cb, so_data->owner, so_data);
177 free(so_data->build_id);
178 if (ret) {
179 goto end;
180 }
181 }
182
183 if (has_debug_link) {
184 ret = trace_statedump_event(
185 trace_debug_link_cb, so_data->owner, so_data);
186 free(so_data->dbg_file);
187 if (ret) {
188 goto end;
189 }
190 }
191
192 end:
193 return ret;
194 }
195
196 static
197 int trace_statedump_start(void *owner)
198 {
199 return trace_statedump_event(trace_start_cb, owner, NULL);
200 }
201
202 static
203 int trace_statedump_end(void *owner)
204 {
205 return trace_statedump_event(trace_end_cb, owner, NULL);
206 }
207
208 static
209 int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *_data)
210 {
211 int j, ret = 0;
212 struct dl_iterate_data *data = _data;
213
214 /*
215 * UST lock nests within dynamic loader lock.
216 *
217 * Hold this lock across handling of the entire module to
218 * protect memory allocation at early process start, due to
219 * interactions with libc-wrapper lttng malloc instrumentation.
220 */
221 if (ust_lock()) {
222 goto end;
223 }
224
225 for (j = 0; j < info->dlpi_phnum; j++) {
226 struct soinfo_data so_data;
227 char resolved_path[PATH_MAX];
228 void *base_addr_ptr;
229
230 if (info->dlpi_phdr[j].p_type != PT_LOAD)
231 continue;
232
233 /* Calculate virtual memory address of the loadable segment */
234 base_addr_ptr = (void *) info->dlpi_addr +
235 info->dlpi_phdr[j].p_vaddr;
236
237 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)) {
238 /*
239 * Only the first phdr without a dlpi_name
240 * encountered is considered as the program
241 * executable. The rest are vdsos.
242 */
243 if (!data->exec_found) {
244 ssize_t path_len;
245 data->exec_found = 1;
246
247 /*
248 * Use /proc/self/exe to resolve the
249 * executable's full path.
250 */
251 path_len = readlink("/proc/self/exe",
252 resolved_path,
253 PATH_MAX - 1);
254 if (path_len <= 0)
255 break;
256
257 resolved_path[path_len] = '\0';
258 so_data.vdso = 0;
259 } else {
260 snprintf(resolved_path, PATH_MAX - 1, "[vdso]");
261 so_data.vdso = 1;
262 }
263 } else {
264 /*
265 * For regular dl_phdr_info entries check if
266 * the path to the SO really exists. If not,
267 * treat as vdso and use dlpi_name as 'path'.
268 */
269 if (!realpath(info->dlpi_name, resolved_path)) {
270 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
271 info->dlpi_name);
272 so_data.vdso = 1;
273 } else {
274 so_data.vdso = 0;
275 }
276 }
277
278 so_data.owner = data->owner;
279 so_data.base_addr_ptr = base_addr_ptr;
280 so_data.resolved_path = resolved_path;
281 ret = trace_baddr(&so_data);
282 break;
283 }
284 end:
285 ust_unlock();
286 return ret;
287 }
288
289 /*
290 * Generate a statedump of base addresses of all shared objects loaded
291 * by the traced application, as well as for the application's
292 * executable itself.
293 */
294 static
295 int do_baddr_statedump(void *owner)
296 {
297 struct dl_iterate_data data;
298
299 if (getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
300 return 0;
301
302 data.owner = owner;
303 data.exec_found = 0;
304 /*
305 * Iterate through the list of currently loaded shared objects and
306 * generate events for loadable segments using
307 * extract_soinfo_events.
308 */
309 dl_iterate_phdr(extract_soinfo_events, &data);
310
311 return 0;
312 }
313
314 /*
315 * Generate a statedump of a given traced application. A statedump is
316 * delimited by start and end events. For a given (process, session)
317 * pair, begin/end events are serialized and will match. However, in a
318 * session, statedumps from different processes may be
319 * interleaved. The vpid context should be used to identify which
320 * events belong to which process.
321 */
322 int do_lttng_ust_statedump(void *owner)
323 {
324 trace_statedump_start(owner);
325 do_baddr_statedump(owner);
326 trace_statedump_end(owner);
327
328 return 0;
329 }
330
331 void lttng_ust_statedump_init(void)
332 {
333 __tracepoints__init();
334 __tracepoints__ptrs_init();
335 __lttng_events_init__lttng_ust_statedump();
336 }
337
338 void lttng_ust_statedump_destroy(void)
339 {
340 __lttng_events_exit__lttng_ust_statedump();
341 __tracepoints__ptrs_destroy();
342 __tracepoints__destroy();
343 }
This page took 0.03631 seconds and 5 git commands to generate.