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