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