AArch64: Add gdbserver MTE support
[deliverable/binutils-gdb.git] / libctf / ctf-dump.c
1 /* Textual dumping of CTF data.
2 Copyright (C) 2019-2021 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 #define str_append(s, a) ctf_str_append_noerr (s, a)
24
25 /* One item to be dumped, in string form. */
26
27 typedef 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
36 struct ctf_dump_state
37 {
38 ctf_sect_names_t cds_sect;
39 ctf_dict_t *cds_fp;
40 ctf_dump_item_t *cds_current;
41 ctf_list_t cds_items;
42 };
43
44 /* Cross-call state for ctf_dump_member. */
45
46 typedef struct ctf_dump_membstate
47 {
48 char **cdm_str;
49 ctf_dict_t *cdm_fp;
50 const char *cdm_toplevel_indent;
51 } ctf_dump_membstate_t;
52
53 static int
54 ctf_dump_append (ctf_dump_state_t *state, char *str)
55 {
56 ctf_dump_item_t *cdi;
57
58 if ((cdi = malloc (sizeof (struct ctf_dump_item))) == NULL)
59 return (ctf_set_errno (state->cds_fp, ENOMEM));
60
61 cdi->cdi_item = str;
62 ctf_list_append (&state->cds_items, cdi);
63 return 0;
64 }
65
66 static void
67 ctf_dump_free (ctf_dump_state_t *state)
68 {
69 ctf_dump_item_t *cdi, *next_cdi;
70
71 if (state == NULL)
72 return;
73
74 for (cdi = ctf_list_next (&state->cds_items); cdi != NULL;
75 cdi = next_cdi)
76 {
77 free (cdi->cdi_item);
78 next_cdi = ctf_list_next (cdi);
79 free (cdi);
80 }
81 }
82
83 /* Return a dump for a single type, without member info: but do optionally show
84 the type's references. */
85
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. */
89
90 static char *
91 ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag)
92 {
93 ctf_id_t new_id;
94 char *str = NULL, *bit = NULL, *buf = NULL;
95
96 ctf_set_errno (fp, 0);
97 new_id = id;
98 do
99 {
100 ctf_encoding_t ep;
101 ctf_arinfo_t ar;
102 int kind, unsliced_kind;
103 const char *nonroot_leader = "";
104 const char *nonroot_trailer = "";
105 const char *idstr = "";
106
107 id = new_id;
108 if (flag == CTF_ADD_NONROOT)
109 {
110 nonroot_leader = "{";
111 nonroot_trailer = "}";
112 }
113
114 buf = ctf_type_aname (fp, id);
115 if (!buf)
116 {
117 if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE)
118 {
119 ctf_set_errno (fp, ECTF_NONREPRESENTABLE);
120 str = str_append (str, " (type not represented in CTF)");
121 return str;
122 }
123
124 goto err;
125 }
126
127 if (flag & CTF_FT_ID)
128 idstr = "ID ";
129 if (asprintf (&bit, "%s%s0x%lx: (kind %i) ", nonroot_leader, idstr,
130 id, ctf_type_kind (fp, id)) < 0)
131 goto oom;
132 str = str_append (str, bit);
133 free (bit);
134 bit = NULL;
135
136 if (buf[0] != '\0')
137 str = str_append (str, buf);
138
139 free (buf);
140 buf = NULL;
141
142 unsliced_kind = ctf_type_kind_unsliced (fp, id);
143 kind = ctf_type_kind (fp, id);
144
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)
149 {
150 if ((ssize_t) ep.cte_bits != ctf_type_size (fp, id) * CHAR_BIT
151 && flag & CTF_FT_BITFIELD)
152 {
153 if (asprintf (&bit, ":%i", ep.cte_bits) < 0)
154 goto oom;
155 str = str_append (str, bit);
156 free (bit);
157 bit = NULL;
158 }
159
160 if ((ssize_t) ep.cte_bits != ctf_type_size (fp, id) * CHAR_BIT
161 || ep.cte_offset != 0)
162 {
163 const char *slice = "";
164
165 if (unsliced_kind == CTF_K_SLICE)
166 slice = "slice ";
167
168 if (asprintf (&bit, " [%s0x%x:0x%x]",
169 slice, ep.cte_offset, ep.cte_bits) < 0)
170 goto oom;
171 str = str_append (str, bit);
172 free (bit);
173 bit = NULL;
174 }
175
176 if (asprintf (&bit, " (format 0x%x)", ep.cte_format) < 0)
177 goto oom;
178 str = str_append (str, bit);
179 free (bit);
180 bit = NULL;
181 }
182
183 if (kind != CTF_K_FUNCTION && kind != CTF_K_FORWARD)
184 {
185 if (asprintf (&bit, " (size 0x%lx)",
186 (unsigned long) ctf_type_size (fp, id)) < 0)
187 goto oom;
188
189 str = str_append (str, bit);
190 free (bit);
191 bit = NULL;
192 }
193
194 if (kind != CTF_K_FORWARD)
195 {
196 if (asprintf (&bit, " (aligned at 0x%lx)",
197 (unsigned long) ctf_type_align (fp, id)) < 0)
198 goto oom;
199
200 str = str_append (str, bit);
201 free (bit);
202 bit = NULL;
203 }
204
205 if (nonroot_trailer[0] != 0)
206 str = str_append (str, nonroot_trailer);
207
208 /* Just exit after one iteration if we are not showing the types this type
209 references. */
210 if (!(flag & CTF_FT_REFS))
211 return str;
212
213 /* Keep going as long as this type references another. We consider arrays
214 to "reference" their element type. */
215
216 if (kind == CTF_K_ARRAY)
217 {
218 if (ctf_array_info (fp, id, &ar) < 0)
219 goto err;
220 new_id = ar.ctr_contents;
221 }
222 else
223 new_id = ctf_type_reference (fp, id);
224 if (new_id != CTF_ERR)
225 str = str_append (str, " -> ");
226 }
227 while (new_id != CTF_ERR);
228
229 if (ctf_errno (fp) != ECTF_NOTREF)
230 {
231 free (str);
232 return NULL;
233 }
234
235 return str;
236
237 oom:
238 ctf_set_errno (fp, errno);
239 err:
240 ctf_err_warn (fp, 1, 0, _("cannot format name dumping type 0x%lx"), id);
241 free (buf);
242 free (str);
243 free (bit);
244 return NULL;
245 }
246
247 /* Dump one string field from the file header into the cds_items. */
248 static int
249 ctf_dump_header_strfield (ctf_dict_t *fp, ctf_dump_state_t *state,
250 const char *name, uint32_t value)
251 {
252 char *str;
253 if (value)
254 {
255 if (asprintf (&str, "%s: %s\n", name, ctf_strptr (fp, value)) < 0)
256 goto err;
257 ctf_dump_append (state, str);
258 }
259 return 0;
260
261 err:
262 return (ctf_set_errno (fp, errno));
263 }
264
265 /* Dump one section-offset field from the file header into the cds_items. */
266 static int
267 ctf_dump_header_sectfield (ctf_dict_t *fp, ctf_dump_state_t *state,
268 const char *sect, uint32_t off, uint32_t nextoff)
269 {
270 char *str;
271 if (nextoff - off)
272 {
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)
276 goto err;
277 ctf_dump_append (state, str);
278 }
279 return 0;
280
281 err:
282 return (ctf_set_errno (fp, errno));
283 }
284
285 /* Dump the file header into the cds_items. */
286 static int
287 ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
288 {
289 char *str;
290 char *flagstr = NULL;
291 const ctf_header_t *hp = fp->ctf_header;
292 const char *vertab[] =
293 {
294 NULL, "CTF_VERSION_1",
295 "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
296 "boundaries)",
297 "CTF_VERSION_2",
298 "CTF_VERSION_3", NULL
299 };
300 const char *verstr = NULL;
301
302 if (asprintf (&str, "Magic number: 0x%x\n", hp->cth_magic) < 0)
303 goto err;
304 ctf_dump_append (state, str);
305
306 if (hp->cth_version <= CTF_VERSION)
307 verstr = vertab[hp->cth_version];
308
309 if (verstr == NULL)
310 verstr = "(not a valid version)";
311
312 if (asprintf (&str, "Version: %i (%s)\n", hp->cth_version,
313 verstr) < 0)
314 goto err;
315 ctf_dump_append (state, str);
316
317 /* Everything else is only printed if present. */
318
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
322 the dumper. */
323
324 if (fp->ctf_openflags > 0)
325 {
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)
331 ? ", " : "",
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))
336 ? ", " : "",
337 fp->ctf_openflags & CTF_F_IDXSORTED
338 ? "CTF_F_IDXSORTED" : "",
339 fp->ctf_openflags & (CTF_F_COMPRESS | CTF_F_NEWFUNCINFO
340 | CTF_F_IDXSORTED)
341 && (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO
342 | CTF_F_IDXSORTED))
343 ? ", " : "",
344 fp->ctf_openflags & CTF_F_DYNSTR
345 ? "CTF_F_DYNSTR" : "") < 0)
346 goto err;
347
348 if (asprintf (&str, "Flags: 0x%x (%s)", fp->ctf_openflags, flagstr) < 0)
349 goto err;
350 ctf_dump_append (state, str);
351 }
352
353 if (ctf_dump_header_strfield (fp, state, "Parent label",
354 hp->cth_parlabel) < 0)
355 goto err;
356
357 if (ctf_dump_header_strfield (fp, state, "Parent name", hp->cth_parname) < 0)
358 goto err;
359
360 if (ctf_dump_header_strfield (fp, state, "Compilation unit name",
361 hp->cth_cuname) < 0)
362 goto err;
363
364 if (ctf_dump_header_sectfield (fp, state, "Label section", hp->cth_lbloff,
365 hp->cth_objtoff) < 0)
366 goto err;
367
368 if (ctf_dump_header_sectfield (fp, state, "Data object section",
369 hp->cth_objtoff, hp->cth_funcoff) < 0)
370 goto err;
371
372 if (ctf_dump_header_sectfield (fp, state, "Function info section",
373 hp->cth_funcoff, hp->cth_objtidxoff) < 0)
374 goto err;
375
376 if (ctf_dump_header_sectfield (fp, state, "Object index section",
377 hp->cth_objtidxoff, hp->cth_funcidxoff) < 0)
378 goto err;
379
380 if (ctf_dump_header_sectfield (fp, state, "Function index section",
381 hp->cth_funcidxoff, hp->cth_varoff) < 0)
382 goto err;
383
384 if (ctf_dump_header_sectfield (fp, state, "Variable section",
385 hp->cth_varoff, hp->cth_typeoff) < 0)
386 goto err;
387
388 if (ctf_dump_header_sectfield (fp, state, "Type section",
389 hp->cth_typeoff, hp->cth_stroff) < 0)
390 goto err;
391
392 if (ctf_dump_header_sectfield (fp, state, "String section", hp->cth_stroff,
393 hp->cth_stroff + hp->cth_strlen + 1) < 0)
394 goto err;
395
396 return 0;
397 err:
398 free (flagstr);
399 return (ctf_set_errno (fp, errno));
400 }
401
402 /* Dump a single label into the cds_items. */
403
404 static int
405 ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
406 void *arg)
407 {
408 char *str;
409 char *typestr;
410 ctf_dump_state_t *state = arg;
411
412 if (asprintf (&str, "%s -> ", name) < 0)
413 return (ctf_set_errno (state->cds_fp, errno));
414
415 if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type,
416 CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)
417 {
418 free (str);
419 return 0; /* Swallow the error. */
420 }
421
422 str = str_append (str, typestr);
423 free (typestr);
424
425 ctf_dump_append (state, str);
426 return 0;
427 }
428
429 /* Dump all the object or function entries into the cds_items. */
430
431 static int
432 ctf_dump_objts (ctf_dict_t *fp, ctf_dump_state_t *state, int functions)
433 {
434 const char *name;
435 ctf_id_t id;
436 ctf_next_t *i = NULL;
437 char *str = NULL;
438
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"));
444
445 while ((id = ctf_symbol_next (fp, &i, &name, functions)) != CTF_ERR)
446 {
447 char *typestr = NULL;
448
449 /* Emit the name, if we know it. No trailing space: ctf_dump_format_type
450 has a leading one. */
451 if (name)
452 {
453 if (asprintf (&str, "%s -> ", name) < 0)
454 goto oom;
455 }
456 else
457 str = xstrdup ("");
458
459 if ((typestr = ctf_dump_format_type (state->cds_fp, id,
460 CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)
461 {
462 ctf_dump_append (state, str);
463 continue; /* Swallow the error. */
464 }
465
466 str = str_append (str, typestr);
467 free (typestr);
468 ctf_dump_append (state, str);
469 continue;
470
471 oom:
472 ctf_set_errno (fp, ENOMEM);
473 ctf_next_destroy (i);
474 return -1;
475 }
476 return 0;
477 }
478
479 /* Dump a single variable into the cds_items. */
480 static int
481 ctf_dump_var (const char *name, ctf_id_t type, void *arg)
482 {
483 char *str;
484 char *typestr;
485 ctf_dump_state_t *state = arg;
486
487 if (asprintf (&str, "%s -> ", name) < 0)
488 return (ctf_set_errno (state->cds_fp, errno));
489
490 if ((typestr = ctf_dump_format_type (state->cds_fp, type,
491 CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)
492 {
493 free (str);
494 return 0; /* Swallow the error. */
495 }
496
497 str = str_append (str, typestr);
498 free (typestr);
499
500 ctf_dump_append (state, str);
501 return 0;
502 }
503
504 /* Dump a single struct/union member into the string in the membstate. */
505 static int
506 ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
507 int depth, void *arg)
508 {
509 ctf_dump_membstate_t *state = arg;
510 char *typestr = NULL;
511 char *bit = NULL;
512
513 /* The struct/union itself has already been printed. */
514 if (depth == 0)
515 return 0;
516
517 if (asprintf (&bit, "%s%*s", state->cdm_toplevel_indent, (depth-1)*4, "") < 0)
518 goto oom;
519 *state->cdm_str = str_append (*state->cdm_str, bit);
520 free (bit);
521
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. */
526
527 if (asprintf (&bit, "[0x%lx] %s: %s\n", offset, name, typestr) < 0)
528 goto oom;
529
530 *state->cdm_str = str_append (*state->cdm_str, bit);
531 free (typestr);
532 free (bit);
533 typestr = NULL;
534 bit = NULL;
535
536 return 0;
537
538 oom:
539 free (typestr);
540 free (bit);
541 return (ctf_set_errno (state->cdm_fp, errno));
542 }
543
544 /* Report the number of digits in the hexadecimal representation of a type
545 ID. */
546
547 static int
548 type_hex_digits (ctf_id_t id)
549 {
550 int i = 0;
551
552 if (id == 0)
553 return 1;
554
555 for (; id > 0; id >>= 4, i++);
556 return i;
557 }
558
559 /* Dump a single type into the cds_items. */
560 static int
561 ctf_dump_type (ctf_id_t id, int flag, void *arg)
562 {
563 char *str;
564 char *indent;
565 int err = 0;
566 ctf_dump_state_t *state = arg;
567 ctf_dump_membstate_t membstate = { &str, state->cds_fp, NULL };
568
569 /* Indent neatly. */
570 if (asprintf (&indent, " %*s", type_hex_digits (id), "") < 0)
571 return (ctf_set_errno (state->cds_fp, ENOMEM));
572
573 /* Dump the type itself. */
574 if ((str = ctf_dump_format_type (state->cds_fp, id,
575 flag | CTF_FT_REFS)) == NULL)
576 goto err;
577 str = str_append (str, "\n");
578
579 membstate.cdm_toplevel_indent = indent;
580
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)
584 {
585 if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
586 {
587 if (id == 0 || ctf_errno (state->cds_fp) == ECTF_NONREPRESENTABLE)
588 {
589 ctf_dump_append (state, str);
590 return 0;
591 }
592 ctf_err_warn (state->cds_fp, 1, ctf_errno (state->cds_fp),
593 _("cannot visit members dumping type 0x%lx"), id);
594 goto err;
595 }
596 }
597
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)
601 {
602 int enum_count = ctf_member_count (state->cds_fp, id);
603 ctf_next_t *it = NULL;
604 int i = 0;
605 const char *enumerand;
606 char *bit;
607 int value;
608
609 while ((enumerand = ctf_enum_next (state->cds_fp, id,
610 &it, &value)) != NULL)
611 {
612 i++;
613 if ((i > 5) && (i < enum_count - 4))
614 continue;
615
616 str = str_append (str, indent);
617
618 if (asprintf (&bit, "%s: %i\n", enumerand, value) < 0)
619 {
620 err = ENOMEM;
621 ctf_next_destroy (it);
622 goto err;
623 }
624 str = str_append (str, bit);
625 free (bit);
626
627 if ((i == 5) && (enum_count > 10))
628 {
629 str = str_append (str, indent);
630 str = str_append (str, "...\n");
631 }
632 }
633 if (ctf_errno (state->cds_fp) != ECTF_NEXT_END)
634 {
635 ctf_err_warn (state->cds_fp, 1, ctf_errno (state->cds_fp),
636 _("cannot visit enumerands dumping type 0x%lx"), id);
637 goto err;
638 }
639 }
640
641 ctf_dump_append (state, str);
642 free (indent);
643
644 return 0;
645
646 err:
647 free (indent);
648 free (str);
649 return ctf_set_errno (state->cds_fp, err);
650 }
651
652 /* Dump the string table into the cds_items. */
653
654 static int
655 ctf_dump_str (ctf_dict_t *fp, ctf_dump_state_t *state)
656 {
657 const char *s = fp->ctf_str[CTF_STRTAB_0].cts_strs;
658
659 for (; s < fp->ctf_str[CTF_STRTAB_0].cts_strs +
660 fp->ctf_str[CTF_STRTAB_0].cts_len;)
661 {
662 char *str;
663 if (asprintf (&str, "0x%lx: %s",
664 (unsigned long) (s - fp->ctf_str[CTF_STRTAB_0].cts_strs),
665 s) < 0)
666 return (ctf_set_errno (fp, errno));
667 ctf_dump_append (state, str);
668 s += strlen (s) + 1;
669 }
670
671 return 0;
672 }
673
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). */
683
684 char *
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)
687 {
688 char *str;
689 char *line;
690 ctf_dump_state_t *state = NULL;
691
692 if (*statep == NULL)
693 {
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. */
699
700 if ((*statep = malloc (sizeof (struct ctf_dump_state))) == NULL)
701 {
702 ctf_set_errno (fp, ENOMEM);
703 goto end;
704 }
705 state = *statep;
706
707 memset (state, 0, sizeof (struct ctf_dump_state));
708 state->cds_fp = fp;
709 state->cds_sect = sect;
710
711 switch (sect)
712 {
713 case CTF_SECT_HEADER:
714 ctf_dump_header (fp, state);
715 break;
716 case CTF_SECT_LABEL:
717 if (ctf_label_iter (fp, ctf_dump_label, state) < 0)
718 {
719 if (ctf_errno (fp) != ECTF_NOLABELDATA)
720 goto end; /* errno is set for us. */
721 ctf_set_errno (fp, 0);
722 }
723 break;
724 case CTF_SECT_OBJT:
725 if (ctf_dump_objts (fp, state, 0) < 0)
726 goto end; /* errno is set for us. */
727 break;
728 case CTF_SECT_FUNC:
729 if (ctf_dump_objts (fp, state, 1) < 0)
730 goto end; /* errno is set for us. */
731 break;
732 case CTF_SECT_VAR:
733 if (ctf_variable_iter (fp, ctf_dump_var, state) < 0)
734 goto end; /* errno is set for us. */
735 break;
736 case CTF_SECT_TYPE:
737 if (ctf_type_iter_all (fp, ctf_dump_type, state) < 0)
738 goto end; /* errno is set for us. */
739 break;
740 case CTF_SECT_STR:
741 ctf_dump_str (fp, state);
742 break;
743 default:
744 ctf_set_errno (fp, ECTF_DUMPSECTUNKNOWN);
745 goto end;
746 }
747 }
748 else
749 {
750 state = *statep;
751
752 if (state->cds_sect != sect)
753 {
754 ctf_set_errno (fp, ECTF_DUMPSECTCHANGED);
755 goto end;
756 }
757 }
758
759 if (state->cds_current == NULL)
760 state->cds_current = ctf_list_next (&state->cds_items);
761 else
762 state->cds_current = ctf_list_next (state->cds_current);
763
764 if (state->cds_current == NULL)
765 goto end;
766
767 /* Hookery. There is some extra complexity to preserve linefeeds within each
768 item while removing linefeeds at the end. */
769 if (func)
770 {
771 size_t len;
772
773 str = NULL;
774 for (line = state->cds_current->cdi_item; line && *line; )
775 {
776 char *nline = line;
777 char *ret;
778
779 nline = strchr (line, '\n');
780 if (nline)
781 nline[0] = '\0';
782
783 ret = func (sect, line, arg);
784 str = str_append (str, ret);
785 str = str_append (str, "\n");
786 if (ret != line)
787 free (ret);
788
789 if (nline)
790 {
791 nline[0] = '\n';
792 nline++;
793 }
794
795 line = nline;
796 }
797
798 len = strlen (str);
799
800 if (str[len-1] == '\n')
801 str[len-1] = '\0';
802 }
803 else
804 {
805 str = strdup (state->cds_current->cdi_item);
806 if (!str)
807 {
808 ctf_set_errno (fp, ENOMEM);
809 return str;
810 }
811 }
812
813 ctf_set_errno (fp, 0);
814 return str;
815
816 end:
817 ctf_dump_free (state);
818 free (state);
819 ctf_set_errno (fp, 0);
820 *statep = NULL;
821 return NULL;
822 }
This page took 0.078162 seconds and 4 git commands to generate.