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