]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - libctf/ctf-dump.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / libctf / ctf-dump.c
CommitLineData
a30b3e18 1/* Textual dumping of CTF data.
250d07de 2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
a30b3e18
NA
3
4 This file is part of libctf.
5
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
9 version.
10
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.
15
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/>. */
19
20#include <ctf-impl.h>
21#include <string.h>
22
9323dd86
NA
23#define str_append(s, a) ctf_str_append_noerr (s, a)
24
a30b3e18
NA
25/* One item to be dumped, in string form. */
26
27typedef struct ctf_dump_item
28{
29 ctf_list_t cdi_list;
30 char *cdi_item;
31} ctf_dump_item_t;
32
33/* Cross-call state for dumping. Basically just enough to track the section in
34 use and a list of return strings. */
35
36struct ctf_dump_state
37{
38 ctf_sect_names_t cds_sect;
139633c3 39 ctf_dict_t *cds_fp;
a30b3e18
NA
40 ctf_dump_item_t *cds_current;
41 ctf_list_t cds_items;
42};
43
44/* Cross-call state for ctf_dump_member. */
45
46typedef struct ctf_dump_membstate
47{
48 char **cdm_str;
139633c3 49 ctf_dict_t *cdm_fp;
a30b3e18
NA
50} ctf_dump_membstate_t;
51
52static int
53ctf_dump_append (ctf_dump_state_t *state, char *str)
54{
55 ctf_dump_item_t *cdi;
56
de07e349 57 if ((cdi = malloc (sizeof (struct ctf_dump_item))) == NULL)
a30b3e18
NA
58 return (ctf_set_errno (state->cds_fp, ENOMEM));
59
60 cdi->cdi_item = str;
61 ctf_list_append (&state->cds_items, cdi);
62 return 0;
63}
64
65static void
66ctf_dump_free (ctf_dump_state_t *state)
67{
68 ctf_dump_item_t *cdi, *next_cdi;
69
70 if (state == NULL)
71 return;
72
73 for (cdi = ctf_list_next (&state->cds_items); cdi != NULL;
74 cdi = next_cdi)
75 {
76 free (cdi->cdi_item);
77 next_cdi = ctf_list_next (cdi);
de07e349 78 free (cdi);
a30b3e18
NA
79 }
80}
81
a30b3e18
NA
82/* Return a dump for a single type, without member info: but do show the
83 type's references. */
84
85static char *
139633c3 86ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag)
a30b3e18
NA
87{
88 ctf_id_t new_id;
89 char *str = NULL, *bit = NULL, *buf = NULL;
90
91 new_id = id;
92 do
93 {
94 ctf_encoding_t enc;
b4f0e09c
NA
95 const char *nonroot_leader = "";
96 const char *nonroot_trailer = "";
a30b3e18
NA
97
98 id = new_id;
b4f0e09c
NA
99 if (flag == CTF_ADD_NONROOT)
100 {
101 nonroot_leader = "{";
102 nonroot_trailer = "}";
103 }
104
a30b3e18
NA
105 buf = ctf_type_aname (fp, id);
106 if (!buf)
791915db
NA
107 {
108 if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE)
109 {
9323dd86 110 str = str_append (str, " (type not represented in CTF)");
791915db
NA
111 ctf_set_errno (fp, ECTF_NOTREF);
112 break;
113 }
114
115 goto err;
116 }
a30b3e18 117
70447401
NA
118 if (asprintf (&bit, " %s%lx: ", nonroot_leader, id) < 0)
119 goto oom;
120 str = str_append (str, bit);
121 free (bit);
122 bit = NULL;
a30b3e18 123
70447401
NA
124 if (buf[0] != '\0')
125 {
126 str = str_append (str, buf);
127 str = str_append (str, " ");
128 }
129
130 free (buf);
131 buf = NULL;
132
133 /* Slices get a different print representation. */
134 if (ctf_type_kind_unsliced (fp, id) == CTF_K_SLICE)
a30b3e18
NA
135 {
136 ctf_type_encoding (fp, id, &enc);
70447401
NA
137 if (asprintf (&bit, "[slice 0x%x:0x%x] ",
138 enc.cte_offset, enc.cte_bits) < 0)
a30b3e18
NA
139 goto oom;
140 }
70447401 141 else if (ctf_type_kind (fp, id) == CTF_K_INTEGER)
a30b3e18 142 {
70447401
NA
143 ctf_type_encoding (fp, id, &enc);
144 if (asprintf (&bit, "[0x%x:0x%x] ",
145 enc.cte_offset, enc.cte_bits) < 0)
a30b3e18
NA
146 goto oom;
147 }
70447401
NA
148 str = str_append (str, bit);
149 free (bit);
150 bit = NULL;
151
152 if (asprintf (&bit, "(size 0x%lx)%s",
153 (unsigned long) ctf_type_size (fp, id),
154 nonroot_trailer) < 0)
155 goto oom;
156
9323dd86 157 str = str_append (str, bit);
a30b3e18
NA
158 free (bit);
159 bit = NULL;
160
161 new_id = ctf_type_reference (fp, id);
162 if (new_id != CTF_ERR)
9323dd86 163 str = str_append (str, " ->");
a30b3e18
NA
164 } while (new_id != CTF_ERR);
165
166 if (ctf_errno (fp) != ECTF_NOTREF)
167 {
168 free (str);
169 return NULL;
170 }
171
172 return str;
173
174 oom:
791915db
NA
175 ctf_set_errno (fp, errno);
176 err:
926c9e76 177 ctf_err_warn (fp, 1, 0, _("cannot format name dumping type 0x%lx"), id);
a30b3e18
NA
178 free (buf);
179 free (str);
180 free (bit);
a30b3e18
NA
181 return NULL;
182}
183
9b32cba4
NA
184/* Dump one string field from the file header into the cds_items. */
185static int
139633c3 186ctf_dump_header_strfield (ctf_dict_t *fp, ctf_dump_state_t *state,
9b32cba4
NA
187 const char *name, uint32_t value)
188{
189 char *str;
190 if (value)
191 {
192 if (asprintf (&str, "%s: %s\n", name, ctf_strptr (fp, value)) < 0)
193 goto err;
194 ctf_dump_append (state, str);
195 }
196 return 0;
197
198 err:
791915db 199 return (ctf_set_errno (fp, errno));
9b32cba4
NA
200}
201
202/* Dump one section-offset field from the file header into the cds_items. */
203static int
139633c3 204ctf_dump_header_sectfield (ctf_dict_t *fp, ctf_dump_state_t *state,
9b32cba4
NA
205 const char *sect, uint32_t off, uint32_t nextoff)
206{
207 char *str;
208 if (nextoff - off)
209 {
210 if (asprintf (&str, "%s:\t0x%lx -- 0x%lx (0x%lx bytes)\n", sect,
211 (unsigned long) off, (unsigned long) (nextoff - 1),
212 (unsigned long) (nextoff - off)) < 0)
213 goto err;
214 ctf_dump_append (state, str);
215 }
216 return 0;
217
218 err:
791915db 219 return (ctf_set_errno (fp, errno));
9b32cba4
NA
220}
221
222/* Dump the file header into the cds_items. */
223static int
139633c3 224ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
9b32cba4
NA
225{
226 char *str;
4665e895 227 char *flagstr = NULL;
9b32cba4
NA
228 const ctf_header_t *hp = fp->ctf_header;
229 const char *vertab[] =
230 {
231 NULL, "CTF_VERSION_1",
232 "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
233 "boundaries)",
234 "CTF_VERSION_2",
235 "CTF_VERSION_3", NULL
236 };
237 const char *verstr = NULL;
238
239 if (asprintf (&str, "Magic number: %x\n", hp->cth_magic) < 0)
240 goto err;
241 ctf_dump_append (state, str);
242
243 if (hp->cth_version <= CTF_VERSION)
244 verstr = vertab[hp->cth_version];
245
246 if (verstr == NULL)
247 verstr = "(not a valid version)";
248
249 if (asprintf (&str, "Version: %i (%s)\n", hp->cth_version,
250 verstr) < 0)
251 goto err;
252 ctf_dump_append (state, str);
253
254 /* Everything else is only printed if present. */
255
139633c3 256 /* The flags are unusual in that they represent the ctf_dict_t *in memory*:
9b32cba4
NA
257 flags representing compression, etc, are turned off as the file is
258 decompressed. So we store a copy of the flags before they are changed, for
259 the dumper. */
260
261 if (fp->ctf_openflags > 0)
262 {
4665e895
NA
263 if (asprintf (&flagstr, "%s%s%s%s%s%s%s",
264 fp->ctf_openflags & CTF_F_COMPRESS
265 ? "CTF_F_COMPRESS": "",
266 (fp->ctf_openflags & CTF_F_COMPRESS)
267 && (fp->ctf_openflags & ~CTF_F_COMPRESS)
268 ? ", " : "",
269 fp->ctf_openflags & CTF_F_NEWFUNCINFO
270 ? "CTF_F_NEWFUNCINFO" : "",
271 (fp->ctf_openflags & (CTF_F_COMPRESS | CTF_F_NEWFUNCINFO))
272 && (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO))
273 ? ", " : "",
274 fp->ctf_openflags & CTF_F_IDXSORTED
275 ? "CTF_F_IDXSORTED" : "",
276 fp->ctf_openflags & (CTF_F_COMPRESS | CTF_F_NEWFUNCINFO
277 | CTF_F_IDXSORTED)
278 && (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO
279 | CTF_F_IDXSORTED))
280 ? ", " : "",
281 fp->ctf_openflags & CTF_F_DYNSTR
282 ? "CTF_F_DYNSTR" : "") < 0)
283 goto err;
284
285 if (asprintf (&str, "Flags: 0x%x (%s)", fp->ctf_openflags, flagstr) < 0)
9b32cba4
NA
286 goto err;
287 ctf_dump_append (state, str);
288 }
289
290 if (ctf_dump_header_strfield (fp, state, "Parent label",
291 hp->cth_parlabel) < 0)
292 goto err;
293
294 if (ctf_dump_header_strfield (fp, state, "Parent name", hp->cth_parname) < 0)
295 goto err;
296
297 if (ctf_dump_header_strfield (fp, state, "Compilation unit name",
298 hp->cth_cuname) < 0)
299 goto err;
300
301 if (ctf_dump_header_sectfield (fp, state, "Label section", hp->cth_lbloff,
302 hp->cth_objtoff) < 0)
303 goto err;
304
305 if (ctf_dump_header_sectfield (fp, state, "Data object section",
306 hp->cth_objtoff, hp->cth_funcoff) < 0)
307 goto err;
308
309 if (ctf_dump_header_sectfield (fp, state, "Function info section",
4665e895
NA
310 hp->cth_funcoff, hp->cth_objtidxoff) < 0)
311 goto err;
312
313 if (ctf_dump_header_sectfield (fp, state, "Object index section",
314 hp->cth_objtidxoff, hp->cth_funcidxoff) < 0)
315 goto err;
316
317 if (ctf_dump_header_sectfield (fp, state, "Function index section",
318 hp->cth_funcidxoff, hp->cth_varoff) < 0)
9b32cba4
NA
319 goto err;
320
321 if (ctf_dump_header_sectfield (fp, state, "Variable section",
322 hp->cth_varoff, hp->cth_typeoff) < 0)
323 goto err;
324
325 if (ctf_dump_header_sectfield (fp, state, "Type section",
326 hp->cth_typeoff, hp->cth_stroff) < 0)
327 goto err;
328
329 if (ctf_dump_header_sectfield (fp, state, "String section", hp->cth_stroff,
330 hp->cth_stroff + hp->cth_strlen + 1) < 0)
331 goto err;
332
333 return 0;
334 err:
4665e895 335 free (flagstr);
791915db 336 return (ctf_set_errno (fp, errno));
9b32cba4
NA
337}
338
a30b3e18
NA
339/* Dump a single label into the cds_items. */
340
341static int
342ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
343 void *arg)
344{
345 char *str;
346 char *typestr;
347 ctf_dump_state_t *state = arg;
348
349 if (asprintf (&str, "%s -> ", name) < 0)
791915db 350 return (ctf_set_errno (state->cds_fp, errno));
a30b3e18 351
b4f0e09c
NA
352 if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type,
353 CTF_ADD_ROOT)) == NULL)
a30b3e18
NA
354 {
355 free (str);
8e795b46 356 return 0; /* Swallow the error. */
a30b3e18
NA
357 }
358
9323dd86 359 str = str_append (str, typestr);
a30b3e18
NA
360 free (typestr);
361
362 ctf_dump_append (state, str);
363 return 0;
364}
365
4665e895 366/* Dump all the object or function entries into the cds_items. */
a30b3e18
NA
367
368static int
4665e895 369ctf_dump_objts (ctf_dict_t *fp, ctf_dump_state_t *state, int functions)
a30b3e18 370{
4665e895
NA
371 const char *name;
372 ctf_id_t id;
373 ctf_next_t *i = NULL;
374 char *str = NULL;
375
376 if ((functions && fp->ctf_funcidx_names)
377 || (!functions && fp->ctf_objtidx_names))
378 str = str_append (str, _("Section is indexed.\n"));
379 else if (fp->ctf_symtab.cts_data == NULL)
380 str = str_append (str, _("No symbol table.\n"));
381
382 while ((id = ctf_symbol_next (fp, &i, &name, functions)) != CTF_ERR)
a30b3e18 383 {
4665e895
NA
384 char *typestr = NULL;
385 int err = 0;
a30b3e18 386
4665e895
NA
387 /* Emit the name, if we know it. */
388 if (name)
a30b3e18 389 {
4665e895
NA
390 if (asprintf (&str, "%s -> ", name) < 0)
391 goto oom;
a30b3e18 392 }
4665e895
NA
393 else
394 str = xstrdup ("");
a30b3e18 395
4665e895 396 if ((typestr = ctf_type_aname (fp, id)) == NULL)
791915db 397 {
4665e895
NA
398 if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE)
399 {
400 if (asprintf (&typestr, " (%s)", _("type not represented in CTF")) < 0)
401 goto oom;
a30b3e18 402
4665e895
NA
403 goto out;
404 }
c6e9a1e5 405
e8cda209 406 if (asprintf (&typestr, _("error: %s"), ctf_errmsg (ctf_errno (fp))) < 0)
a30b3e18 407 goto oom;
a30b3e18 408
4665e895
NA
409 err = -1;
410 goto out;
a30b3e18
NA
411 }
412
4665e895
NA
413 str = str_append (str, typestr);
414 str = str_append (str, "\n");
a30b3e18
NA
415 ctf_dump_append (state, str);
416 continue;
417
418 oom:
4665e895
NA
419 ctf_set_errno (fp, ENOMEM);
420 ctf_next_destroy (i);
421 return -1;
422 out:
423 str = str_append (str, typestr);
424 free (typestr);
425 ctf_dump_append (state, str);
426 ctf_next_destroy (i);
427 return err; /* errno is set for us. */
a30b3e18
NA
428 }
429 return 0;
430}
431
432/* Dump a single variable into the cds_items. */
433static int
434ctf_dump_var (const char *name, ctf_id_t type, void *arg)
435{
436 char *str;
437 char *typestr;
438 ctf_dump_state_t *state = arg;
439
440 if (asprintf (&str, "%s -> ", name) < 0)
791915db 441 return (ctf_set_errno (state->cds_fp, errno));
a30b3e18 442
b4f0e09c
NA
443 if ((typestr = ctf_dump_format_type (state->cds_fp, type,
444 CTF_ADD_ROOT)) == NULL)
a30b3e18
NA
445 {
446 free (str);
8e795b46 447 return 0; /* Swallow the error. */
a30b3e18
NA
448 }
449
9323dd86 450 str = str_append (str, typestr);
a30b3e18
NA
451 free (typestr);
452
453 ctf_dump_append (state, str);
454 return 0;
455}
456
457/* Dump a single member into the string in the membstate. */
458static int
459ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
460 int depth, void *arg)
461{
462 ctf_dump_membstate_t *state = arg;
463 char *typestr = NULL;
464 char *bit = NULL;
465 ctf_encoding_t ep;
70447401 466 int has_encoding = 0;
a30b3e18
NA
467 ssize_t i;
468
469 for (i = 0; i < depth; i++)
9323dd86 470 *state->cdm_str = str_append (*state->cdm_str, " ");
a30b3e18
NA
471
472 if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL)
791915db
NA
473 {
474 if (id == 0 || ctf_errno (state->cdm_fp) == ECTF_NONREPRESENTABLE)
475 {
476 if (asprintf (&bit, " [0x%lx] (type not represented in CTF)",
477 offset) < 0)
478 goto oom;
479
9323dd86 480 *state->cdm_str = str_append (*state->cdm_str, bit);
791915db
NA
481 free (typestr);
482 free (bit);
483 return 0;
484 }
485
70447401
NA
486 return -1; /* errno is set for us. */
487 }
488
489 if (ctf_type_encoding (state->cdm_fp, id, &ep) == 0)
490 {
491 has_encoding = 1;
492 ctf_type_encoding (state->cdm_fp, id, &ep);
493
494 if (asprintf (&bit, " [0x%lx] (ID 0x%lx) (kind %i) %s%s%s:%i "
495 "(aligned at 0x%lx", offset, id,
496 ctf_type_kind (state->cdm_fp, id), typestr,
497 (name[0] != 0 && typestr[0] != 0) ? " " : "", name,
498 ep.cte_bits, (unsigned long) ctf_type_align (state->cdm_fp,
499 id)) < 0)
500 goto oom;
501 }
502 else
503 {
504 if (asprintf (&bit, " [0x%lx] (ID 0x%lx) (kind %i) %s%s%s "
505 "(aligned at 0x%lx", offset, id,
506 ctf_type_kind (state->cdm_fp, id), typestr,
507 (name[0] != 0 && typestr[0] != 0) ? " " : "", name,
508 (unsigned long) ctf_type_align (state->cdm_fp, id)) < 0)
509 goto oom;
791915db 510 }
a30b3e18 511
9323dd86 512 *state->cdm_str = str_append (*state->cdm_str, bit);
a30b3e18
NA
513 free (typestr);
514 free (bit);
515 typestr = NULL;
516 bit = NULL;
517
70447401 518 if (has_encoding)
a30b3e18 519 {
a30b3e18
NA
520 if (asprintf (&bit, ", format 0x%x, offset:bits 0x%x:0x%x", ep.cte_format,
521 ep.cte_offset, ep.cte_bits) < 0)
522 goto oom;
9323dd86 523 *state->cdm_str = str_append (*state->cdm_str, bit);
a30b3e18
NA
524 free (bit);
525 bit = NULL;
526 }
527
9323dd86 528 *state->cdm_str = str_append (*state->cdm_str, ")\n");
a30b3e18
NA
529 return 0;
530
531 oom:
532 free (typestr);
533 free (bit);
791915db 534 return (ctf_set_errno (state->cdm_fp, errno));
a30b3e18
NA
535}
536
537/* Dump a single type into the cds_items. */
a30b3e18 538static int
b4f0e09c 539ctf_dump_type (ctf_id_t id, int flag, void *arg)
a30b3e18
NA
540{
541 char *str;
542 ctf_dump_state_t *state = arg;
543 ctf_dump_membstate_t membstate = { &str, state->cds_fp };
544 size_t len;
545
b4f0e09c 546 if ((str = ctf_dump_format_type (state->cds_fp, id, flag)) == NULL)
926c9e76 547 goto err;
a30b3e18 548
9323dd86 549 str = str_append (str, "\n");
a30b3e18 550 if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
791915db
NA
551 {
552 if (id == 0 || ctf_errno (state->cds_fp) == ECTF_NONREPRESENTABLE)
553 {
554 ctf_dump_append (state, str);
555 return 0;
556 }
926c9e76
NA
557 ctf_err_warn (state->cds_fp, 1, ctf_errno (state->cds_fp),
558 _("cannot visit members dumping type 0x%lx"), id);
791915db
NA
559 goto err;
560 }
a30b3e18
NA
561
562 /* Trim off the last linefeed added by ctf_dump_member(). */
563 len = strlen (str);
564 if (str[len-1] == '\n')
565 str[len-1] = '\0';
566
567 ctf_dump_append (state, str);
568 return 0;
569
570 err:
571 free (str);
8e795b46 572 return 0; /* Swallow the error. */
a30b3e18
NA
573}
574
575/* Dump the string table into the cds_items. */
576
577static int
139633c3 578ctf_dump_str (ctf_dict_t *fp, ctf_dump_state_t *state)
a30b3e18
NA
579{
580 const char *s = fp->ctf_str[CTF_STRTAB_0].cts_strs;
581
582 for (; s < fp->ctf_str[CTF_STRTAB_0].cts_strs +
583 fp->ctf_str[CTF_STRTAB_0].cts_len;)
584 {
585 char *str;
595a4d43
NA
586 if (asprintf (&str, "%lx: %s",
587 (unsigned long) (s - fp->ctf_str[CTF_STRTAB_0].cts_strs),
a30b3e18 588 s) < 0)
791915db 589 return (ctf_set_errno (fp, errno));
a30b3e18
NA
590 ctf_dump_append (state, str);
591 s += strlen (s) + 1;
592 }
593
594 return 0;
595}
596
597/* Dump a particular section of a CTF file, in textual form. Call with a
598 pointer to a NULL STATE: each call emits a dynamically allocated string
599 containing a description of one entity in the specified section, in order.
600 Only the first call (with a NULL state) may vary SECT. Once the CTF section
601 has been entirely dumped, the call returns NULL and frees and annuls the
602 STATE, ready for another section to be dumped. The returned textual content
603 may span multiple lines: between each call the FUNC is called with one
604 textual line at a time, and should return a suitably decorated line (it can
605 allocate a new one and return it if it likes). */
606
607char *
139633c3 608ctf_dump (ctf_dict_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect,
a30b3e18
NA
609 ctf_dump_decorate_f *func, void *arg)
610{
611 char *str;
612 char *line;
613 ctf_dump_state_t *state = NULL;
614
615 if (*statep == NULL)
616 {
617 /* Data collection. Transforming a call-at-a-time iterator into a
618 return-at-a-time iterator in a language without call/cc is annoying. It
619 is easiest to simply collect everything at once and then return it bit
620 by bit. The first call will take (much) longer than otherwise, but the
621 amortized time needed is the same. */
622
de07e349 623 if ((*statep = malloc (sizeof (struct ctf_dump_state))) == NULL)
a30b3e18
NA
624 {
625 ctf_set_errno (fp, ENOMEM);
626 goto end;
627 }
628 state = *statep;
629
630 memset (state, 0, sizeof (struct ctf_dump_state));
631 state->cds_fp = fp;
632 state->cds_sect = sect;
633
634 switch (sect)
635 {
636 case CTF_SECT_HEADER:
9b32cba4 637 ctf_dump_header (fp, state);
a30b3e18
NA
638 break;
639 case CTF_SECT_LABEL:
640 if (ctf_label_iter (fp, ctf_dump_label, state) < 0)
641 {
642 if (ctf_errno (fp) != ECTF_NOLABELDATA)
643 goto end; /* errno is set for us. */
644 ctf_set_errno (fp, 0);
645 }
646 break;
647 case CTF_SECT_OBJT:
4665e895 648 if (ctf_dump_objts (fp, state, 0) < 0)
a30b3e18
NA
649 goto end; /* errno is set for us. */
650 break;
651 case CTF_SECT_FUNC:
4665e895 652 if (ctf_dump_objts (fp, state, 1) < 0)
a30b3e18
NA
653 goto end; /* errno is set for us. */
654 break;
655 case CTF_SECT_VAR:
656 if (ctf_variable_iter (fp, ctf_dump_var, state) < 0)
657 goto end; /* errno is set for us. */
658 break;
659 case CTF_SECT_TYPE:
b4f0e09c 660 if (ctf_type_iter_all (fp, ctf_dump_type, state) < 0)
a30b3e18
NA
661 goto end; /* errno is set for us. */
662 break;
663 case CTF_SECT_STR:
664 ctf_dump_str (fp, state);
665 break;
666 default:
667 ctf_set_errno (fp, ECTF_DUMPSECTUNKNOWN);
668 goto end;
669 }
670 }
671 else
672 {
673 state = *statep;
674
675 if (state->cds_sect != sect)
676 {
677 ctf_set_errno (fp, ECTF_DUMPSECTCHANGED);
678 goto end;
679 }
680 }
681
682 if (state->cds_current == NULL)
683 state->cds_current = ctf_list_next (&state->cds_items);
684 else
685 state->cds_current = ctf_list_next (state->cds_current);
686
687 if (state->cds_current == NULL)
688 goto end;
689
690 /* Hookery. There is some extra complexity to preserve linefeeds within each
691 item while removing linefeeds at the end. */
692 if (func)
693 {
694 size_t len;
695
696 str = NULL;
697 for (line = state->cds_current->cdi_item; line && *line; )
698 {
699 char *nline = line;
700 char *ret;
701
702 nline = strchr (line, '\n');
703 if (nline)
704 nline[0] = '\0';
705
706 ret = func (sect, line, arg);
9323dd86
NA
707 str = str_append (str, ret);
708 str = str_append (str, "\n");
a30b3e18
NA
709 if (ret != line)
710 free (ret);
711
712 if (nline)
713 {
714 nline[0] = '\n';
715 nline++;
716 }
717
718 line = nline;
719 }
720
721 len = strlen (str);
722
723 if (str[len-1] == '\n')
724 str[len-1] = '\0';
725 }
726 else
9323dd86
NA
727 {
728 str = strdup (state->cds_current->cdi_item);
729 if (!str)
730 {
731 ctf_set_errno (fp, ENOMEM);
732 return str;
733 }
734 }
a30b3e18
NA
735
736 ctf_set_errno (fp, 0);
737 return str;
738
739 end:
740 ctf_dump_free (state);
de07e349 741 free (state);
a30b3e18
NA
742 ctf_set_errno (fp, 0);
743 *statep = NULL;
744 return NULL;
745}