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