1 /* Textual dumping of CTF data.
2 Copyright (C) 2019-2020 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 } ctf_dump_membstate_t
;
53 ctf_dump_append (ctf_dump_state_t
*state
, char *str
)
57 if ((cdi
= malloc (sizeof (struct ctf_dump_item
))) == NULL
)
58 return (ctf_set_errno (state
->cds_fp
, ENOMEM
));
61 ctf_list_append (&state
->cds_items
, cdi
);
66 ctf_dump_free (ctf_dump_state_t
*state
)
68 ctf_dump_item_t
*cdi
, *next_cdi
;
73 for (cdi
= ctf_list_next (&state
->cds_items
); cdi
!= NULL
;
77 next_cdi
= ctf_list_next (cdi
);
82 /* Slices need special handling to distinguish them from their referenced
86 ctf_is_slice (ctf_file_t
*fp
, ctf_id_t id
, ctf_encoding_t
*enc
)
88 int kind
= ctf_type_kind (fp
, id
);
90 return (((kind
== CTF_K_INTEGER
) || (kind
== CTF_K_ENUM
)
91 || (kind
== CTF_K_FLOAT
))
92 && ctf_type_reference (fp
, id
) != CTF_ERR
93 && ctf_type_encoding (fp
, id
, enc
) == 0);
96 /* Return a dump for a single type, without member info: but do show the
100 ctf_dump_format_type (ctf_file_t
*fp
, ctf_id_t id
, int flag
)
103 char *str
= NULL
, *bit
= NULL
, *buf
= NULL
;
109 const char *nonroot_leader
= "";
110 const char *nonroot_trailer
= "";
113 if (flag
== CTF_ADD_NONROOT
)
115 nonroot_leader
= "{";
116 nonroot_trailer
= "}";
119 buf
= ctf_type_aname (fp
, id
);
122 if (id
== 0 || ctf_errno (fp
) == ECTF_NONREPRESENTABLE
)
124 str
= str_append (str
, " (type not represented in CTF)");
125 ctf_set_errno (fp
, ECTF_NOTREF
);
132 /* Slices get a different print representation. */
134 if (ctf_is_slice (fp
, id
, &enc
))
136 ctf_type_encoding (fp
, id
, &enc
);
137 if (asprintf (&bit
, " %s%lx: [slice 0x%x:0x%x]%s",
138 nonroot_leader
, id
, enc
.cte_offset
, enc
.cte_bits
,
139 nonroot_trailer
) < 0)
144 if (asprintf (&bit
, " %s%lx: %s (size 0x%lx)%s", nonroot_leader
,
145 id
, buf
[0] == '\0' ? "(nameless)" : buf
,
146 (unsigned long) ctf_type_size (fp
, id
),
147 nonroot_trailer
) < 0)
152 str
= str_append (str
, bit
);
156 new_id
= ctf_type_reference (fp
, id
);
157 if (new_id
!= CTF_ERR
)
158 str
= str_append (str
, " ->");
159 } while (new_id
!= CTF_ERR
);
161 if (ctf_errno (fp
) != ECTF_NOTREF
)
170 ctf_set_errno (fp
, errno
);
172 ctf_err_warn (fp
, 1, "Cannot format name dumping type 0x%lx: %s", id
,
173 ctf_errmsg (ctf_errno (fp
)));
180 /* Dump one string field from the file header into the cds_items. */
182 ctf_dump_header_strfield (ctf_file_t
*fp
, ctf_dump_state_t
*state
,
183 const char *name
, uint32_t value
)
188 if (asprintf (&str
, "%s: %s\n", name
, ctf_strptr (fp
, value
)) < 0)
190 ctf_dump_append (state
, str
);
195 return (ctf_set_errno (fp
, errno
));
198 /* Dump one section-offset field from the file header into the cds_items. */
200 ctf_dump_header_sectfield (ctf_file_t
*fp
, ctf_dump_state_t
*state
,
201 const char *sect
, uint32_t off
, uint32_t nextoff
)
206 if (asprintf (&str
, "%s:\t0x%lx -- 0x%lx (0x%lx bytes)\n", sect
,
207 (unsigned long) off
, (unsigned long) (nextoff
- 1),
208 (unsigned long) (nextoff
- off
)) < 0)
210 ctf_dump_append (state
, str
);
215 return (ctf_set_errno (fp
, errno
));
218 /* Dump the file header into the cds_items. */
220 ctf_dump_header (ctf_file_t
*fp
, ctf_dump_state_t
*state
)
223 const ctf_header_t
*hp
= fp
->ctf_header
;
224 const char *vertab
[] =
226 NULL
, "CTF_VERSION_1",
227 "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
230 "CTF_VERSION_3", NULL
232 const char *verstr
= NULL
;
234 if (asprintf (&str
, "Magic number: %x\n", hp
->cth_magic
) < 0)
236 ctf_dump_append (state
, str
);
238 if (hp
->cth_version
<= CTF_VERSION
)
239 verstr
= vertab
[hp
->cth_version
];
242 verstr
= "(not a valid version)";
244 if (asprintf (&str
, "Version: %i (%s)\n", hp
->cth_version
,
247 ctf_dump_append (state
, str
);
249 /* Everything else is only printed if present. */
251 /* The flags are unusual in that they represent the ctf_file_t *in memory*:
252 flags representing compression, etc, are turned off as the file is
253 decompressed. So we store a copy of the flags before they are changed, for
256 if (fp
->ctf_openflags
> 0)
258 if (fp
->ctf_openflags
)
259 if (asprintf (&str
, "Flags: 0x%x (%s)", fp
->ctf_openflags
,
260 fp
->ctf_openflags
& CTF_F_COMPRESS
? "CTF_F_COMPRESS"
263 ctf_dump_append (state
, str
);
266 if (ctf_dump_header_strfield (fp
, state
, "Parent label",
267 hp
->cth_parlabel
) < 0)
270 if (ctf_dump_header_strfield (fp
, state
, "Parent name", hp
->cth_parname
) < 0)
273 if (ctf_dump_header_strfield (fp
, state
, "Compilation unit name",
277 if (ctf_dump_header_sectfield (fp
, state
, "Label section", hp
->cth_lbloff
,
278 hp
->cth_objtoff
) < 0)
281 if (ctf_dump_header_sectfield (fp
, state
, "Data object section",
282 hp
->cth_objtoff
, hp
->cth_funcoff
) < 0)
285 if (ctf_dump_header_sectfield (fp
, state
, "Function info section",
286 hp
->cth_funcoff
, hp
->cth_varoff
) < 0)
289 if (ctf_dump_header_sectfield (fp
, state
, "Variable section",
290 hp
->cth_varoff
, hp
->cth_typeoff
) < 0)
293 if (ctf_dump_header_sectfield (fp
, state
, "Type section",
294 hp
->cth_typeoff
, hp
->cth_stroff
) < 0)
297 if (ctf_dump_header_sectfield (fp
, state
, "String section", hp
->cth_stroff
,
298 hp
->cth_stroff
+ hp
->cth_strlen
+ 1) < 0)
303 return (ctf_set_errno (fp
, errno
));
306 /* Dump a single label into the cds_items. */
309 ctf_dump_label (const char *name
, const ctf_lblinfo_t
*info
,
314 ctf_dump_state_t
*state
= arg
;
316 if (asprintf (&str
, "%s -> ", name
) < 0)
317 return (ctf_set_errno (state
->cds_fp
, errno
));
319 if ((typestr
= ctf_dump_format_type (state
->cds_fp
, info
->ctb_type
,
320 CTF_ADD_ROOT
)) == NULL
)
323 return 0; /* Swallow the error. */
326 str
= str_append (str
, typestr
);
329 ctf_dump_append (state
, str
);
333 /* Dump all the object entries into the cds_items. (There is no iterator for
334 this section, so we just do it in a loop, and this function handles all of
335 them, rather than only one. */
338 ctf_dump_objts (ctf_file_t
*fp
, ctf_dump_state_t
*state
)
342 for (i
= 0; i
< fp
->ctf_nsyms
; i
++)
346 const char *sym_name
;
349 if ((type
= ctf_lookup_by_symbol (state
->cds_fp
, i
)) == CTF_ERR
)
350 switch (ctf_errno (state
->cds_fp
))
352 /* Most errors are just an indication that this symbol is not a data
353 symbol, but this one indicates that we were called wrong, on a
354 CTF file with no associated symbol table. */
363 sym_name
= ctf_lookup_symbol_name (fp
, i
);
364 if (sym_name
[0] == '\0')
366 if (asprintf (&str
, "%lx -> ", (unsigned long) i
) < 0)
367 return (ctf_set_errno (fp
, errno
));
371 if (asprintf (&str
, "%s (%lx) -> ", sym_name
, (unsigned long) i
) < 0)
372 return (ctf_set_errno (fp
, errno
));
376 if ((typestr
= ctf_dump_format_type (state
->cds_fp
, type
,
377 CTF_ADD_ROOT
)) == NULL
)
380 return 0; /* Swallow the error. */
383 str
= str_append (str
, typestr
);
386 ctf_dump_append (state
, str
);
391 /* Dump all the function entries into the cds_items. (As above, there is no
392 iterator for this section.) */
395 ctf_dump_funcs (ctf_file_t
*fp
, ctf_dump_state_t
*state
)
399 for (i
= 0; i
< fp
->ctf_nsyms
; i
++)
404 const char *sym_name
;
408 if ((type
= ctf_func_info (state
->cds_fp
, i
, &fi
)) == CTF_ERR
)
409 switch (ctf_errno (state
->cds_fp
))
411 /* Most errors are just an indication that this symbol is not a data
412 symbol, but this one indicates that we were called wrong, on a
413 CTF file with no associated symbol table. */
422 /* Return type and all args. */
423 if ((bit
= ctf_type_aname (state
->cds_fp
, type
)) == NULL
)
425 err
= "look up return type";
429 /* Replace in the returned string, dropping in the function name. */
431 sym_name
= ctf_lookup_symbol_name (fp
, i
);
432 if (sym_name
[0] != '\0')
438 new_bit
= malloc (strlen (bit
) + 1 + strlen (sym_name
));
442 /* See ctf_type_aname. */
443 retstar
= strstr (bit
, "(*) (");
444 if (!ctf_assert (fp
, retstar
))
446 retstar
+= 2; /* After the '*' */
448 /* C is not good at search-and-replace. */
450 memcpy (walk
, bit
, retstar
- bit
);
451 walk
+= (retstar
- bit
);
452 strcpy (walk
, sym_name
);
453 walk
+= strlen (sym_name
);
454 strcpy (walk
, retstar
);
460 if (asprintf (&str
, "Symbol 0x%lx: %s", (unsigned long) i
, bit
) < 0)
464 ctf_dump_append (state
, str
);
468 ctf_err_warn (fp
, 1, "Cannot %s dumping function type for "
469 "symbol 0x%li: %s", err
, (unsigned long) i
,
470 ctf_errmsg (ctf_errno (state
->cds_fp
)));
472 return -1; /* errno is set for us. */
476 return (ctf_set_errno (fp
, errno
));
480 return -1; /* errno is set for us. */
485 /* Dump a single variable into the cds_items. */
487 ctf_dump_var (const char *name
, ctf_id_t type
, void *arg
)
491 ctf_dump_state_t
*state
= arg
;
493 if (asprintf (&str
, "%s -> ", name
) < 0)
494 return (ctf_set_errno (state
->cds_fp
, errno
));
496 if ((typestr
= ctf_dump_format_type (state
->cds_fp
, type
,
497 CTF_ADD_ROOT
)) == NULL
)
500 return 0; /* Swallow the error. */
503 str
= str_append (str
, typestr
);
506 ctf_dump_append (state
, str
);
510 /* Dump a single member into the string in the membstate. */
512 ctf_dump_member (const char *name
, ctf_id_t id
, unsigned long offset
,
513 int depth
, void *arg
)
515 ctf_dump_membstate_t
*state
= arg
;
516 char *typestr
= NULL
;
521 for (i
= 0; i
< depth
; i
++)
522 *state
->cdm_str
= str_append (*state
->cdm_str
, " ");
524 if ((typestr
= ctf_type_aname (state
->cdm_fp
, id
)) == NULL
)
526 if (id
== 0 || ctf_errno (state
->cdm_fp
) == ECTF_NONREPRESENTABLE
)
528 if (asprintf (&bit
, " [0x%lx] (type not represented in CTF)",
532 *state
->cdm_str
= str_append (*state
->cdm_str
, bit
);
541 if (asprintf (&bit
, " [0x%lx] (ID 0x%lx) (kind %i) %s %s (aligned at 0x%lx",
542 offset
, id
, ctf_type_kind (state
->cdm_fp
, id
), typestr
, name
,
543 (unsigned long) ctf_type_align (state
->cdm_fp
, id
)) < 0)
545 *state
->cdm_str
= str_append (*state
->cdm_str
, bit
);
551 if ((ctf_type_kind (state
->cdm_fp
, id
) == CTF_K_INTEGER
)
552 || (ctf_type_kind (state
->cdm_fp
, id
) == CTF_K_FLOAT
)
553 || (ctf_is_slice (state
->cdm_fp
, id
, &ep
) == CTF_K_ENUM
))
555 ctf_type_encoding (state
->cdm_fp
, id
, &ep
);
556 if (asprintf (&bit
, ", format 0x%x, offset:bits 0x%x:0x%x", ep
.cte_format
,
557 ep
.cte_offset
, ep
.cte_bits
) < 0)
559 *state
->cdm_str
= str_append (*state
->cdm_str
, bit
);
564 *state
->cdm_str
= str_append (*state
->cdm_str
, ")\n");
570 return (ctf_set_errno (state
->cdm_fp
, errno
));
573 /* Dump a single type into the cds_items. */
575 ctf_dump_type (ctf_id_t id
, int flag
, void *arg
)
579 ctf_dump_state_t
*state
= arg
;
580 ctf_dump_membstate_t membstate
= { &str
, state
->cds_fp
};
583 if ((str
= ctf_dump_format_type (state
->cds_fp
, id
, flag
)) == NULL
)
584 goto err_nomsg
; /* Error already logged for us. */
586 str
= str_append (str
, "\n");
587 if ((ctf_type_visit (state
->cds_fp
, id
, ctf_dump_member
, &membstate
)) < 0)
589 if (id
== 0 || ctf_errno (state
->cds_fp
) == ECTF_NONREPRESENTABLE
)
591 ctf_dump_append (state
, str
);
594 err
= "visit members";
598 /* Trim off the last linefeed added by ctf_dump_member(). */
600 if (str
[len
-1] == '\n')
603 ctf_dump_append (state
, str
);
607 ctf_err_warn (state
->cds_fp
, 1, "Cannot %s dumping type 0x%lx: %s",
608 err
, id
, ctf_errmsg (ctf_errno (state
->cds_fp
)));
611 return 0; /* Swallow the error. */
614 /* Dump the string table into the cds_items. */
617 ctf_dump_str (ctf_file_t
*fp
, ctf_dump_state_t
*state
)
619 const char *s
= fp
->ctf_str
[CTF_STRTAB_0
].cts_strs
;
621 for (; s
< fp
->ctf_str
[CTF_STRTAB_0
].cts_strs
+
622 fp
->ctf_str
[CTF_STRTAB_0
].cts_len
;)
625 if (asprintf (&str
, "%lx: %s",
626 (unsigned long) (s
- fp
->ctf_str
[CTF_STRTAB_0
].cts_strs
),
628 return (ctf_set_errno (fp
, errno
));
629 ctf_dump_append (state
, str
);
636 /* Dump a particular section of a CTF file, in textual form. Call with a
637 pointer to a NULL STATE: each call emits a dynamically allocated string
638 containing a description of one entity in the specified section, in order.
639 Only the first call (with a NULL state) may vary SECT. Once the CTF section
640 has been entirely dumped, the call returns NULL and frees and annuls the
641 STATE, ready for another section to be dumped. The returned textual content
642 may span multiple lines: between each call the FUNC is called with one
643 textual line at a time, and should return a suitably decorated line (it can
644 allocate a new one and return it if it likes). */
647 ctf_dump (ctf_file_t
*fp
, ctf_dump_state_t
**statep
, ctf_sect_names_t sect
,
648 ctf_dump_decorate_f
*func
, void *arg
)
652 ctf_dump_state_t
*state
= NULL
;
656 /* Data collection. Transforming a call-at-a-time iterator into a
657 return-at-a-time iterator in a language without call/cc is annoying. It
658 is easiest to simply collect everything at once and then return it bit
659 by bit. The first call will take (much) longer than otherwise, but the
660 amortized time needed is the same. */
662 if ((*statep
= malloc (sizeof (struct ctf_dump_state
))) == NULL
)
664 ctf_set_errno (fp
, ENOMEM
);
669 memset (state
, 0, sizeof (struct ctf_dump_state
));
671 state
->cds_sect
= sect
;
675 case CTF_SECT_HEADER
:
676 ctf_dump_header (fp
, state
);
679 if (ctf_label_iter (fp
, ctf_dump_label
, state
) < 0)
681 if (ctf_errno (fp
) != ECTF_NOLABELDATA
)
682 goto end
; /* errno is set for us. */
683 ctf_set_errno (fp
, 0);
687 if (ctf_dump_objts (fp
, state
) < 0)
688 goto end
; /* errno is set for us. */
691 if (ctf_dump_funcs (fp
, state
) < 0)
692 goto end
; /* errno is set for us. */
695 if (ctf_variable_iter (fp
, ctf_dump_var
, state
) < 0)
696 goto end
; /* errno is set for us. */
699 if (ctf_type_iter_all (fp
, ctf_dump_type
, state
) < 0)
700 goto end
; /* errno is set for us. */
703 ctf_dump_str (fp
, state
);
706 ctf_set_errno (fp
, ECTF_DUMPSECTUNKNOWN
);
714 if (state
->cds_sect
!= sect
)
716 ctf_set_errno (fp
, ECTF_DUMPSECTCHANGED
);
721 if (state
->cds_current
== NULL
)
722 state
->cds_current
= ctf_list_next (&state
->cds_items
);
724 state
->cds_current
= ctf_list_next (state
->cds_current
);
726 if (state
->cds_current
== NULL
)
729 /* Hookery. There is some extra complexity to preserve linefeeds within each
730 item while removing linefeeds at the end. */
736 for (line
= state
->cds_current
->cdi_item
; line
&& *line
; )
741 nline
= strchr (line
, '\n');
745 ret
= func (sect
, line
, arg
);
746 str
= str_append (str
, ret
);
747 str
= str_append (str
, "\n");
762 if (str
[len
-1] == '\n')
767 str
= strdup (state
->cds_current
->cdi_item
);
770 ctf_set_errno (fp
, ENOMEM
);
775 ctf_set_errno (fp
, 0);
779 ctf_dump_free (state
);
781 ctf_set_errno (fp
, 0);