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