1 /* Textual dumping of CTF data.
2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
4 This file is part of libctf.
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
23 #define str_append(s, a) ctf_str_append_noerr (s, a)
25 /* One item to be dumped, in string form. */
27 typedef struct ctf_dump_item
33 /* Cross-call state for dumping. Basically just enough to track the section in
34 use and a list of return strings. */
38 ctf_sect_names_t cds_sect
;
40 ctf_dump_item_t
*cds_current
;
44 /* Cross-call state for ctf_dump_member. */
46 typedef struct ctf_dump_membstate
50 const char *cdm_toplevel_indent
;
51 } ctf_dump_membstate_t
;
54 ctf_dump_append (ctf_dump_state_t
*state
, char *str
)
58 if ((cdi
= malloc (sizeof (struct ctf_dump_item
))) == NULL
)
59 return (ctf_set_errno (state
->cds_fp
, ENOMEM
));
62 ctf_list_append (&state
->cds_items
, cdi
);
67 ctf_dump_free (ctf_dump_state_t
*state
)
69 ctf_dump_item_t
*cdi
, *next_cdi
;
74 for (cdi
= ctf_list_next (&state
->cds_items
); cdi
!= NULL
;
78 next_cdi
= ctf_list_next (cdi
);
83 /* Return a dump for a single type, without member info: but do optionally show
84 the type's references. */
86 #define CTF_FT_REFS 0x2 /* Print referenced types. */
87 #define CTF_FT_BITFIELD 0x4 /* Print :BITS if a bitfield. */
88 #define CTF_FT_ID 0x8 /* Print "ID: " in front of type IDs. */
91 ctf_dump_format_type (ctf_dict_t
*fp
, ctf_id_t id
, int flag
)
94 char *str
= NULL
, *bit
= NULL
, *buf
= NULL
;
96 ctf_set_errno (fp
, 0);
102 int kind
, unsliced_kind
;
103 const char *nonroot_leader
= "";
104 const char *nonroot_trailer
= "";
105 const char *idstr
= "";
108 if (flag
== CTF_ADD_NONROOT
)
110 nonroot_leader
= "{";
111 nonroot_trailer
= "}";
114 buf
= ctf_type_aname (fp
, id
);
117 if (id
== 0 || ctf_errno (fp
) == ECTF_NONREPRESENTABLE
)
119 ctf_set_errno (fp
, ECTF_NONREPRESENTABLE
);
120 str
= str_append (str
, " (type not represented in CTF)");
127 if (flag
& CTF_FT_ID
)
129 if (asprintf (&bit
, "%s%s0x%lx: (kind %i) ", nonroot_leader
, idstr
,
130 id
, ctf_type_kind (fp
, id
)) < 0)
132 str
= str_append (str
, bit
);
137 str
= str_append (str
, buf
);
142 unsliced_kind
= ctf_type_kind_unsliced (fp
, id
);
143 kind
= ctf_type_kind (fp
, id
);
145 /* Report encodings of everything with an encoding other than enums:
146 base-type enums cannot have a nonzero cte_offset or cte_bits value.
147 (Slices of them can, but they are of kind CTF_K_SLICE.) */
148 if (unsliced_kind
!= CTF_K_ENUM
&& ctf_type_encoding (fp
, id
, &ep
) == 0)
150 if ((ssize_t
) ep
.cte_bits
!= ctf_type_size (fp
, id
) * CHAR_BIT
151 && flag
& CTF_FT_BITFIELD
)
153 if (asprintf (&bit
, ":%i", ep
.cte_bits
) < 0)
155 str
= str_append (str
, bit
);
160 if ((ssize_t
) ep
.cte_bits
!= ctf_type_size (fp
, id
) * CHAR_BIT
161 || ep
.cte_offset
!= 0)
163 const char *slice
= "";
165 if (unsliced_kind
== CTF_K_SLICE
)
168 if (asprintf (&bit
, " [%s0x%x:0x%x]",
169 slice
, ep
.cte_offset
, ep
.cte_bits
) < 0)
171 str
= str_append (str
, bit
);
176 if (asprintf (&bit
, " (format 0x%x)", ep
.cte_format
) < 0)
178 str
= str_append (str
, bit
);
183 if (kind
!= CTF_K_FUNCTION
&& kind
!= CTF_K_FORWARD
)
185 if (asprintf (&bit
, " (size 0x%lx)",
186 (unsigned long) ctf_type_size (fp
, id
)) < 0)
189 str
= str_append (str
, bit
);
194 if (kind
!= CTF_K_FORWARD
)
196 if (asprintf (&bit
, " (aligned at 0x%lx)",
197 (unsigned long) ctf_type_align (fp
, id
)) < 0)
200 str
= str_append (str
, bit
);
205 if (nonroot_trailer
[0] != 0)
206 str
= str_append (str
, nonroot_trailer
);
208 /* Just exit after one iteration if we are not showing the types this type
210 if (!(flag
& CTF_FT_REFS
))
213 /* Keep going as long as this type references another. We consider arrays
214 to "reference" their element type. */
216 if (kind
== CTF_K_ARRAY
)
218 if (ctf_array_info (fp
, id
, &ar
) < 0)
220 new_id
= ar
.ctr_contents
;
223 new_id
= ctf_type_reference (fp
, id
);
224 if (new_id
!= CTF_ERR
)
225 str
= str_append (str
, " -> ");
227 while (new_id
!= CTF_ERR
);
229 if (ctf_errno (fp
) != ECTF_NOTREF
)
238 ctf_set_errno (fp
, errno
);
240 ctf_err_warn (fp
, 1, 0, _("cannot format name dumping type 0x%lx"), id
);
247 /* Dump one string field from the file header into the cds_items. */
249 ctf_dump_header_strfield (ctf_dict_t
*fp
, ctf_dump_state_t
*state
,
250 const char *name
, uint32_t value
)
255 if (asprintf (&str
, "%s: %s\n", name
, ctf_strptr (fp
, value
)) < 0)
257 ctf_dump_append (state
, str
);
262 return (ctf_set_errno (fp
, errno
));
265 /* Dump one section-offset field from the file header into the cds_items. */
267 ctf_dump_header_sectfield (ctf_dict_t
*fp
, ctf_dump_state_t
*state
,
268 const char *sect
, uint32_t off
, uint32_t nextoff
)
273 if (asprintf (&str
, "%s:\t0x%lx -- 0x%lx (0x%lx bytes)\n", sect
,
274 (unsigned long) off
, (unsigned long) (nextoff
- 1),
275 (unsigned long) (nextoff
- off
)) < 0)
277 ctf_dump_append (state
, str
);
282 return (ctf_set_errno (fp
, errno
));
285 /* Dump the file header into the cds_items. */
287 ctf_dump_header (ctf_dict_t
*fp
, ctf_dump_state_t
*state
)
290 char *flagstr
= NULL
;
291 const ctf_header_t
*hp
= fp
->ctf_header
;
292 const char *vertab
[] =
294 NULL
, "CTF_VERSION_1",
295 "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
298 "CTF_VERSION_3", NULL
300 const char *verstr
= NULL
;
302 if (asprintf (&str
, "Magic number: 0x%x\n", hp
->cth_magic
) < 0)
304 ctf_dump_append (state
, str
);
306 if (hp
->cth_version
<= CTF_VERSION
)
307 verstr
= vertab
[hp
->cth_version
];
310 verstr
= "(not a valid version)";
312 if (asprintf (&str
, "Version: %i (%s)\n", hp
->cth_version
,
315 ctf_dump_append (state
, str
);
317 /* Everything else is only printed if present. */
319 /* The flags are unusual in that they represent the ctf_dict_t *in memory*:
320 flags representing compression, etc, are turned off as the file is
321 decompressed. So we store a copy of the flags before they are changed, for
324 if (fp
->ctf_openflags
> 0)
326 if (asprintf (&flagstr
, "%s%s%s%s%s%s%s",
327 fp
->ctf_openflags
& CTF_F_COMPRESS
328 ? "CTF_F_COMPRESS": "",
329 (fp
->ctf_openflags
& CTF_F_COMPRESS
)
330 && (fp
->ctf_openflags
& ~CTF_F_COMPRESS
)
332 fp
->ctf_openflags
& CTF_F_NEWFUNCINFO
333 ? "CTF_F_NEWFUNCINFO" : "",
334 (fp
->ctf_openflags
& (CTF_F_COMPRESS
| CTF_F_NEWFUNCINFO
))
335 && (fp
->ctf_openflags
& ~(CTF_F_COMPRESS
| CTF_F_NEWFUNCINFO
))
337 fp
->ctf_openflags
& CTF_F_IDXSORTED
338 ? "CTF_F_IDXSORTED" : "",
339 fp
->ctf_openflags
& (CTF_F_COMPRESS
| CTF_F_NEWFUNCINFO
341 && (fp
->ctf_openflags
& ~(CTF_F_COMPRESS
| CTF_F_NEWFUNCINFO
344 fp
->ctf_openflags
& CTF_F_DYNSTR
345 ? "CTF_F_DYNSTR" : "") < 0)
348 if (asprintf (&str
, "Flags: 0x%x (%s)", fp
->ctf_openflags
, flagstr
) < 0)
350 ctf_dump_append (state
, str
);
353 if (ctf_dump_header_strfield (fp
, state
, "Parent label",
354 hp
->cth_parlabel
) < 0)
357 if (ctf_dump_header_strfield (fp
, state
, "Parent name", hp
->cth_parname
) < 0)
360 if (ctf_dump_header_strfield (fp
, state
, "Compilation unit name",
364 if (ctf_dump_header_sectfield (fp
, state
, "Label section", hp
->cth_lbloff
,
365 hp
->cth_objtoff
) < 0)
368 if (ctf_dump_header_sectfield (fp
, state
, "Data object section",
369 hp
->cth_objtoff
, hp
->cth_funcoff
) < 0)
372 if (ctf_dump_header_sectfield (fp
, state
, "Function info section",
373 hp
->cth_funcoff
, hp
->cth_objtidxoff
) < 0)
376 if (ctf_dump_header_sectfield (fp
, state
, "Object index section",
377 hp
->cth_objtidxoff
, hp
->cth_funcidxoff
) < 0)
380 if (ctf_dump_header_sectfield (fp
, state
, "Function index section",
381 hp
->cth_funcidxoff
, hp
->cth_varoff
) < 0)
384 if (ctf_dump_header_sectfield (fp
, state
, "Variable section",
385 hp
->cth_varoff
, hp
->cth_typeoff
) < 0)
388 if (ctf_dump_header_sectfield (fp
, state
, "Type section",
389 hp
->cth_typeoff
, hp
->cth_stroff
) < 0)
392 if (ctf_dump_header_sectfield (fp
, state
, "String section", hp
->cth_stroff
,
393 hp
->cth_stroff
+ hp
->cth_strlen
+ 1) < 0)
399 return (ctf_set_errno (fp
, errno
));
402 /* Dump a single label into the cds_items. */
405 ctf_dump_label (const char *name
, const ctf_lblinfo_t
*info
,
410 ctf_dump_state_t
*state
= arg
;
412 if (asprintf (&str
, "%s -> ", name
) < 0)
413 return (ctf_set_errno (state
->cds_fp
, errno
));
415 if ((typestr
= ctf_dump_format_type (state
->cds_fp
, info
->ctb_type
,
416 CTF_ADD_ROOT
| CTF_FT_REFS
)) == NULL
)
419 return 0; /* Swallow the error. */
422 str
= str_append (str
, typestr
);
425 ctf_dump_append (state
, str
);
429 /* Dump all the object or function entries into the cds_items. */
432 ctf_dump_objts (ctf_dict_t
*fp
, ctf_dump_state_t
*state
, int functions
)
436 ctf_next_t
*i
= NULL
;
439 if ((functions
&& fp
->ctf_funcidx_names
)
440 || (!functions
&& fp
->ctf_objtidx_names
))
441 str
= str_append (str
, _("Section is indexed.\n"));
442 else if (fp
->ctf_symtab
.cts_data
== NULL
)
443 str
= str_append (str
, _("No symbol table.\n"));
445 while ((id
= ctf_symbol_next (fp
, &i
, &name
, functions
)) != CTF_ERR
)
447 char *typestr
= NULL
;
449 /* Emit the name, if we know it. No trailing space: ctf_dump_format_type
450 has a leading one. */
453 if (asprintf (&str
, "%s -> ", name
) < 0)
459 if ((typestr
= ctf_dump_format_type (state
->cds_fp
, id
,
460 CTF_ADD_ROOT
| CTF_FT_REFS
)) == NULL
)
462 ctf_dump_append (state
, str
);
463 continue; /* Swallow the error. */
466 str
= str_append (str
, typestr
);
468 ctf_dump_append (state
, str
);
472 ctf_set_errno (fp
, ENOMEM
);
473 ctf_next_destroy (i
);
479 /* Dump a single variable into the cds_items. */
481 ctf_dump_var (const char *name
, ctf_id_t type
, void *arg
)
485 ctf_dump_state_t
*state
= arg
;
487 if (asprintf (&str
, "%s -> ", name
) < 0)
488 return (ctf_set_errno (state
->cds_fp
, errno
));
490 if ((typestr
= ctf_dump_format_type (state
->cds_fp
, type
,
491 CTF_ADD_ROOT
| CTF_FT_REFS
)) == NULL
)
494 return 0; /* Swallow the error. */
497 str
= str_append (str
, typestr
);
500 ctf_dump_append (state
, str
);
504 /* Dump a single struct/union member into the string in the membstate. */
506 ctf_dump_member (const char *name
, ctf_id_t id
, unsigned long offset
,
507 int depth
, void *arg
)
509 ctf_dump_membstate_t
*state
= arg
;
510 char *typestr
= NULL
;
513 /* The struct/union itself has already been printed. */
517 if (asprintf (&bit
, "%s%*s", state
->cdm_toplevel_indent
, (depth
-1)*4, "") < 0)
519 *state
->cdm_str
= str_append (*state
->cdm_str
, bit
);
522 if ((typestr
= ctf_dump_format_type (state
->cdm_fp
, id
,
523 CTF_ADD_ROOT
| CTF_FT_BITFIELD
524 | CTF_FT_ID
)) == NULL
)
525 return -1; /* errno is set for us. */
527 if (asprintf (&bit
, "[0x%lx] %s: %s\n", offset
, name
, typestr
) < 0)
530 *state
->cdm_str
= str_append (*state
->cdm_str
, bit
);
541 return (ctf_set_errno (state
->cdm_fp
, errno
));
544 /* Report the number of digits in the hexadecimal representation of a type
548 type_hex_digits (ctf_id_t id
)
555 for (; id
> 0; id
>>= 4, i
++);
559 /* Dump a single type into the cds_items. */
561 ctf_dump_type (ctf_id_t id
, int flag
, void *arg
)
566 ctf_dump_state_t
*state
= arg
;
567 ctf_dump_membstate_t membstate
= { &str
, state
->cds_fp
, NULL
};
570 if (asprintf (&indent
, " %*s", type_hex_digits (id
), "") < 0)
571 return (ctf_set_errno (state
->cds_fp
, ENOMEM
));
573 /* Dump the type itself. */
574 if ((str
= ctf_dump_format_type (state
->cds_fp
, id
,
575 flag
| CTF_FT_REFS
)) == NULL
)
577 str
= str_append (str
, "\n");
579 membstate
.cdm_toplevel_indent
= indent
;
581 /* Member dumping for structs, unions... */
582 if (ctf_type_kind (state
->cds_fp
, id
) == CTF_K_STRUCT
583 || ctf_type_kind (state
->cds_fp
, id
) == CTF_K_UNION
)
585 if ((ctf_type_visit (state
->cds_fp
, id
, ctf_dump_member
, &membstate
)) < 0)
587 if (id
== 0 || ctf_errno (state
->cds_fp
) == ECTF_NONREPRESENTABLE
)
589 ctf_dump_append (state
, str
);
592 ctf_err_warn (state
->cds_fp
, 1, ctf_errno (state
->cds_fp
),
593 _("cannot visit members dumping type 0x%lx"), id
);
598 /* ... and enums, for which we dump the first and last few members and skip
599 the ones in the middle. */
600 if (ctf_type_kind (state
->cds_fp
, id
) == CTF_K_ENUM
)
602 int enum_count
= ctf_member_count (state
->cds_fp
, id
);
603 ctf_next_t
*it
= NULL
;
605 const char *enumerand
;
609 while ((enumerand
= ctf_enum_next (state
->cds_fp
, id
,
610 &it
, &value
)) != NULL
)
613 if ((i
> 5) && (i
< enum_count
- 4))
616 str
= str_append (str
, indent
);
618 if (asprintf (&bit
, "%s: %i\n", enumerand
, value
) < 0)
621 ctf_next_destroy (it
);
624 str
= str_append (str
, bit
);
627 if ((i
== 5) && (enum_count
> 10))
629 str
= str_append (str
, indent
);
630 str
= str_append (str
, "...\n");
633 if (ctf_errno (state
->cds_fp
) != ECTF_NEXT_END
)
635 ctf_err_warn (state
->cds_fp
, 1, ctf_errno (state
->cds_fp
),
636 _("cannot visit enumerands dumping type 0x%lx"), id
);
641 ctf_dump_append (state
, str
);
649 return ctf_set_errno (state
->cds_fp
, err
);
652 /* Dump the string table into the cds_items. */
655 ctf_dump_str (ctf_dict_t
*fp
, ctf_dump_state_t
*state
)
657 const char *s
= fp
->ctf_str
[CTF_STRTAB_0
].cts_strs
;
659 for (; s
< fp
->ctf_str
[CTF_STRTAB_0
].cts_strs
+
660 fp
->ctf_str
[CTF_STRTAB_0
].cts_len
;)
663 if (asprintf (&str
, "0x%lx: %s",
664 (unsigned long) (s
- fp
->ctf_str
[CTF_STRTAB_0
].cts_strs
),
666 return (ctf_set_errno (fp
, errno
));
667 ctf_dump_append (state
, str
);
674 /* Dump a particular section of a CTF file, in textual form. Call with a
675 pointer to a NULL STATE: each call emits a dynamically allocated string
676 containing a description of one entity in the specified section, in order.
677 Only the first call (with a NULL state) may vary SECT. Once the CTF section
678 has been entirely dumped, the call returns NULL and frees and annuls the
679 STATE, ready for another section to be dumped. The returned textual content
680 may span multiple lines: between each call the FUNC is called with one
681 textual line at a time, and should return a suitably decorated line (it can
682 allocate a new one and return it if it likes). */
685 ctf_dump (ctf_dict_t
*fp
, ctf_dump_state_t
**statep
, ctf_sect_names_t sect
,
686 ctf_dump_decorate_f
*func
, void *arg
)
690 ctf_dump_state_t
*state
= NULL
;
694 /* Data collection. Transforming a call-at-a-time iterator into a
695 return-at-a-time iterator in a language without call/cc is annoying. It
696 is easiest to simply collect everything at once and then return it bit
697 by bit. The first call will take (much) longer than otherwise, but the
698 amortized time needed is the same. */
700 if ((*statep
= malloc (sizeof (struct ctf_dump_state
))) == NULL
)
702 ctf_set_errno (fp
, ENOMEM
);
707 memset (state
, 0, sizeof (struct ctf_dump_state
));
709 state
->cds_sect
= sect
;
713 case CTF_SECT_HEADER
:
714 ctf_dump_header (fp
, state
);
717 if (ctf_label_iter (fp
, ctf_dump_label
, state
) < 0)
719 if (ctf_errno (fp
) != ECTF_NOLABELDATA
)
720 goto end
; /* errno is set for us. */
721 ctf_set_errno (fp
, 0);
725 if (ctf_dump_objts (fp
, state
, 0) < 0)
726 goto end
; /* errno is set for us. */
729 if (ctf_dump_objts (fp
, state
, 1) < 0)
730 goto end
; /* errno is set for us. */
733 if (ctf_variable_iter (fp
, ctf_dump_var
, state
) < 0)
734 goto end
; /* errno is set for us. */
737 if (ctf_type_iter_all (fp
, ctf_dump_type
, state
) < 0)
738 goto end
; /* errno is set for us. */
741 ctf_dump_str (fp
, state
);
744 ctf_set_errno (fp
, ECTF_DUMPSECTUNKNOWN
);
752 if (state
->cds_sect
!= sect
)
754 ctf_set_errno (fp
, ECTF_DUMPSECTCHANGED
);
759 if (state
->cds_current
== NULL
)
760 state
->cds_current
= ctf_list_next (&state
->cds_items
);
762 state
->cds_current
= ctf_list_next (state
->cds_current
);
764 if (state
->cds_current
== NULL
)
767 /* Hookery. There is some extra complexity to preserve linefeeds within each
768 item while removing linefeeds at the end. */
774 for (line
= state
->cds_current
->cdi_item
; line
&& *line
; )
779 nline
= strchr (line
, '\n');
783 ret
= func (sect
, line
, arg
);
784 str
= str_append (str
, ret
);
785 str
= str_append (str
, "\n");
800 if (str
[len
-1] == '\n')
805 str
= strdup (state
->cds_current
->cdi_item
);
808 ctf_set_errno (fp
, ENOMEM
);
813 ctf_set_errno (fp
, 0);
817 ctf_dump_free (state
);
819 ctf_set_errno (fp
, 0);