doc/man: convert lttng-crash(1) to AsciiDoc
[lttng-tools.git] / src / bin / lttng-crash / lttng-crash.c
1 /*
2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2 only,
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <getopt.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/mman.h>
28 #include <fcntl.h>
29 #include <sys/wait.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <dirent.h>
33 #include <byteswap.h>
34 #include <inttypes.h>
35 #include <stdbool.h>
36
37 #include <version.h>
38 #include <lttng/lttng.h>
39 #include <common/common.h>
40
41 #define DEFAULT_VIEWER "babeltrace"
42
43 #define COPY_BUFLEN 4096
44 #define RB_CRASH_DUMP_ABI_LEN 32
45
46 #define RB_CRASH_DUMP_ABI_MAGIC_LEN 16
47
48 /*
49 * The 128-bit magic number is xor'd in the process data so it does not
50 * cause a false positive when searching for buffers by scanning memory.
51 * The actual magic number is:
52 * 0x17, 0x7B, 0xF1, 0x77, 0xBF, 0x17, 0x7B, 0xF1,
53 * 0x77, 0xBF, 0x17, 0x7B, 0xF1, 0x77, 0xBF, 0x17,
54 */
55 #define RB_CRASH_DUMP_ABI_MAGIC_XOR \
56 { \
57 0x17 ^ 0xFF, 0x7B ^ 0xFF, 0xF1 ^ 0xFF, 0x77 ^ 0xFF, \
58 0xBF ^ 0xFF, 0x17 ^ 0xFF, 0x7B ^ 0xFF, 0xF1 ^ 0xFF, \
59 0x77 ^ 0xFF, 0xBF ^ 0xFF, 0x17 ^ 0xFF, 0x7B ^ 0xFF, \
60 0xF1 ^ 0xFF, 0x77 ^ 0xFF, 0xBF ^ 0xFF, 0x17 ^ 0xFF, \
61 }
62
63 /*
64 * Non-static to ensure the compiler does not optimize away the xor.
65 */
66 uint8_t lttng_crash_expected_magic_xor[] = RB_CRASH_DUMP_ABI_MAGIC_XOR;
67
68 #define RB_CRASH_ENDIAN 0x1234
69 #define RB_CRASH_ENDIAN_REVERSE 0x3412
70
71 enum lttng_crash_type {
72 LTTNG_CRASH_TYPE_UST = 0,
73 LTTNG_CRASH_TYPE_KERNEL = 1,
74 };
75
76 /* LTTng ring buffer defines (copied) */
77
78 #define HALF_ULONG_BITS(wl) (((wl) * CHAR_BIT) >> 1)
79
80 #define SB_ID_OFFSET_SHIFT(wl) (HALF_ULONG_BITS(wl) + 1)
81 #define SB_ID_OFFSET_COUNT(wl) (1UL << SB_ID_OFFSET_SHIFT(wl))
82 #define SB_ID_OFFSET_MASK(wl) (~(SB_ID_OFFSET_COUNT(wl) - 1))
83 /*
84 * Lowest bit of top word half belongs to noref. Used only for overwrite mode.
85 */
86 #define SB_ID_NOREF_SHIFT(wl) (SB_ID_OFFSET_SHIFT(wl) - 1)
87 #define SB_ID_NOREF_COUNT(wl) (1UL << SB_ID_NOREF_SHIFT(wl))
88 #define SB_ID_NOREF_MASK(wl) SB_ID_NOREF_COUNT(wl)
89 /*
90 * In overwrite mode: lowest half of word is used for index.
91 * Limit of 2^16 subbuffers per buffer on 32-bit, 2^32 on 64-bit.
92 * In producer-consumer mode: whole word used for index.
93 */
94 #define SB_ID_INDEX_SHIFT(wl) 0
95 #define SB_ID_INDEX_COUNT(wl) (1UL << SB_ID_INDEX_SHIFT(wl))
96 #define SB_ID_INDEX_MASK(wl) (SB_ID_NOREF_COUNT(wl) - 1)
97
98 enum rb_modes {
99 RING_BUFFER_OVERWRITE = 0, /* Overwrite when buffer full */
100 RING_BUFFER_DISCARD = 1, /* Discard when buffer full */
101 };
102
103 struct crash_abi_unknown {
104 uint8_t magic[RB_CRASH_DUMP_ABI_MAGIC_LEN];
105 uint64_t mmap_length; /* Overall length of crash record */
106 uint16_t endian; /*
107 * { 0x12, 0x34 }: big endian
108 * { 0x34, 0x12 }: little endian
109 */
110 uint16_t major; /* Major number. */
111 uint16_t minor; /* Minor number. */
112 uint8_t word_size; /* Word size (bytes). */
113 uint8_t layout_type; /* enum lttng_crash_layout */
114 } __attribute__((packed));
115
116 struct crash_abi_0_0 {
117 struct crash_abi_unknown parent;
118
119 struct {
120 uint32_t prod_offset;
121 uint32_t consumed_offset;
122 uint32_t commit_hot_array;
123 uint32_t commit_hot_seq;
124 uint32_t buf_wsb_array;
125 uint32_t buf_wsb_id;
126 uint32_t sb_array;
127 uint32_t sb_array_shmp_offset;
128 uint32_t sb_backend_p_offset;
129 uint32_t content_size;
130 uint32_t packet_size;
131 } __attribute__((packed)) offset;
132 struct {
133 uint8_t prod_offset;
134 uint8_t consumed_offset;
135 uint8_t commit_hot_seq;
136 uint8_t buf_wsb_id;
137 uint8_t sb_array_shmp_offset;
138 uint8_t sb_backend_p_offset;
139 uint8_t content_size;
140 uint8_t packet_size;
141 } __attribute__((packed)) length;
142 struct {
143 uint32_t commit_hot_array;
144 uint32_t buf_wsb_array;
145 uint32_t sb_array;
146 } __attribute__((packed)) stride;
147
148 uint64_t buf_size; /* Size of the buffer */
149 uint64_t subbuf_size; /* Sub-buffer size */
150 uint64_t num_subbuf; /* Number of sub-buffers for writer */
151 uint32_t mode; /* Buffer mode: 0: overwrite, 1: discard */
152 } __attribute__((packed));
153
154 struct lttng_crash_layout {
155 struct {
156 int prod_offset, consumed_offset,
157 commit_hot_array, commit_hot_seq,
158 buf_wsb_array, buf_wsb_id,
159 sb_array, sb_array_shmp_offset,
160 sb_backend_p_offset, content_size,
161 packet_size;
162 } offset;
163 struct {
164 int prod_offset, consumed_offset,
165 commit_hot_seq, buf_wsb_id,
166 sb_array_shmp_offset, sb_backend_p_offset,
167 content_size, packet_size;
168 } length;
169 struct {
170 int commit_hot_array, buf_wsb_array, sb_array;
171 } stride;
172
173 int reverse_byte_order;
174 int word_size;
175
176 uint64_t mmap_length; /* Length of crash record */
177 uint64_t buf_size; /* Size of the buffer */
178 uint64_t subbuf_size; /* Sub-buffer size */
179 uint64_t num_subbuf; /* Number of sub-buffers for writer */
180 uint32_t mode; /* Buffer mode: 0: overwrite, 1: discard */
181 };
182
183 /* Variables */
184 static char *progname,
185 *opt_viewer_path = NULL,
186 *opt_output_path = NULL;
187
188 static char *input_path;
189
190 int lttng_opt_quiet, lttng_opt_verbose, lttng_opt_mi;
191
192 enum {
193 OPT_DUMP_OPTIONS,
194 };
195
196 /* Getopt options. No first level command. */
197 static struct option long_options[] = {
198 { "version", 0, NULL, 'V' },
199 { "help", 0, NULL, 'h' },
200 { "verbose", 0, NULL, 'v' },
201 { "viewer", 1, NULL, 'e' },
202 { "extract", 1, NULL, 'x' },
203 { "list-options", 0, NULL, OPT_DUMP_OPTIONS },
204 { NULL, 0, NULL, 0 },
205 };
206
207 static void usage(FILE *ofp)
208 {
209 fprintf(ofp, "LTTng Crash Trace Viewer " VERSION " - " VERSION_NAME "%s\n\n",
210 GIT_VERSION[0] == '\0' ? "" : " - " GIT_VERSION);
211 fprintf(ofp, "usage: lttng-crash [OPTIONS] FILE\n");
212 fprintf(ofp, "\n");
213 fprintf(ofp, "Options:\n");
214 fprintf(ofp, " -V, --version Show version.\n");
215 fprintf(ofp, " -h, --help Show this help.\n");
216 fprintf(ofp, " --list-options Simple listing of lttng-crash options.\n");
217 fprintf(ofp, " -v, --verbose Increase verbosity.\n");
218 fprintf(ofp, " -e, --viewer Specify viewer and/or options to use. This will\n"
219 " completely override the default viewers so please\n"
220 " make sure to specify the full command. The trace\n"
221 " directory paths appended at the end to the\n"
222 " arguments.\n");
223 fprintf(ofp, " -x, --extract PATH Extract trace(s) to specified path. Don't view\n"
224 " trace.\n");
225 fprintf(ofp, "\n");
226 fprintf(ofp, "Please see the lttng-crash(1) man page for full documentation.\n");
227 fprintf(ofp, "See http://lttng.org for updates, bug reports and news.\n");
228 }
229
230 static void version(FILE *ofp)
231 {
232 fprintf(ofp, "%s (LTTng Crash Trace Viewer) " VERSION " - " VERSION_NAME
233 "%s\n",
234 progname,
235 GIT_VERSION[0] == '\0' ? "" : " - " GIT_VERSION);
236 }
237
238 /*
239 * list_options
240 *
241 * List options line by line. This is mostly for bash auto completion and to
242 * avoid difficult parsing.
243 */
244 static void list_options(FILE *ofp)
245 {
246 int i = 0;
247 struct option *option = NULL;
248
249 option = &long_options[i];
250 while (option->name != NULL) {
251 fprintf(ofp, "--%s\n", option->name);
252
253 if (isprint(option->val)) {
254 fprintf(ofp, "-%c\n", option->val);
255 }
256
257 i++;
258 option = &long_options[i];
259 }
260 }
261
262 /*
263 * Parse command line arguments.
264 *
265 * Return 0 if OK, else -1
266 */
267 static int parse_args(int argc, char **argv)
268 {
269 int opt, ret = 0;
270
271 if (argc < 2) {
272 usage(stderr);
273 exit(EXIT_FAILURE);
274 }
275
276 while ((opt = getopt_long(argc, argv, "+Vhve:x:", long_options, NULL)) != -1) {
277 switch (opt) {
278 case 'V':
279 version(stdout);
280 ret = 1;
281 goto end;
282 case 'h':
283 usage(stdout);
284 ret = 1;
285 goto end;
286 case 'v':
287 /* There is only 3 possible level of verbosity. (-vvv) */
288 if (lttng_opt_verbose < 3) {
289 lttng_opt_verbose += 1;
290 }
291 break;
292 case 'e':
293 free(opt_viewer_path);
294 opt_viewer_path = strdup(optarg);
295 break;
296 case 'x':
297 free(opt_output_path);
298 opt_output_path = strdup(optarg);
299 break;
300 case OPT_DUMP_OPTIONS:
301 list_options(stdout);
302 ret = 1;
303 goto end;
304 default:
305 usage(stderr);
306 goto error;
307 }
308 }
309
310 if (!opt_viewer_path) {
311 opt_viewer_path = DEFAULT_VIEWER;
312 }
313
314 /* No leftovers, or more than one input path, print usage and quit */
315 if ((argc - optind) == 0 || (argc - optind) > 1) {
316 usage(stderr);
317 goto error;
318 }
319
320 input_path = argv[optind];
321 end:
322 return ret;
323
324 error:
325 return -1;
326 }
327
328 static
329 int copy_file(const char *file_dest, const char *file_src)
330 {
331 int fd_src = -1, fd_dest = -1;
332 ssize_t readlen, writelen;
333 char buf[COPY_BUFLEN];
334 int ret;
335
336 DBG("Copy metadata file '%s' into '%s'", file_src, file_dest);
337
338 fd_src = open(file_src, O_RDONLY);
339 if (fd_src < 0) {
340 PERROR("Error opening %s for reading", file_src);
341 ret = -errno;
342 goto error;
343 }
344 fd_dest = open(file_dest, O_RDWR | O_CREAT | O_EXCL,
345 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
346 if (fd_dest < 0) {
347 PERROR("Error opening %s for writing", file_dest);
348 ret = -errno;
349 goto error;
350 }
351
352 for (;;) {
353 readlen = lttng_read(fd_src, buf, COPY_BUFLEN);
354 if (readlen < 0) {
355 PERROR("Error reading input file");
356 ret = -1;
357 goto error;
358 }
359 if (!readlen) {
360 break;
361 }
362 writelen = lttng_write(fd_dest, buf, readlen);
363 if (writelen < readlen) {
364 PERROR("Error writing to output file");
365 ret = -1;
366 goto error;
367 }
368 }
369
370 ret = 0;
371 error:
372 if (fd_src >= 0) {
373 if (close(fd_src) < 0) {
374 PERROR("Error closing %s", file_src);
375 }
376 }
377
378 if (fd_dest >= 0) {
379 if (close(fd_dest) < 0) {
380 PERROR("Error closing %s", file_dest);
381 }
382 }
383 return ret;
384 }
385
386 static
387 uint64_t _crash_get_field(const struct lttng_crash_layout *layout,
388 const char *ptr, size_t size)
389 {
390 switch (size) {
391 case 1: return *(uint8_t *) ptr;
392 case 2: if (layout->reverse_byte_order) {
393 return __bswap_16(*(uint16_t *) ptr);
394 } else {
395 return *(uint16_t *) ptr;
396
397 }
398 case 4: if (layout->reverse_byte_order) {
399 return __bswap_32(*(uint32_t *) ptr);
400 } else {
401 return *(uint32_t *) ptr;
402
403 }
404 case 8: if (layout->reverse_byte_order) {
405 return __bswap_64(*(uint64_t *) ptr);
406 } else {
407 return *(uint64_t *) ptr;
408 }
409 default:
410 abort();
411 return -1;
412 }
413
414 }
415
416 #define crash_get_field(layout, map, name) \
417 _crash_get_field(layout, (map) + (layout)->offset.name, \
418 layout->length.name)
419
420 #define crash_get_array_field(layout, map, array_name, idx, field_name) \
421 _crash_get_field(layout, \
422 (map) + (layout)->offset.array_name \
423 + (idx * (layout)->stride.array_name) \
424 + (layout)->offset.field_name, \
425 (layout)->length.field_name)
426
427 #define crash_get_hdr_raw_field(layout, hdr, name) ((hdr)->name)
428
429 #define crash_get_hdr_field(layout, hdr, name) \
430 _crash_get_field(layout, (const char *) &(hdr)->name, \
431 sizeof((hdr)->name))
432
433 #define crash_get_layout(layout, hdr, name) \
434 do { \
435 (layout)->name = crash_get_hdr_field(layout, hdr, \
436 name); \
437 DBG("layout.%s = %" PRIu64, #name, \
438 (uint64_t) (layout)->name); \
439 } while (0)
440
441 static
442 int get_crash_layout_0_0(struct lttng_crash_layout *layout,
443 char *map)
444 {
445 const struct crash_abi_0_0 *abi = (const struct crash_abi_0_0 *) map;
446
447 crash_get_layout(layout, abi, offset.prod_offset);
448 crash_get_layout(layout, abi, offset.consumed_offset);
449 crash_get_layout(layout, abi, offset.commit_hot_array);
450 crash_get_layout(layout, abi, offset.commit_hot_seq);
451 crash_get_layout(layout, abi, offset.buf_wsb_array);
452 crash_get_layout(layout, abi, offset.buf_wsb_id);
453 crash_get_layout(layout, abi, offset.sb_array);
454 crash_get_layout(layout, abi, offset.sb_array_shmp_offset);
455 crash_get_layout(layout, abi, offset.sb_backend_p_offset);
456 crash_get_layout(layout, abi, offset.content_size);
457 crash_get_layout(layout, abi, offset.packet_size);
458
459 crash_get_layout(layout, abi, length.prod_offset);
460 crash_get_layout(layout, abi, length.consumed_offset);
461 crash_get_layout(layout, abi, length.commit_hot_seq);
462 crash_get_layout(layout, abi, length.buf_wsb_id);
463 crash_get_layout(layout, abi, length.sb_array_shmp_offset);
464 crash_get_layout(layout, abi, length.sb_backend_p_offset);
465 crash_get_layout(layout, abi, length.content_size);
466 crash_get_layout(layout, abi, length.packet_size);
467
468 crash_get_layout(layout, abi, stride.commit_hot_array);
469 crash_get_layout(layout, abi, stride.buf_wsb_array);
470 crash_get_layout(layout, abi, stride.sb_array);
471
472 crash_get_layout(layout, abi, buf_size);
473 crash_get_layout(layout, abi, subbuf_size);
474 crash_get_layout(layout, abi, num_subbuf);
475 crash_get_layout(layout, abi, mode);
476
477 return 0;
478 }
479
480 static
481 void print_dbg_magic(const uint8_t *magic)
482 {
483 DBG("magic: 0x%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X",
484 magic[0], magic[1], magic[2], magic[3],
485 magic[4], magic[5], magic[6], magic[7],
486 magic[8], magic[9], magic[10], magic[11],
487 magic[12], magic[13], magic[14], magic[15]);
488 }
489
490 static
491 int check_magic(const uint8_t *magic)
492 {
493 int i;
494
495 for (i = 0; i < RB_CRASH_DUMP_ABI_MAGIC_LEN; i++) {
496 if ((magic[i] ^ 0xFF) != lttng_crash_expected_magic_xor[i]) {
497 return -1;
498 }
499 }
500 return 0;
501 }
502
503 static
504 int get_crash_layout(struct lttng_crash_layout *layout, int fd)
505 {
506 char *map;
507 int ret = 0, unmapret;
508 const uint8_t *magic;
509 uint64_t mmap_length;
510 uint16_t major, minor;
511 uint8_t word_size;
512 const struct crash_abi_unknown *abi;
513 uint16_t endian;
514 enum lttng_crash_type layout_type;
515
516 map = mmap(NULL, RB_CRASH_DUMP_ABI_LEN, PROT_READ, MAP_PRIVATE,
517 fd, 0);
518 if (map == MAP_FAILED) {
519 PERROR("Mapping file");
520 return -1;
521 }
522 abi = (const struct crash_abi_unknown *) map;
523 magic = crash_get_hdr_raw_field(layout, abi, magic);
524 print_dbg_magic(magic);
525 if (check_magic(magic)) {
526 DBG("Unknown magic number");
527 ret = 1; /* positive return value, skip */
528 goto end;
529 }
530 endian = crash_get_hdr_field(layout, abi, endian);
531 switch (endian) {
532 case RB_CRASH_ENDIAN:
533 break;
534 case RB_CRASH_ENDIAN_REVERSE:
535 layout->reverse_byte_order = 1;
536 break;
537 default:
538 DBG("Unknown endianness value: 0x%X", (unsigned int) endian);
539 ret = 1; /* positive return value, skip */
540 goto end;
541 }
542 layout_type = (enum lttng_crash_type) crash_get_hdr_field(layout, abi, layout_type);
543 switch (layout_type) {
544 case LTTNG_CRASH_TYPE_UST:
545 break;
546 case LTTNG_CRASH_TYPE_KERNEL:
547 ERR("lttng-modules buffer layout support not implemented");
548 ret = 1; /* positive return value, skip */
549 goto end;
550 default:
551 ERR("Unknown layout type %u", (unsigned int) layout_type);
552 ret = 1; /* positive return value, skip */
553 goto end;
554 }
555 mmap_length = crash_get_hdr_field(layout, abi, mmap_length);
556 DBG("mmap_length: %" PRIu64, mmap_length);
557 layout->mmap_length = mmap_length;
558 major = crash_get_hdr_field(layout, abi, major);
559 DBG("major: %u", major);
560 minor = crash_get_hdr_field(layout, abi, minor);
561 DBG("minor: %u", minor);
562 word_size = crash_get_hdr_field(layout, abi, word_size);
563 DBG("word_size: %u", word_size);
564 switch (major) {
565 case 0:
566 switch (minor) {
567 case 0:
568 ret = get_crash_layout_0_0(layout, map);
569 if (ret)
570 goto end;
571 break;
572 default:
573 ret = -1;
574 ERR("Unsupported crash ABI %u.%u\n", major, minor);
575 goto end;
576 }
577 break;
578 default:
579 ERR("Unsupported crash ABI %u.%u\n", major, minor);
580 ret = -1;
581 goto end;
582 }
583 layout->word_size = word_size;
584 end:
585 unmapret = munmap(map, RB_CRASH_DUMP_ABI_LEN);
586 if (unmapret) {
587 PERROR("munmap");
588 }
589 return ret;
590 }
591
592 /* buf_trunc mask selects only the buffer number. */
593 static inline
594 uint64_t buf_trunc(uint64_t offset, uint64_t buf_size)
595 {
596 return offset & ~(buf_size - 1);
597 }
598
599 /* subbuf_trunc mask selects the subbuffer number. */
600 static inline
601 uint64_t subbuf_trunc(uint64_t offset, uint64_t subbuf_size)
602 {
603 return offset & ~(subbuf_size - 1);
604 }
605
606 /* buf_offset mask selects only the offset within the current buffer. */
607 static inline
608 uint64_t buf_offset(uint64_t offset, uint64_t buf_size)
609 {
610 return offset & (buf_size - 1);
611 }
612
613 /* subbuf_offset mask selects the offset within the current subbuffer. */
614 static inline
615 uint64_t subbuf_offset(uint64_t offset, uint64_t subbuf_size)
616 {
617 return offset & (subbuf_size - 1);
618 }
619
620 /* subbuf_index returns the index of the current subbuffer within the buffer. */
621 static inline
622 uint64_t subbuf_index(uint64_t offset, uint64_t buf_size, uint64_t subbuf_size)
623 {
624 return buf_offset(offset, buf_size) / subbuf_size;
625 }
626
627 static inline
628 uint64_t subbuffer_id_get_index(uint32_t mode, uint64_t id,
629 unsigned int wl)
630 {
631 if (mode == RING_BUFFER_OVERWRITE)
632 return id & SB_ID_INDEX_MASK(wl);
633 else
634 return id;
635 }
636
637 static
638 int copy_crash_subbuf(const struct lttng_crash_layout *layout,
639 int fd_dest, char *buf, uint64_t offset)
640 {
641 uint64_t buf_size, subbuf_size, num_subbuf, sbidx, id,
642 sb_bindex, rpages_offset, p_offset, seq_cc,
643 committed, commit_count_mask, consumed_cur,
644 packet_size;
645 char *subbuf_ptr;
646 ssize_t writelen;
647
648 /*
649 * Get the current subbuffer by applying the proper mask to
650 * "offset", and looking up the subbuf location within the
651 * source file buf.
652 */
653
654 buf_size = layout->buf_size;
655 subbuf_size = layout->subbuf_size;
656 num_subbuf = layout->num_subbuf;
657
658 switch (layout->word_size) {
659 case 4: commit_count_mask = 0xFFFFFFFFULL / num_subbuf;
660 break;
661 case 8: commit_count_mask = 0xFFFFFFFFFFFFFFFFULL / num_subbuf;
662 break;
663 default:
664 ERR("Unsupported word size: %u",
665 (unsigned int) layout->word_size);
666 return -EINVAL;
667 }
668
669 DBG("Copy crash subbuffer at offset %" PRIu64, offset);
670 sbidx = subbuf_index(offset, buf_size, subbuf_size);
671
672 /*
673 * Find where the seq cc is located. Compute length of data to
674 * copy.
675 */
676 seq_cc = crash_get_array_field(layout, buf, commit_hot_array,
677 sbidx, commit_hot_seq);
678 consumed_cur = crash_get_field(layout, buf, consumed_offset);
679
680 /*
681 * Check that the buffer we are getting is after or at
682 * consumed_cur position.
683 */
684 if ((long) subbuf_trunc(offset, subbuf_size)
685 - (long) subbuf_trunc(consumed_cur, subbuf_size) < 0) {
686 DBG("No data: position is before consumed_cur");
687 goto nodata;
688 }
689
690 /*
691 * Check if subbuffer has been fully committed.
692 */
693 if (((seq_cc - subbuf_size) & commit_count_mask)
694 - (buf_trunc(offset, buf_size) / num_subbuf)
695 == 0) {
696 committed = subbuf_size;
697 } else {
698 committed = subbuf_offset(seq_cc, subbuf_size);
699 if (!committed) {
700 DBG("No data committed, seq_cc: %" PRIu64, seq_cc);
701 goto nodata;
702 }
703 }
704
705 /* Find actual physical offset in subbuffer table */
706 id = crash_get_array_field(layout, buf, buf_wsb_array,
707 sbidx, buf_wsb_id);
708 sb_bindex = subbuffer_id_get_index(layout->mode, id,
709 layout->word_size);
710 rpages_offset = crash_get_array_field(layout, buf, sb_array,
711 sb_bindex, sb_array_shmp_offset);
712 p_offset = crash_get_field(layout, buf + rpages_offset,
713 sb_backend_p_offset);
714 subbuf_ptr = buf + p_offset;
715
716 if (committed == subbuf_size) {
717 /*
718 * Packet header can be used.
719 */
720 if (layout->length.packet_size) {
721 memcpy(&packet_size,
722 subbuf_ptr + layout->offset.packet_size,
723 layout->length.packet_size);
724 if (layout->reverse_byte_order) {
725 packet_size = __bswap_64(packet_size);
726 }
727 packet_size /= CHAR_BIT;
728 } else {
729 packet_size = subbuf_size;
730 }
731 } else {
732 uint64_t patch_size;
733
734 /*
735 * Find where to patch the sub-buffer header with actual
736 * readable data len and packet len, derived from seq
737 * cc. Patch it in our in-memory copy.
738 */
739 patch_size = committed * CHAR_BIT;
740 if (layout->reverse_byte_order) {
741 patch_size = __bswap_64(patch_size);
742 }
743 if (layout->length.content_size) {
744 memcpy(subbuf_ptr + layout->offset.content_size,
745 &patch_size, layout->length.content_size);
746 }
747 if (layout->length.packet_size) {
748 memcpy(subbuf_ptr + layout->offset.packet_size,
749 &patch_size, layout->length.packet_size);
750 }
751 packet_size = committed;
752 }
753
754 /*
755 * Copy packet into fd_dest.
756 */
757 writelen = lttng_write(fd_dest, subbuf_ptr, packet_size);
758 if (writelen < packet_size) {
759 PERROR("Error writing to output file");
760 return -1;
761 }
762 DBG("Copied %" PRIu64 " bytes of data", packet_size);
763 return 0;
764
765 nodata:
766 return -ENODATA;
767 }
768
769 static
770 int copy_crash_data(const struct lttng_crash_layout *layout, int fd_dest,
771 int fd_src)
772 {
773 char *buf;
774 int ret = 0, has_data = 0;
775 struct stat statbuf;
776 size_t src_file_len;
777 uint64_t prod_offset, consumed_offset;
778 uint64_t offset, subbuf_size;
779 ssize_t readlen;
780
781 ret = fstat(fd_src, &statbuf);
782 if (ret) {
783 return ret;
784 }
785 src_file_len = layout->mmap_length;
786 buf = zmalloc(src_file_len);
787 if (!buf) {
788 return -1;
789 }
790 readlen = lttng_read(fd_src, buf, src_file_len);
791 if (readlen < 0) {
792 PERROR("Error reading input file");
793 ret = -1;
794 goto end;
795 }
796
797 prod_offset = crash_get_field(layout, buf, prod_offset);
798 DBG("prod_offset: 0x%" PRIx64, prod_offset);
799 consumed_offset = crash_get_field(layout, buf, consumed_offset);
800 DBG("consumed_offset: 0x%" PRIx64, consumed_offset);
801 subbuf_size = layout->subbuf_size;
802
803 for (offset = consumed_offset; offset < prod_offset;
804 offset += subbuf_size) {
805 ret = copy_crash_subbuf(layout, fd_dest, buf, offset);
806 if (!ret) {
807 has_data = 1;
808 }
809 if (ret) {
810 goto end;
811 }
812 }
813 end:
814 free(buf);
815 if (ret && ret != -ENODATA) {
816 return ret;
817 }
818 if (has_data) {
819 return 0;
820 } else {
821 return -ENODATA;
822 }
823 }
824
825 static
826 int extract_file(int output_dir_fd, const char *output_file,
827 int input_dir_fd, const char *input_file)
828 {
829 int fd_dest, fd_src, ret = 0, closeret;
830 struct lttng_crash_layout layout;
831
832 layout.reverse_byte_order = 0; /* For reading magic number */
833
834 DBG("Extract file '%s'", input_file);
835 fd_src = openat(input_dir_fd, input_file, O_RDONLY);
836 if (fd_src < 0) {
837 PERROR("Error opening '%s' for reading",
838 input_file);
839 ret = -1;
840 goto end;
841 }
842
843 /* Query the crash ABI layout */
844 ret = get_crash_layout(&layout, fd_src);
845 if (ret) {
846 goto close_src;
847 }
848
849 fd_dest = openat(output_dir_fd, output_file,
850 O_RDWR | O_CREAT | O_EXCL,
851 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
852 if (fd_dest < 0) {
853 PERROR("Error opening '%s' for writing",
854 output_file);
855 ret = -1;
856 goto close_src;
857 }
858
859 ret = copy_crash_data(&layout, fd_dest, fd_src);
860 if (ret) {
861 goto close_dest;
862 }
863
864 close_dest:
865 closeret = close(fd_dest);
866 if (closeret) {
867 PERROR("close");
868 }
869 if (ret == -ENODATA) {
870 closeret = unlinkat(output_dir_fd, output_file, 0);
871 if (closeret) {
872 PERROR("unlinkat");
873 }
874 }
875 close_src:
876 closeret = close(fd_src);
877 if (closeret) {
878 PERROR("close");
879 }
880 end:
881 return ret;
882 }
883
884 static
885 int extract_all_files(const char *output_path,
886 const char *input_path)
887 {
888 DIR *input_dir, *output_dir;
889 int input_dir_fd, output_dir_fd, ret = 0, closeret;
890 struct dirent *entry; /* input */
891
892 /* Open input directory */
893 input_dir = opendir(input_path);
894 if (!input_dir) {
895 PERROR("Cannot open '%s' path", input_path);
896 return -1;
897 }
898 input_dir_fd = dirfd(input_dir);
899 if (input_dir_fd < 0) {
900 PERROR("dirfd");
901 return -1;
902 }
903
904 /* Open output directory */
905 output_dir = opendir(output_path);
906 if (!output_dir) {
907 PERROR("Cannot open '%s' path", output_path);
908 return -1;
909 }
910 output_dir_fd = dirfd(output_dir);
911 if (output_dir_fd < 0) {
912 PERROR("dirfd");
913 return -1;
914 }
915
916 while ((entry = readdir(input_dir))) {
917 if (!strcmp(entry->d_name, ".")
918 || !strcmp(entry->d_name, ".."))
919 continue;
920 ret = extract_file(output_dir_fd, entry->d_name,
921 input_dir_fd, entry->d_name);
922 if (ret == -ENODATA) {
923 DBG("No data in file '%s', skipping", entry->d_name);
924 ret = 0;
925 continue;
926 } else if (ret < 0) {
927 break;
928 } else if (ret > 0) {
929 DBG("Skipping file '%s'", entry->d_name);
930 ret = 0;
931 continue;
932 }
933 }
934 closeret = closedir(output_dir);
935 if (closeret) {
936 PERROR("closedir");
937 }
938 closeret = closedir(input_dir);
939 if (closeret) {
940 PERROR("closedir");
941 }
942 return ret;
943 }
944
945 static
946 int extract_one_trace(const char *output_path,
947 const char *input_path)
948 {
949 char dest[PATH_MAX], src[PATH_MAX];
950 int ret;
951
952 DBG("Extract crash trace '%s' into '%s'", input_path, output_path);
953
954 /* Copy metadata */
955 strncpy(dest, output_path, PATH_MAX);
956 dest[PATH_MAX - 1] = '\0';
957 strncat(dest, "/metadata", PATH_MAX - strlen(dest) - 1);
958
959 strncpy(src, input_path, PATH_MAX);
960 src[PATH_MAX - 1] = '\0';
961 strncat(src, "/metadata", PATH_MAX - strlen(dest) - 1);
962
963 ret = copy_file(dest, src);
964 if (ret) {
965 return ret;
966 }
967
968 /* Extract each other file that has expected header */
969 return extract_all_files(output_path, input_path);
970 }
971
972 static
973 int extract_trace_recursive(const char *output_path,
974 const char *input_path)
975 {
976 DIR *dir;
977 int dir_fd, ret = 0, closeret;
978 struct dirent *entry;
979 int has_warning = 0;
980
981 /* Open directory */
982 dir = opendir(input_path);
983 if (!dir) {
984 PERROR("Cannot open '%s' path", input_path);
985 return -1;
986 }
987 dir_fd = dirfd(dir);
988 if (dir_fd < 0) {
989 PERROR("dirfd");
990 return -1;
991 }
992
993 while ((entry = readdir(dir))) {
994 if (!strcmp(entry->d_name, ".")
995 || !strcmp(entry->d_name, "..")) {
996 continue;
997 }
998 switch (entry->d_type) {
999 case DT_DIR:
1000 {
1001 char output_subpath[PATH_MAX];
1002 char input_subpath[PATH_MAX];
1003
1004 strncpy(output_subpath, output_path,
1005 sizeof(output_subpath));
1006 output_subpath[sizeof(output_subpath) - 1] = '\0';
1007 strncat(output_subpath, "/",
1008 sizeof(output_subpath) - strlen(output_subpath) - 1);
1009 strncat(output_subpath, entry->d_name,
1010 sizeof(output_subpath) - strlen(output_subpath) - 1);
1011
1012 ret = mkdir(output_subpath, S_IRWXU | S_IRWXG);
1013 if (ret) {
1014 PERROR("mkdir");
1015 has_warning = 1;
1016 goto end;
1017 }
1018
1019 strncpy(input_subpath, input_path,
1020 sizeof(input_subpath));
1021 input_subpath[sizeof(input_subpath) - 1] = '\0';
1022 strncat(input_subpath, "/",
1023 sizeof(input_subpath) - strlen(input_subpath) - 1);
1024 strncat(input_subpath, entry->d_name,
1025 sizeof(input_subpath) - strlen(input_subpath) - 1);
1026
1027 ret = extract_trace_recursive(output_subpath,
1028 input_subpath);
1029 if (ret) {
1030 has_warning = 1;
1031 }
1032 break;
1033 }
1034 case DT_REG:
1035 case DT_LNK:
1036 if (!strcmp(entry->d_name, "metadata")) {
1037 ret = extract_one_trace(output_path,
1038 input_path);
1039 if (ret) {
1040 WARN("Error extracting trace '%s', continuing anyway.",
1041 input_path);
1042 has_warning = 1;
1043 }
1044 }
1045 /* Ignore other files */
1046 break;
1047 default:
1048 has_warning = 1;
1049 goto end;
1050 }
1051 }
1052 end:
1053 closeret = closedir(dir);
1054 if (closeret) {
1055 PERROR("closedir");
1056 }
1057 return has_warning;
1058 }
1059
1060 static
1061 int delete_dir_recursive(const char *path)
1062 {
1063 DIR *dir;
1064 int dir_fd, ret = 0, closeret;
1065 struct dirent *entry;
1066
1067 /* Open trace directory */
1068 dir = opendir(path);
1069 if (!dir) {
1070 PERROR("Cannot open '%s' path", path);
1071 ret = -errno;
1072 goto end;
1073 }
1074 dir_fd = dirfd(dir);
1075 if (dir_fd < 0) {
1076 PERROR("dirfd");
1077 ret = -errno;
1078 goto end;
1079 }
1080
1081 while ((entry = readdir(dir))) {
1082 if (!strcmp(entry->d_name, ".")
1083 || !strcmp(entry->d_name, "..")) {
1084 continue;
1085 }
1086 switch (entry->d_type) {
1087 case DT_DIR:
1088 {
1089 char *subpath = zmalloc(PATH_MAX);
1090
1091 if (!subpath) {
1092 PERROR("zmalloc path");
1093 ret = -1;
1094 goto end;
1095 }
1096 strncpy(subpath, path, PATH_MAX);
1097 subpath[PATH_MAX - 1] = '\0';
1098 strncat(subpath, "/",
1099 PATH_MAX - strlen(subpath) - 1);
1100 strncat(subpath, entry->d_name,
1101 PATH_MAX - strlen(subpath) - 1);
1102
1103 ret = delete_dir_recursive(subpath);
1104 free(subpath);
1105 if (ret) {
1106 /* Error occured, abort traversal. */
1107 goto end;
1108 }
1109 break;
1110 }
1111 case DT_REG:
1112 ret = unlinkat(dir_fd, entry->d_name, 0);
1113 if (ret) {
1114 PERROR("Unlinking '%s'", entry->d_name);
1115 goto end;
1116 }
1117 break;
1118 default:
1119 ret = -EINVAL;
1120 goto end;
1121 }
1122 }
1123 end:
1124 if (!ret) {
1125 ret = rmdir(path);
1126 if (ret) {
1127 PERROR("rmdir '%s'", path);
1128 }
1129 }
1130 closeret = closedir(dir);
1131 if (closeret) {
1132 PERROR("closedir");
1133 }
1134 return ret;
1135 }
1136
1137 static
1138 int view_trace(const char *viewer_path, const char *trace_path)
1139 {
1140 pid_t pid;
1141
1142 pid = fork();
1143 if (pid < 0) {
1144 /* Error */
1145 PERROR("fork");
1146 return -1;
1147 } else if (pid > 0) {
1148 /* Parent */
1149 int status;
1150
1151 pid = waitpid(pid, &status, 0);
1152 if (pid < 0 || !WIFEXITED(status)) {
1153 return -1;
1154 }
1155 } else {
1156 /* Child */
1157 int ret;
1158
1159 ret = execlp(viewer_path, viewer_path,
1160 trace_path, (char *) NULL);
1161 if (ret) {
1162 PERROR("execlp");
1163 exit(EXIT_FAILURE);
1164 }
1165 exit(EXIT_SUCCESS); /* Never reached */
1166 }
1167 return 0;
1168 }
1169
1170 /*
1171 * main
1172 */
1173 int main(int argc, char *argv[])
1174 {
1175 int ret;
1176 bool has_warning = false;
1177 const char *output_path = NULL;
1178 char tmppath[] = "/tmp/lttng-crash-XXXXXX";
1179
1180 progname = argv[0] ? argv[0] : "lttng-crash";
1181
1182 ret = parse_args(argc, argv);
1183 if (ret > 0) {
1184 goto end;
1185 } else if (ret < 0) {
1186 has_warning = true;
1187 goto end;
1188 }
1189
1190 if (opt_output_path) {
1191 output_path = opt_output_path;
1192 ret = mkdir(output_path, S_IRWXU | S_IRWXG);
1193 if (ret) {
1194 PERROR("mkdir");
1195 has_warning = true;
1196 goto end;
1197 }
1198 } else {
1199 output_path = mkdtemp(tmppath);
1200 if (!output_path) {
1201 PERROR("mkdtemp");
1202 has_warning = true;
1203 goto end;
1204 }
1205 }
1206
1207 ret = extract_trace_recursive(output_path, input_path);
1208 if (ret < 0) {
1209 has_warning = true;
1210 goto end;
1211 } else if (ret > 0) {
1212 /* extract_trace_recursive reported a warning. */
1213 has_warning = true;
1214 }
1215 if (!opt_output_path) {
1216 /* View trace */
1217 ret = view_trace(opt_viewer_path, output_path);
1218 if (ret) {
1219 has_warning = true;
1220 }
1221 /* unlink temporary trace */
1222 ret = delete_dir_recursive(output_path);
1223 if (ret) {
1224 has_warning = true;
1225 }
1226 }
1227 end:
1228 exit(has_warning ? EXIT_FAILURE : EXIT_SUCCESS);
1229 }
This page took 0.094798 seconds and 4 git commands to generate.