2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright (c) 2015, Joyent, Inc.
17 * Dump information about CTF containers. This was inspired by the original
18 * ctfdump written in tools/ctf, but this has been reimplemented in terms of
29 #include <sys/sysmacros.h>
30 #include <sys/types.h>
36 typedef enum ctfdump_arg
{
37 CTFDUMP_OBJECTS
= 0x01,
38 CTFDUMP_FUNCTIONS
= 0x02,
39 CTFDUMP_HEADER
= 0x04,
40 CTFDUMP_LABELS
= 0x08,
41 CTFDUMP_STRINGS
= 0x10,
44 CTFDUMP_DEFAULT
= 0x7f,
45 CTFDUMP_OUTPUT
= 0x80,
49 typedef struct ctfdump_stat
{
50 ulong_t cs_ndata
; /* number of data objects */
51 ulong_t cs_nfuncs
; /* number of functions */
52 ulong_t cs_nfuncargs
; /* number of function args */
53 ulong_t cs_nfuncmax
; /* largest number of args */
54 ulong_t cs_ntypes
[CTF_K_MAX
]; /* number of types */
55 ulong_t cs_nsmembs
; /* number of struct members */
56 ulong_t cs_nsmax
; /* largest number of members */
57 ulong_t cs_structsz
; /* sum of structures sizes */
58 ulong_t cs_sszmax
; /* largest structure */
59 ulong_t cs_numembs
; /* number of union members */
60 ulong_t cs_numax
; /* largest number of members */
61 ulong_t cs_unionsz
; /* sum of unions sizes */
62 ulong_t cs_uszmax
; /* largest union */
63 ulong_t cs_nemembs
; /* number of enum members */
64 ulong_t cs_nemax
; /* largest number of members */
65 ulong_t cs_nstrings
; /* number of strings */
66 ulong_t cs_strsz
; /* string size */
67 ulong_t cs_strmax
; /* longest string */
70 static const char *g_progname
;
71 static ctfdump_arg_t g_dump
;
72 static ctf_file_t
*g_fp
;
73 static ctfdump_stat_t g_stats
;
74 static ctf_id_t
*g_fargc
;
77 static int g_exit
= 0;
79 static const char *ctfdump_fpenc
[] = {
96 * When stats are requested, we have to go through everything. To make our lives
97 * easier, we'll just always allow the code to print everything out, but only
98 * output it if we have actually enabled that section.
101 ctfdump_printf(ctfdump_arg_t arg
, const char *fmt
, ...)
105 if ((arg
& g_dump
) == 0)
109 vfprintf(stdout
, fmt
, ap
);
114 ctfdump_warn(const char *fmt
, ...)
118 (void) fprintf(stderr
, "%s: ", g_progname
);
120 vfprintf(stderr
, fmt
, ap
);
125 ctfdump_fatal(const char *fmt
, ...)
129 (void) fprintf(stderr
, "%s: ", g_progname
);
131 vfprintf(stderr
, fmt
, ap
);
138 ctfdump_usage(const char *fmt
, ...)
142 (void) fprintf(stderr
, "%s: ", g_progname
);
144 (void) vfprintf(stderr
, fmt
, ap
);
148 (void) fprintf(stderr
, "Usage: %s [-dfhlsSt] [-p parent] [-u outfile] "
151 "\t-d dump object data\n"
152 "\t-f dump function data\n"
153 "\t-h dump the CTF header\n"
154 "\t-l dump the label table\n"
155 "\t-p use parent to supply additional information\n"
156 "\t-s dump the string table\n"
157 "\t-S dump statistics about the CTF container\n"
158 "\t-t dump type information\n"
159 "\t-u dump uncompressed CTF data to outfile\n",
164 ctfdump_title(ctfdump_arg_t arg
, const char *header
)
166 static const char line
[] = "----------------------------------------"
167 "----------------------------------------";
168 ctfdump_printf(arg
, "\n- %s %.*s\n\n", header
, (int)78 - strlen(header
),
173 ctfdump_objects_cb(const char *name
, ctf_id_t id
, ulong_t symidx
, void *arg
)
177 len
= snprintf(NULL
, 0, " [%u] %u", g_stats
.cs_ndata
, id
);
178 ctfdump_printf(CTFDUMP_OBJECTS
, " [%u] %u %*s%s (%u)\n",
179 g_stats
.cs_ndata
, id
, MAX(15 - len
, 0), "", name
, symidx
);
185 ctfdump_objects(void)
187 ctfdump_title(CTFDUMP_OBJECTS
, "Data Objects");
188 if (ctf_object_iter(g_fp
, ctfdump_objects_cb
, NULL
) == CTF_ERR
) {
189 ctfdump_warn("failed to dump objects: %s\n",
190 ctf_errmsg(ctf_errno(g_fp
)));
196 ctfdump_fargs_grow(int nargs
)
198 if (g_nfargc
< nargs
) {
199 g_fargc
= reallocarray(g_fargc
, nargs
, sizeof (ctf_id_t
));
201 ctfdump_fatal("failed to get memory for %d "
202 "ctf_id_t's\n", nargs
);
208 ctfdump_functions_cb(const char *name
, ulong_t symidx
, ctf_funcinfo_t
*ctc
,
213 if (ctc
->ctc_argc
!= 0) {
214 ctfdump_fargs_grow(ctc
->ctc_argc
);
215 if (ctf_func_args(g_fp
, symidx
, g_nfargc
, g_fargc
) == CTF_ERR
)
216 ctfdump_fatal("failed to get arguments for function "
217 "%s: %s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
220 ctfdump_printf(CTFDUMP_FUNCTIONS
,
221 " [%lu] %s (%lu) returns: %u args: (", g_stats
.cs_nfuncs
, name
,
222 symidx
, ctc
->ctc_return
);
223 for (i
= 0; i
< ctc
->ctc_argc
; i
++)
224 ctfdump_printf(CTFDUMP_FUNCTIONS
, "%lu%s", g_fargc
[i
],
225 i
+ 1 == ctc
->ctc_argc
? "" : ", ");
226 if (ctc
->ctc_flags
& CTF_FUNC_VARARG
)
227 ctfdump_printf(CTFDUMP_FUNCTIONS
, "%s...",
228 ctc
->ctc_argc
== 0 ? "" : ", ");
229 ctfdump_printf(CTFDUMP_FUNCTIONS
, ")\n");
232 g_stats
.cs_nfuncargs
+= ctc
->ctc_argc
;
233 g_stats
.cs_nfuncmax
= MAX(ctc
->ctc_argc
, g_stats
.cs_nfuncmax
);
239 ctfdump_functions(void)
241 ctfdump_title(CTFDUMP_FUNCTIONS
, "Functions");
243 if (ctf_function_iter(g_fp
, ctfdump_functions_cb
, NULL
) == CTF_ERR
) {
244 ctfdump_warn("failed to dump functions: %s\n",
245 ctf_errmsg(ctf_errno(g_fp
)));
253 const ctf_header_t
*hp
;
254 const char *parname
, *parlabel
;
256 ctfdump_title(CTFDUMP_HEADER
, "CTF Header");
257 ctf_dataptr(g_fp
, (const void **)&hp
, NULL
);
258 ctfdump_printf(CTFDUMP_HEADER
, " cth_magic = 0x%04x\n",
260 ctfdump_printf(CTFDUMP_HEADER
, " cth_version = %u\n",
262 ctfdump_printf(CTFDUMP_HEADER
, " cth_flags = 0x%02x\n",
264 parname
= ctf_parent_name(g_fp
);
265 parlabel
= ctf_parent_label(g_fp
);
266 ctfdump_printf(CTFDUMP_HEADER
, " cth_parlabel = %s\n",
267 parlabel
== NULL
? "(anon)" : parlabel
);
268 ctfdump_printf(CTFDUMP_HEADER
, " cth_parname = %s\n",
269 parname
== NULL
? "(anon)" : parname
);
270 ctfdump_printf(CTFDUMP_HEADER
, " cth_lbloff = %u\n",
272 ctfdump_printf(CTFDUMP_HEADER
, " cth_objtoff = %u\n",
274 ctfdump_printf(CTFDUMP_HEADER
, " cth_funcoff = %u\n",
276 ctfdump_printf(CTFDUMP_HEADER
, " cth_typeoff = %u\n",
278 ctfdump_printf(CTFDUMP_HEADER
, " cth_stroff = %u\n",
280 ctfdump_printf(CTFDUMP_HEADER
, " cth_strlen = %u\n",
285 ctfdump_labels_cb(const char *name
, const ctf_lblinfo_t
*li
, void *arg
)
287 ctfdump_printf(CTFDUMP_LABELS
, " %5lu %s\n", li
->ctb_typeidx
, name
);
294 ctfdump_title(CTFDUMP_LABELS
, "Label Table");
295 if (ctf_label_iter(g_fp
, ctfdump_labels_cb
, NULL
) == CTF_ERR
) {
296 ctfdump_warn("failed to dump labels: %s\n",
297 ctf_errmsg(ctf_errno(g_fp
)));
303 ctfdump_strings_cb(const char *s
, void *arg
)
305 size_t len
= strlen(s
) + 1;
306 ulong_t
*stroff
= arg
;
307 ctfdump_printf(CTFDUMP_STRINGS
, " [%lu] %s\n", *stroff
,
308 *s
== '\0' ? "\\0" : s
);
309 *stroff
= *stroff
+ len
;
310 g_stats
.cs_nstrings
++;
311 g_stats
.cs_strsz
+= len
;
312 g_stats
.cs_strmax
= MAX(g_stats
.cs_strmax
, len
);
317 ctfdump_strings(void)
321 ctfdump_title(CTFDUMP_STRINGS
, "String Table");
322 if (ctf_string_iter(g_fp
, ctfdump_strings_cb
, &stroff
) == CTF_ERR
) {
323 ctfdump_warn("failed to dump strings: %s\n",
324 ctf_errmsg(ctf_errno(g_fp
)));
330 ctfdump_stat_int(const char *name
, ulong_t value
)
332 ctfdump_printf(CTFDUMP_STATS
, " %-36s= %lu\n", name
, value
);
336 ctfdump_stat_fp(const char *name
, float value
)
338 ctfdump_printf(CTFDUMP_STATS
, " %-36s= %.2f\n", name
, value
);
347 ctfdump_title(CTFDUMP_STATS
, "CTF Statistics");
349 ctfdump_stat_int("total number of data objects", g_stats
.cs_ndata
);
350 ctfdump_printf(CTFDUMP_STATS
, "\n");
351 ctfdump_stat_int("total number of functions", g_stats
.cs_nfuncs
);
352 ctfdump_stat_int("total number of function arguments",
353 g_stats
.cs_nfuncargs
);
354 ctfdump_stat_int("maximum argument list length", g_stats
.cs_nfuncmax
);
355 if (g_stats
.cs_nfuncs
!= 0)
356 ctfdump_stat_fp("average argument list length",
357 (float)g_stats
.cs_nfuncargs
/ (float)g_stats
.cs_nfuncs
);
358 ctfdump_printf(CTFDUMP_STATS
, "\n");
361 for (i
= 0; i
< CTF_K_MAX
; i
++)
362 sum
+= g_stats
.cs_ntypes
[i
];
363 ctfdump_stat_int("total number of types", sum
);
364 ctfdump_stat_int("total number of integers",
365 g_stats
.cs_ntypes
[CTF_K_INTEGER
]);
366 ctfdump_stat_int("total number of floats",
367 g_stats
.cs_ntypes
[CTF_K_FLOAT
]);
368 ctfdump_stat_int("total number of pointers",
369 g_stats
.cs_ntypes
[CTF_K_POINTER
]);
370 ctfdump_stat_int("total number of arrays",
371 g_stats
.cs_ntypes
[CTF_K_ARRAY
]);
372 ctfdump_stat_int("total number of func types",
373 g_stats
.cs_ntypes
[CTF_K_FUNCTION
]);
374 ctfdump_stat_int("total number of structs",
375 g_stats
.cs_ntypes
[CTF_K_STRUCT
]);
376 ctfdump_stat_int("total number of unions",
377 g_stats
.cs_ntypes
[CTF_K_UNION
]);
378 ctfdump_stat_int("total number of enums",
379 g_stats
.cs_ntypes
[CTF_K_ENUM
]);
380 ctfdump_stat_int("total number of forward tags",
381 g_stats
.cs_ntypes
[CTF_K_FORWARD
]);
382 ctfdump_stat_int("total number of typedefs",
383 g_stats
.cs_ntypes
[CTF_K_TYPEDEF
]);
384 ctfdump_stat_int("total number of volatile types",
385 g_stats
.cs_ntypes
[CTF_K_VOLATILE
]);
386 ctfdump_stat_int("total number of const types",
387 g_stats
.cs_ntypes
[CTF_K_CONST
]);
388 ctfdump_stat_int("total number of restrict types",
389 g_stats
.cs_ntypes
[CTF_K_RESTRICT
]);
390 ctfdump_stat_int("total number of unknowns (holes)",
391 g_stats
.cs_ntypes
[CTF_K_UNKNOWN
]);
393 ctfdump_printf(CTFDUMP_STATS
, "\n");
394 ctfdump_stat_int("total number of struct members", g_stats
.cs_nsmembs
);
395 ctfdump_stat_int("maximum number of struct members", g_stats
.cs_nsmax
);
396 ctfdump_stat_int("total size of all structs", g_stats
.cs_structsz
);
397 ctfdump_stat_int("maximum size of a struct", g_stats
.cs_sszmax
);
398 if (g_stats
.cs_ntypes
[CTF_K_STRUCT
] != 0) {
399 ctfdump_stat_fp("average number of struct members",
400 (float)g_stats
.cs_nsmembs
/
401 (float)g_stats
.cs_ntypes
[CTF_K_STRUCT
]);
402 ctfdump_stat_fp("average size of a struct",
403 (float)g_stats
.cs_structsz
/
404 (float)g_stats
.cs_ntypes
[CTF_K_STRUCT
]);
406 ctfdump_printf(CTFDUMP_STATS
, "\n");
407 ctfdump_stat_int("total number of union members", g_stats
.cs_numembs
);
408 ctfdump_stat_int("maximum number of union members", g_stats
.cs_numax
);
409 ctfdump_stat_int("total size of all unions", g_stats
.cs_unionsz
);
410 ctfdump_stat_int("maximum size of a union", g_stats
.cs_uszmax
);
411 if (g_stats
.cs_ntypes
[CTF_K_UNION
] != 0) {
412 ctfdump_stat_fp("average number of union members",
413 (float)g_stats
.cs_numembs
/
414 (float)g_stats
.cs_ntypes
[CTF_K_UNION
]);
415 ctfdump_stat_fp("average size of a union",
416 (float)g_stats
.cs_unionsz
/
417 (float)g_stats
.cs_ntypes
[CTF_K_UNION
]);
419 ctfdump_printf(CTFDUMP_STATS
, "\n");
421 ctfdump_stat_int("total number of enum members", g_stats
.cs_nemembs
);
422 ctfdump_stat_int("maximum number of enum members", g_stats
.cs_nemax
);
423 if (g_stats
.cs_ntypes
[CTF_K_ENUM
] != 0) {
424 ctfdump_stat_fp("average number of enum members",
425 (float)g_stats
.cs_nemembs
/
426 (float)g_stats
.cs_ntypes
[CTF_K_ENUM
]);
428 ctfdump_printf(CTFDUMP_STATS
, "\n");
430 ctfdump_stat_int("total number of strings", g_stats
.cs_nstrings
);
431 ctfdump_stat_int("bytes of string data", g_stats
.cs_strsz
);
432 ctfdump_stat_int("maximum string length", g_stats
.cs_strmax
);
433 if (g_stats
.cs_nstrings
!= 0)
434 ctfdump_stat_fp("average string length",
435 (float)g_stats
.cs_strsz
/ (float)g_stats
.cs_nstrings
);
436 ctfdump_printf(CTFDUMP_STATS
, "\n");
440 ctfdump_intenc_name(ctf_encoding_t
*cte
, char *buf
, int len
)
443 boolean_t space
= B_FALSE
;
445 if (cte
->cte_format
== 0 || (cte
->cte_format
&
446 ~(CTF_INT_SIGNED
| CTF_INT_CHAR
| CTF_INT_BOOL
|
447 CTF_INT_VARARGS
)) != 0) {
448 (void) snprintf(buf
, len
, "0x%x", cte
->cte_format
);
452 if (cte
->cte_format
& CTF_INT_SIGNED
) {
453 off
+= snprintf(buf
+ off
, MAX(len
- off
, 0), "%sSIGNED",
454 space
== B_TRUE
? " " : "");
458 if (cte
->cte_format
& CTF_INT_CHAR
) {
459 off
+= snprintf(buf
+ off
, MAX(len
- off
, 0), "%sCHAR",
460 space
== B_TRUE
? " " : "");
464 if (cte
->cte_format
& CTF_INT_BOOL
) {
465 off
+= snprintf(buf
+ off
, MAX(len
- off
, 0), "%sBOOL",
466 space
== B_TRUE
? " " : "");
470 if (cte
->cte_format
& CTF_INT_VARARGS
) {
471 off
+= snprintf(buf
+ off
, MAX(len
- off
, 0), "%sVARARGS",
472 space
== B_TRUE
? " " : "");
478 ctfdump_member_cb(const char *member
, ctf_id_t type
, ulong_t off
, void *arg
)
481 ctfdump_printf(CTFDUMP_TYPES
, "\t%s type=%lu off=%lu\n", member
, type
,
488 ctfdump_enum_cb(const char *name
, int value
, void *arg
)
491 ctfdump_printf(CTFDUMP_TYPES
, "\t%s = %d\n", name
, value
);
497 ctfdump_types_cb(ctf_id_t id
, boolean_t root
, void *arg
)
501 char name
[512], ienc
[128];
508 if ((kind
= ctf_type_kind(g_fp
, id
)) == CTF_ERR
)
509 ctfdump_fatal("encountered malformed ctf, type %s does not "
510 "have a kind: %s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
512 if (ctf_type_name(g_fp
, id
, name
, sizeof (name
)) == NULL
) {
513 if (ctf_errno(g_fp
) != ECTF_NOPARENT
)
514 ctfdump_fatal("type %lu missing name: %s\n", id
,
515 ctf_errmsg(ctf_errno(g_fp
)));
516 (void) snprintf(name
, sizeof (name
), "(unknown %s)",
517 ctf_kind_name(g_fp
, kind
));
520 g_stats
.cs_ntypes
[kind
]++;
522 ctfdump_printf(CTFDUMP_TYPES
, " <%lu> ", id
);
524 ctfdump_printf(CTFDUMP_TYPES
, " [%lu] ", id
);
530 if (ctf_type_encoding(g_fp
, id
, &cte
) == CTF_ERR
)
531 ctfdump_fatal("failed to get encoding information "
532 "for %s: %s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
533 ctfdump_intenc_name(&cte
, ienc
, sizeof (ienc
));
534 ctfdump_printf(CTFDUMP_TYPES
,
535 "%s encoding=%s offset=%u bits=%u",
536 name
, ienc
, cte
.cte_offset
, cte
.cte_bits
);
539 if (ctf_type_encoding(g_fp
, id
, &cte
) == CTF_ERR
)
540 ctfdump_fatal("failed to get encoding information "
541 "for %s: %s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
542 if (cte
.cte_format
< 1 || cte
.cte_format
> 12)
545 encn
= ctfdump_fpenc
[cte
.cte_format
];
546 ctfdump_printf(CTFDUMP_TYPES
, "%s encoding=%s offset=%u "
547 "bits=%u", name
, encn
, cte
.cte_offset
, cte
.cte_bits
);
550 if ((ref
= ctf_type_reference(g_fp
, id
)) == CTF_ERR
)
551 ctfdump_fatal("failed to get reference type for %s: "
552 "%s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
553 ctfdump_printf(CTFDUMP_TYPES
, "%s refers to %lu", name
,
557 if (ctf_array_info(g_fp
, id
, &ar
) == CTF_ERR
)
558 ctfdump_fatal("failed to get array information for "
559 "%s: %s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
560 ctfdump_printf(CTFDUMP_TYPES
, "%s contents: %lu, index: %lu",
561 name
, ar
.ctr_contents
, ar
.ctr_index
);
564 if (ctf_func_info_by_id(g_fp
, id
, &ctc
) == CTF_ERR
)
565 ctfdump_fatal("failed to get function info for %s: "
566 "%s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
567 if (ctc
.ctc_argc
> 0) {
568 ctfdump_fargs_grow(ctc
.ctc_argc
);
569 if (ctf_func_args_by_id(g_fp
, id
, g_nfargc
, g_fargc
) ==
571 ctfdump_fatal("failed to get function "
572 "arguments for %s: %s\n", name
,
573 ctf_errmsg(ctf_errno(g_fp
)));
575 ctfdump_printf(CTFDUMP_TYPES
,
576 "%s returns: %lu args: (", name
, ctc
.ctc_return
);
577 for (i
= 0; i
< ctc
.ctc_argc
; i
++) {
578 ctfdump_printf(CTFDUMP_TYPES
, "%lu%s", g_fargc
[i
],
579 i
+ 1 == ctc
.ctc_argc
? "" : ", ");
581 if (ctc
.ctc_flags
& CTF_FUNC_VARARG
)
582 ctfdump_printf(CTFDUMP_TYPES
, "%s...",
583 ctc
.ctc_argc
== 0 ? "" : ", ");
584 ctfdump_printf(CTFDUMP_TYPES
, ")");
588 size
= ctf_type_size(g_fp
, id
);
590 ctfdump_fatal("failed to get size of %s: %s\n", name
,
591 ctf_errmsg(ctf_errno(g_fp
)));
592 ctfdump_printf(CTFDUMP_TYPES
, "%s (%d bytes)\n", name
, size
);
594 if (ctf_member_iter(g_fp
, id
, ctfdump_member_cb
, &count
) != 0)
595 ctfdump_fatal("failed to iterate members of %s: %s\n",
596 name
, ctf_errmsg(ctf_errno(g_fp
)));
597 if (kind
== CTF_K_STRUCT
) {
598 g_stats
.cs_nsmembs
+= count
;
599 g_stats
.cs_nsmax
= MAX(count
, g_stats
.cs_nsmax
);
600 g_stats
.cs_structsz
+= size
;
601 g_stats
.cs_sszmax
= MAX(size
, g_stats
.cs_sszmax
);
603 g_stats
.cs_numembs
+= count
;
604 g_stats
.cs_numax
= MAX(count
, g_stats
.cs_numax
);
605 g_stats
.cs_unionsz
+= size
;
606 g_stats
.cs_uszmax
= MAX(count
, g_stats
.cs_uszmax
);
610 ctfdump_printf(CTFDUMP_TYPES
, "%s\n", name
);
612 if (ctf_enum_iter(g_fp
, id
, ctfdump_enum_cb
, &count
) != 0)
613 ctfdump_fatal("failed to iterate enumerators of %s: "
614 "%s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
615 g_stats
.cs_nemembs
+= count
;
616 g_stats
.cs_nemax
= MAX(g_stats
.cs_nemax
, count
);
619 ctfdump_printf(CTFDUMP_TYPES
, "forward %s\n", name
);
622 if ((ref
= ctf_type_reference(g_fp
, id
)) == CTF_ERR
)
623 ctfdump_fatal("failed to get reference type for %s: "
624 "%s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
625 ctfdump_printf(CTFDUMP_TYPES
, "typedef %s refers to %lu", name
,
629 if ((ref
= ctf_type_reference(g_fp
, id
)) == CTF_ERR
)
630 ctfdump_fatal("failed to get reference type for %s: "
631 "%s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
632 ctfdump_printf(CTFDUMP_TYPES
, "%s refers to %lu", name
,
636 if ((ref
= ctf_type_reference(g_fp
, id
)) == CTF_ERR
)
637 ctfdump_fatal("failed to get reference type for %s: "
638 "%s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
639 ctfdump_printf(CTFDUMP_TYPES
, "%s refers to %lu", name
,
643 if ((ref
= ctf_type_reference(g_fp
, id
)) == CTF_ERR
)
644 ctfdump_fatal("failed to get reference type for %s: "
645 "%s\n", name
, ctf_errmsg(ctf_errno(g_fp
)));
646 ctfdump_printf(CTFDUMP_TYPES
, "%s refers to %lu", name
,
650 ctfdump_fatal("encountered unknown kind for type %s: %d\n",
654 ctfdump_printf(CTFDUMP_TYPES
, "\n");
662 ctfdump_title(CTFDUMP_TYPES
, "Types");
664 if (ctf_type_iter(g_fp
, B_TRUE
, ctfdump_types_cb
, NULL
) == CTF_ERR
) {
665 ctfdump_warn("failed to dump labels: %s\n",
666 ctf_errmsg(ctf_errno(g_fp
)));
672 ctfdump_output(const char *out
)
678 ctf_dataptr(g_fp
, &data
, &len
);
679 if ((fd
= open(out
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0666)) < 0)
680 ctfdump_fatal("failed to open output file %s: %s\n", out
,
684 ret
= write(fd
, data
, len
);
685 if (ret
== -1 && errno
== EINTR
)
687 else if (ret
== -1 && (errno
== EFAULT
|| errno
== EBADF
))
690 ctfdump_fatal("failed to write to %s: %s\n", out
,
698 } while (ret
== -1 && errno
== EINTR
);
699 if (ret
!= 0 && errno
== EBADF
)
702 ctfdump_fatal("failed to close %s: %s\n", out
, strerror(errno
));
706 main(int argc
, char *argv
[])
709 const char *ufile
= NULL
, *parent
= NULL
;
711 g_progname
= basename(argv
[0]);
712 while ((c
= getopt(argc
, argv
, ":dfhlp:sStu:")) != -1) {
715 g_dump
|= CTFDUMP_OBJECTS
;
718 g_dump
|= CTFDUMP_FUNCTIONS
;
721 g_dump
|= CTFDUMP_HEADER
;
724 g_dump
|= CTFDUMP_LABELS
;
730 g_dump
|= CTFDUMP_STRINGS
;
733 g_dump
|= CTFDUMP_STATS
;
736 g_dump
|= CTFDUMP_TYPES
;
739 g_dump
|= CTFDUMP_OUTPUT
;
743 ctfdump_usage("Unknown option: -%c\n", optopt
);
746 ctfdump_usage("Option -%c requires an operand\n",
756 * Dump all information by default.
759 g_dump
= CTFDUMP_DEFAULT
;
762 ctfdump_usage("no file to dump\n");
766 if ((fd
= open(argv
[0], O_RDONLY
)) < 0)
767 ctfdump_fatal("failed to open file %s: %s\n", argv
[0],
770 g_fp
= ctf_fdopen(fd
, &err
);
772 ctfdump_fatal("failed to open file %s: %s\n", argv
[0],
775 if (parent
!= NULL
) {
776 ctf_file_t
*pfp
= ctf_open(parent
, &err
);
779 ctfdump_fatal("failed to open parent file %s: %s\n",
780 parent
, ctf_errmsg(err
));
781 if (ctf_import(g_fp
, pfp
) != 0)
782 ctfdump_fatal("failed to import parent %s: %s\n",
783 parent
, ctf_errmsg(ctf_errno(g_fp
)));
787 * If stats is set, we must run through everything exect CTFDUMP_OUTPUT.
788 * We also do CTFDUMP_STATS last as a result.
790 if (g_dump
& CTFDUMP_HEADER
)
793 if (g_dump
& (CTFDUMP_LABELS
| CTFDUMP_STATS
))
796 if (g_dump
& (CTFDUMP_OBJECTS
| CTFDUMP_STATS
))
799 if (g_dump
& (CTFDUMP_FUNCTIONS
| CTFDUMP_STATS
))
802 if (g_dump
& (CTFDUMP_TYPES
| CTFDUMP_STATS
))
805 if (g_dump
& (CTFDUMP_STRINGS
| CTFDUMP_STATS
))
808 if (g_dump
& CTFDUMP_STATS
)
811 if (g_dump
& CTFDUMP_OUTPUT
)
812 ctfdump_output(ufile
);