gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / libctf / ctf-dump.c
CommitLineData
a30b3e18 1/* Textual dumping of CTF data.
b3adc24a 2 Copyright (C) 2019-2020 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;
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
46typedef struct ctf_dump_membstate
47{
48 char **cdm_str;
49 ctf_file_t *cdm_fp;
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
82/* Slices need special handling to distinguish them from their referenced
83 type. */
84
85static int
86ctf_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
a0486bac 93 && ctf_type_encoding (fp, id, enc) == 0);
a30b3e18
NA
94}
95
96/* Return a dump for a single type, without member info: but do show the
97 type's references. */
98
99static char *
b4f0e09c 100ctf_dump_format_type (ctf_file_t *fp, ctf_id_t id, int flag)
a30b3e18
NA
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;
b4f0e09c
NA
109 const char *nonroot_leader = "";
110 const char *nonroot_trailer = "";
a30b3e18
NA
111
112 id = new_id;
b4f0e09c
NA
113 if (flag == CTF_ADD_NONROOT)
114 {
115 nonroot_leader = "{";
116 nonroot_trailer = "}";
117 }
118
a30b3e18
NA
119 buf = ctf_type_aname (fp, id);
120 if (!buf)
791915db
NA
121 {
122 if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE)
123 {
9323dd86 124 str = str_append (str, " (type not represented in CTF)");
791915db
NA
125 ctf_set_errno (fp, ECTF_NOTREF);
126 break;
127 }
128
129 goto err;
130 }
a30b3e18
NA
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);
b4f0e09c
NA
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)
a30b3e18
NA
140 goto oom;
141 }
142 else
143 {
b4f0e09c
NA
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)
a30b3e18
NA
148 goto oom;
149 }
150 free (buf);
151 buf = NULL;
9323dd86 152 str = str_append (str, bit);
a30b3e18
NA
153 free (bit);
154 bit = NULL;
155
156 new_id = ctf_type_reference (fp, id);
157 if (new_id != CTF_ERR)
9323dd86 158 str = str_append (str, " ->");
a30b3e18
NA
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:
791915db
NA
170 ctf_set_errno (fp, errno);
171 err:
a30b3e18
NA
172 free (buf);
173 free (str);
174 free (bit);
a30b3e18
NA
175 return NULL;
176}
177
9b32cba4
NA
178/* Dump one string field from the file header into the cds_items. */
179static int
180ctf_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:
791915db 193 return (ctf_set_errno (fp, errno));
9b32cba4
NA
194}
195
196/* Dump one section-offset field from the file header into the cds_items. */
197static int
198ctf_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:
791915db 213 return (ctf_set_errno (fp, errno));
9b32cba4
NA
214}
215
216/* Dump the file header into the cds_items. */
217static int
218ctf_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:
791915db 301 return (ctf_set_errno (fp, errno));
9b32cba4
NA
302}
303
a30b3e18
NA
304/* Dump a single label into the cds_items. */
305
306static int
307ctf_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)
791915db 315 return (ctf_set_errno (state->cds_fp, errno));
a30b3e18 316
b4f0e09c
NA
317 if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type,
318 CTF_ADD_ROOT)) == NULL)
a30b3e18
NA
319 {
320 free (str);
a0486bac 321 return -1; /* errno is set for us. */
a30b3e18
NA
322 }
323
9323dd86 324 str = str_append (str, typestr);
a30b3e18
NA
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
335static int
336ctf_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
a0486bac 347 if ((type = ctf_lookup_by_symbol (state->cds_fp, i)) == CTF_ERR)
a30b3e18
NA
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:
a0486bac 354 return -1;
a30b3e18
NA
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 {
595a4d43 364 if (asprintf (&str, "%lx -> ", (unsigned long) i) < 0)
791915db 365 return (ctf_set_errno (fp, errno));
a30b3e18
NA
366 }
367 else
368 {
595a4d43 369 if (asprintf (&str, "%s (%lx) -> ", sym_name, (unsigned long) i) < 0)
791915db 370 return (ctf_set_errno (fp, errno));
a30b3e18
NA
371 }
372
373 /* Variable type. */
b4f0e09c
NA
374 if ((typestr = ctf_dump_format_type (state->cds_fp, type,
375 CTF_ADD_ROOT)) == NULL)
a30b3e18
NA
376 {
377 free (str);
a0486bac 378 return -1; /* errno is set for us. */
a30b3e18
NA
379 }
380
9323dd86 381 str = str_append (str, typestr);
a30b3e18
NA
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
392static int
393ctf_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 {
791915db 399 char *str;
a30b3e18 400 char *bit;
791915db 401 const char *err;
a30b3e18
NA
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
a0486bac 408 if ((type = ctf_func_info (state->cds_fp, i, &fi)) == CTF_ERR)
a30b3e18
NA
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:
a0486bac 415 return -1;
a30b3e18 416 case ECTF_NOTDATA:
d18f9f16
NA
417 case ECTF_NOTFUNC:
418 case ECTF_NOFUNCDAT:
a30b3e18
NA
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)
791915db
NA
426 {
427 err = "look up return type";
428 goto err;
429 }
a30b3e18 430
9323dd86 431 str = str_append (str, " ");
a30b3e18
NA
432
433 /* Function name. */
434
435 sym_name = ctf_lookup_symbol_name (fp, i);
436 if (sym_name[0] == '\0')
437 {
c550e7ba 438 if (asprintf (&bit, "0x%lx ", (unsigned long) i) < 0)
a30b3e18
NA
439 goto oom;
440 }
441 else
442 {
c550e7ba 443 if (asprintf (&bit, "%s (0x%lx) ", sym_name, (unsigned long) i) < 0)
a30b3e18
NA
444 goto oom;
445 }
9323dd86
NA
446 str = str_append (str, bit);
447 str = str_append (str, " (");
941accce 448 free (bit);
a30b3e18
NA
449
450 /* Function arguments. */
451
452 if (ctf_func_args (state->cds_fp, i, fi.ctc_argc, args) < 0)
791915db
NA
453 {
454 err = "look up argument type";
455 goto err;
456 }
a30b3e18
NA
457
458 for (j = 0; j < fi.ctc_argc; j++)
459 {
460 if ((bit = ctf_type_aname (state->cds_fp, args[j])) == NULL)
791915db
NA
461 {
462 err = "look up argument type name";
463 goto err;
464 }
9323dd86 465 str = str_append (str, bit);
a30b3e18 466 if ((j < fi.ctc_argc - 1) || (fi.ctc_flags & CTF_FUNC_VARARG))
9323dd86 467 str = str_append (str, ", ");
a30b3e18
NA
468 free (bit);
469 }
470
471 if (fi.ctc_flags & CTF_FUNC_VARARG)
9323dd86
NA
472 str = str_append (str, "...");
473 str = str_append (str, ")");
a30b3e18
NA
474
475 free (args);
476 ctf_dump_append (state, str);
477 continue;
478
479 oom:
480 free (args);
481 free (str);
791915db 482 return (ctf_set_errno (fp, errno));
a30b3e18 483 err:
791915db
NA
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)));
a30b3e18
NA
487 free (args);
488 free (str);
a0486bac 489 return -1; /* errno is set for us. */
a30b3e18
NA
490 }
491 return 0;
492}
493
494/* Dump a single variable into the cds_items. */
495static int
496ctf_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)
791915db 503 return (ctf_set_errno (state->cds_fp, errno));
a30b3e18 504
b4f0e09c
NA
505 if ((typestr = ctf_dump_format_type (state->cds_fp, type,
506 CTF_ADD_ROOT)) == NULL)
a30b3e18
NA
507 {
508 free (str);
a0486bac 509 return -1; /* errno is set for us. */
a30b3e18
NA
510 }
511
9323dd86 512 str = str_append (str, typestr);
a30b3e18
NA
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. */
520static int
521ctf_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++)
9323dd86 531 *state->cdm_str = str_append (*state->cdm_str, " ");
a30b3e18
NA
532
533 if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL)
791915db
NA
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
9323dd86 541 *state->cdm_str = str_append (*state->cdm_str, bit);
791915db
NA
542 free (typestr);
543 free (bit);
544 return 0;
545 }
546
547 goto oom;
548 }
a30b3e18
NA
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,
595a4d43 552 (unsigned long) ctf_type_align (state->cdm_fp, id)) < 0)
a30b3e18 553 goto oom;
9323dd86 554 *state->cdm_str = str_append (*state->cdm_str, bit);
a30b3e18
NA
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;
9323dd86 568 *state->cdm_str = str_append (*state->cdm_str, bit);
a30b3e18
NA
569 free (bit);
570 bit = NULL;
571 }
572
9323dd86 573 *state->cdm_str = str_append (*state->cdm_str, ")\n");
a30b3e18
NA
574 return 0;
575
576 oom:
577 free (typestr);
578 free (bit);
791915db 579 return (ctf_set_errno (state->cdm_fp, errno));
a30b3e18
NA
580}
581
582/* Dump a single type into the cds_items. */
a30b3e18 583static int
b4f0e09c 584ctf_dump_type (ctf_id_t id, int flag, void *arg)
a30b3e18
NA
585{
586 char *str;
791915db 587 const char *err;
a30b3e18
NA
588 ctf_dump_state_t *state = arg;
589 ctf_dump_membstate_t membstate = { &str, state->cds_fp };
590 size_t len;
591
b4f0e09c 592 if ((str = ctf_dump_format_type (state->cds_fp, id, flag)) == NULL)
791915db
NA
593 {
594 err = "format type";
595 goto err;
596 }
a30b3e18 597
9323dd86 598 str = str_append (str, "\n");
a30b3e18 599 if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
791915db
NA
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 }
a30b3e18
NA
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:
791915db
NA
619 ctf_dprintf ("Cannot %s dumping type 0x%lx: %s\n", err, id,
620 ctf_errmsg (ctf_errno (state->cds_fp)));
a30b3e18 621 free (str);
a0486bac 622 return -1; /* errno is set for us. */
a30b3e18
NA
623}
624
625/* Dump the string table into the cds_items. */
626
627static int
628ctf_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;
595a4d43
NA
636 if (asprintf (&str, "%lx: %s",
637 (unsigned long) (s - fp->ctf_str[CTF_STRTAB_0].cts_strs),
a30b3e18 638 s) < 0)
791915db 639 return (ctf_set_errno (fp, errno));
a30b3e18
NA
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
657char *
658ctf_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
de07e349 673 if ((*statep = malloc (sizeof (struct ctf_dump_state))) == NULL)
a30b3e18
NA
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:
9b32cba4 687 ctf_dump_header (fp, state);
a30b3e18
NA
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:
b4f0e09c 710 if (ctf_type_iter_all (fp, ctf_dump_type, state) < 0)
a30b3e18
NA
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);
9323dd86
NA
757 str = str_append (str, ret);
758 str = str_append (str, "\n");
a30b3e18
NA
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
9323dd86
NA
777 {
778 str = strdup (state->cds_current->cdi_item);
779 if (!str)
780 {
781 ctf_set_errno (fp, ENOMEM);
782 return str;
783 }
784 }
a30b3e18
NA
785
786 ctf_set_errno (fp, 0);
787 return str;
788
789 end:
790 ctf_dump_free (state);
de07e349 791 free (state);
a30b3e18
NA
792 ctf_set_errno (fp, 0);
793 *statep = NULL;
794 return NULL;
795}
This page took 0.108772 seconds and 4 git commands to generate.