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