libctf, binutils, include, ld: gettextize and improve error handling
[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
a30b3e18
NA
82/* Return a dump for a single type, without member info: but do show the
83 type's references. */
84
85static char *
b4f0e09c 86ctf_dump_format_type (ctf_file_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
186ctf_dump_header_strfield (ctf_file_t *fp, ctf_dump_state_t *state,
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
204ctf_dump_header_sectfield (ctf_file_t *fp, ctf_dump_state_t *state,
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
224ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state)
225{
226 char *str;
227 const ctf_header_t *hp = fp->ctf_header;
228 const char *vertab[] =
229 {
230 NULL, "CTF_VERSION_1",
231 "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
232 "boundaries)",
233 "CTF_VERSION_2",
234 "CTF_VERSION_3", NULL
235 };
236 const char *verstr = NULL;
237
238 if (asprintf (&str, "Magic number: %x\n", hp->cth_magic) < 0)
239 goto err;
240 ctf_dump_append (state, str);
241
242 if (hp->cth_version <= CTF_VERSION)
243 verstr = vertab[hp->cth_version];
244
245 if (verstr == NULL)
246 verstr = "(not a valid version)";
247
248 if (asprintf (&str, "Version: %i (%s)\n", hp->cth_version,
249 verstr) < 0)
250 goto err;
251 ctf_dump_append (state, str);
252
253 /* Everything else is only printed if present. */
254
255 /* The flags are unusual in that they represent the ctf_file_t *in memory*:
256 flags representing compression, etc, are turned off as the file is
257 decompressed. So we store a copy of the flags before they are changed, for
258 the dumper. */
259
260 if (fp->ctf_openflags > 0)
261 {
262 if (fp->ctf_openflags)
263 if (asprintf (&str, "Flags: 0x%x (%s)", fp->ctf_openflags,
264 fp->ctf_openflags & CTF_F_COMPRESS ? "CTF_F_COMPRESS"
265 : "") < 0)
266 goto err;
267 ctf_dump_append (state, str);
268 }
269
270 if (ctf_dump_header_strfield (fp, state, "Parent label",
271 hp->cth_parlabel) < 0)
272 goto err;
273
274 if (ctf_dump_header_strfield (fp, state, "Parent name", hp->cth_parname) < 0)
275 goto err;
276
277 if (ctf_dump_header_strfield (fp, state, "Compilation unit name",
278 hp->cth_cuname) < 0)
279 goto err;
280
281 if (ctf_dump_header_sectfield (fp, state, "Label section", hp->cth_lbloff,
282 hp->cth_objtoff) < 0)
283 goto err;
284
285 if (ctf_dump_header_sectfield (fp, state, "Data object section",
286 hp->cth_objtoff, hp->cth_funcoff) < 0)
287 goto err;
288
289 if (ctf_dump_header_sectfield (fp, state, "Function info section",
290 hp->cth_funcoff, hp->cth_varoff) < 0)
291 goto err;
292
293 if (ctf_dump_header_sectfield (fp, state, "Variable section",
294 hp->cth_varoff, hp->cth_typeoff) < 0)
295 goto err;
296
297 if (ctf_dump_header_sectfield (fp, state, "Type section",
298 hp->cth_typeoff, hp->cth_stroff) < 0)
299 goto err;
300
301 if (ctf_dump_header_sectfield (fp, state, "String section", hp->cth_stroff,
302 hp->cth_stroff + hp->cth_strlen + 1) < 0)
303 goto err;
304
305 return 0;
306 err:
791915db 307 return (ctf_set_errno (fp, errno));
9b32cba4
NA
308}
309
a30b3e18
NA
310/* Dump a single label into the cds_items. */
311
312static int
313ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
314 void *arg)
315{
316 char *str;
317 char *typestr;
318 ctf_dump_state_t *state = arg;
319
320 if (asprintf (&str, "%s -> ", name) < 0)
791915db 321 return (ctf_set_errno (state->cds_fp, errno));
a30b3e18 322
b4f0e09c
NA
323 if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type,
324 CTF_ADD_ROOT)) == NULL)
a30b3e18
NA
325 {
326 free (str);
8e795b46 327 return 0; /* Swallow the error. */
a30b3e18
NA
328 }
329
9323dd86 330 str = str_append (str, typestr);
a30b3e18
NA
331 free (typestr);
332
333 ctf_dump_append (state, str);
334 return 0;
335}
336
337/* Dump all the object entries into the cds_items. (There is no iterator for
338 this section, so we just do it in a loop, and this function handles all of
339 them, rather than only one. */
340
341static int
342ctf_dump_objts (ctf_file_t *fp, ctf_dump_state_t *state)
343{
344 size_t i;
345
346 for (i = 0; i < fp->ctf_nsyms; i++)
347 {
348 char *str;
349 char *typestr;
350 const char *sym_name;
351 ctf_id_t type;
352
a0486bac 353 if ((type = ctf_lookup_by_symbol (state->cds_fp, i)) == CTF_ERR)
a30b3e18
NA
354 switch (ctf_errno (state->cds_fp))
355 {
356 /* Most errors are just an indication that this symbol is not a data
357 symbol, but this one indicates that we were called wrong, on a
358 CTF file with no associated symbol table. */
359 case ECTF_NOSYMTAB:
a0486bac 360 return -1;
a30b3e18
NA
361 case ECTF_NOTDATA:
362 case ECTF_NOTYPEDAT:
363 continue;
364 }
365
366 /* Variable name. */
367 sym_name = ctf_lookup_symbol_name (fp, i);
368 if (sym_name[0] == '\0')
369 {
595a4d43 370 if (asprintf (&str, "%lx -> ", (unsigned long) i) < 0)
791915db 371 return (ctf_set_errno (fp, errno));
a30b3e18
NA
372 }
373 else
374 {
595a4d43 375 if (asprintf (&str, "%s (%lx) -> ", sym_name, (unsigned long) i) < 0)
791915db 376 return (ctf_set_errno (fp, errno));
a30b3e18
NA
377 }
378
379 /* Variable type. */
b4f0e09c
NA
380 if ((typestr = ctf_dump_format_type (state->cds_fp, type,
381 CTF_ADD_ROOT)) == NULL)
a30b3e18
NA
382 {
383 free (str);
8e795b46 384 return 0; /* Swallow the error. */
a30b3e18
NA
385 }
386
9323dd86 387 str = str_append (str, typestr);
a30b3e18
NA
388 free (typestr);
389
390 ctf_dump_append (state, str);
391 }
392 return 0;
393}
394
395/* Dump all the function entries into the cds_items. (As above, there is no
396 iterator for this section.) */
397
398static int
399ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
400{
401 size_t i;
402
403 for (i = 0; i < fp->ctf_nsyms; i++)
404 {
791915db 405 char *str;
c6e9a1e5 406 char *bit = NULL;
a30b3e18
NA
407 const char *sym_name;
408 ctf_funcinfo_t fi;
409 ctf_id_t type;
a30b3e18 410
a0486bac 411 if ((type = ctf_func_info (state->cds_fp, i, &fi)) == CTF_ERR)
a30b3e18
NA
412 switch (ctf_errno (state->cds_fp))
413 {
414 /* Most errors are just an indication that this symbol is not a data
415 symbol, but this one indicates that we were called wrong, on a
416 CTF file with no associated symbol table. */
417 case ECTF_NOSYMTAB:
a0486bac 418 return -1;
a30b3e18 419 case ECTF_NOTDATA:
d18f9f16
NA
420 case ECTF_NOTFUNC:
421 case ECTF_NOFUNCDAT:
a30b3e18
NA
422 continue;
423 }
a30b3e18 424
c6e9a1e5
NA
425 /* Return type and all args. */
426 if ((bit = ctf_type_aname (state->cds_fp, type)) == NULL)
791915db 427 {
926c9e76
NA
428 ctf_err_warn (fp, 1, ctf_errno (state->cds_fp),
429 _("cannot look up return type dumping function type "
430 "for symbol 0x%li"), (unsigned long) i);
431 free (bit);
432 return -1; /* errno is set for us. */
791915db 433 }
a30b3e18 434
c6e9a1e5 435 /* Replace in the returned string, dropping in the function name. */
a30b3e18
NA
436
437 sym_name = ctf_lookup_symbol_name (fp, i);
c6e9a1e5 438 if (sym_name[0] != '\0')
a30b3e18 439 {
c6e9a1e5
NA
440 char *retstar;
441 char *new_bit;
442 char *walk;
443
444 new_bit = malloc (strlen (bit) + 1 + strlen (sym_name));
445 if (!new_bit)
a30b3e18 446 goto oom;
a30b3e18 447
c6e9a1e5
NA
448 /* See ctf_type_aname. */
449 retstar = strstr (bit, "(*) (");
450 if (!ctf_assert (fp, retstar))
451 goto assert_err;
452 retstar += 2; /* After the '*' */
a30b3e18 453
c6e9a1e5
NA
454 /* C is not good at search-and-replace. */
455 walk = new_bit;
456 memcpy (walk, bit, retstar - bit);
457 walk += (retstar - bit);
458 strcpy (walk, sym_name);
459 walk += strlen (sym_name);
460 strcpy (walk, retstar);
a30b3e18 461
a30b3e18 462 free (bit);
c6e9a1e5 463 bit = new_bit;
a30b3e18
NA
464 }
465
c6e9a1e5
NA
466 if (asprintf (&str, "Symbol 0x%lx: %s", (unsigned long) i, bit) < 0)
467 goto oom;
468 free (bit);
a30b3e18 469
a30b3e18
NA
470 ctf_dump_append (state, str);
471 continue;
472
473 oom:
c6e9a1e5 474 free (bit);
791915db 475 return (ctf_set_errno (fp, errno));
c6e9a1e5
NA
476
477 assert_err:
478 free (bit);
a0486bac 479 return -1; /* errno is set for us. */
a30b3e18
NA
480 }
481 return 0;
482}
483
484/* Dump a single variable into the cds_items. */
485static int
486ctf_dump_var (const char *name, ctf_id_t type, void *arg)
487{
488 char *str;
489 char *typestr;
490 ctf_dump_state_t *state = arg;
491
492 if (asprintf (&str, "%s -> ", name) < 0)
791915db 493 return (ctf_set_errno (state->cds_fp, errno));
a30b3e18 494
b4f0e09c
NA
495 if ((typestr = ctf_dump_format_type (state->cds_fp, type,
496 CTF_ADD_ROOT)) == NULL)
a30b3e18
NA
497 {
498 free (str);
8e795b46 499 return 0; /* Swallow the error. */
a30b3e18
NA
500 }
501
9323dd86 502 str = str_append (str, typestr);
a30b3e18
NA
503 free (typestr);
504
505 ctf_dump_append (state, str);
506 return 0;
507}
508
509/* Dump a single member into the string in the membstate. */
510static int
511ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
512 int depth, void *arg)
513{
514 ctf_dump_membstate_t *state = arg;
515 char *typestr = NULL;
516 char *bit = NULL;
517 ctf_encoding_t ep;
70447401 518 int has_encoding = 0;
a30b3e18
NA
519 ssize_t i;
520
521 for (i = 0; i < depth; i++)
9323dd86 522 *state->cdm_str = str_append (*state->cdm_str, " ");
a30b3e18
NA
523
524 if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL)
791915db
NA
525 {
526 if (id == 0 || ctf_errno (state->cdm_fp) == ECTF_NONREPRESENTABLE)
527 {
528 if (asprintf (&bit, " [0x%lx] (type not represented in CTF)",
529 offset) < 0)
530 goto oom;
531
9323dd86 532 *state->cdm_str = str_append (*state->cdm_str, bit);
791915db
NA
533 free (typestr);
534 free (bit);
535 return 0;
536 }
537
70447401
NA
538 return -1; /* errno is set for us. */
539 }
540
541 if (ctf_type_encoding (state->cdm_fp, id, &ep) == 0)
542 {
543 has_encoding = 1;
544 ctf_type_encoding (state->cdm_fp, id, &ep);
545
546 if (asprintf (&bit, " [0x%lx] (ID 0x%lx) (kind %i) %s%s%s:%i "
547 "(aligned at 0x%lx", offset, id,
548 ctf_type_kind (state->cdm_fp, id), typestr,
549 (name[0] != 0 && typestr[0] != 0) ? " " : "", name,
550 ep.cte_bits, (unsigned long) ctf_type_align (state->cdm_fp,
551 id)) < 0)
552 goto oom;
553 }
554 else
555 {
556 if (asprintf (&bit, " [0x%lx] (ID 0x%lx) (kind %i) %s%s%s "
557 "(aligned at 0x%lx", offset, id,
558 ctf_type_kind (state->cdm_fp, id), typestr,
559 (name[0] != 0 && typestr[0] != 0) ? " " : "", name,
560 (unsigned long) ctf_type_align (state->cdm_fp, id)) < 0)
561 goto oom;
791915db 562 }
a30b3e18 563
9323dd86 564 *state->cdm_str = str_append (*state->cdm_str, bit);
a30b3e18
NA
565 free (typestr);
566 free (bit);
567 typestr = NULL;
568 bit = NULL;
569
70447401 570 if (has_encoding)
a30b3e18 571 {
a30b3e18
NA
572 if (asprintf (&bit, ", format 0x%x, offset:bits 0x%x:0x%x", ep.cte_format,
573 ep.cte_offset, ep.cte_bits) < 0)
574 goto oom;
9323dd86 575 *state->cdm_str = str_append (*state->cdm_str, bit);
a30b3e18
NA
576 free (bit);
577 bit = NULL;
578 }
579
9323dd86 580 *state->cdm_str = str_append (*state->cdm_str, ")\n");
a30b3e18
NA
581 return 0;
582
583 oom:
584 free (typestr);
585 free (bit);
791915db 586 return (ctf_set_errno (state->cdm_fp, errno));
a30b3e18
NA
587}
588
589/* Dump a single type into the cds_items. */
a30b3e18 590static int
b4f0e09c 591ctf_dump_type (ctf_id_t id, int flag, void *arg)
a30b3e18
NA
592{
593 char *str;
594 ctf_dump_state_t *state = arg;
595 ctf_dump_membstate_t membstate = { &str, state->cds_fp };
596 size_t len;
597
b4f0e09c 598 if ((str = ctf_dump_format_type (state->cds_fp, id, flag)) == NULL)
926c9e76 599 goto err;
a30b3e18 600
9323dd86 601 str = str_append (str, "\n");
a30b3e18 602 if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
791915db
NA
603 {
604 if (id == 0 || ctf_errno (state->cds_fp) == ECTF_NONREPRESENTABLE)
605 {
606 ctf_dump_append (state, str);
607 return 0;
608 }
926c9e76
NA
609 ctf_err_warn (state->cds_fp, 1, ctf_errno (state->cds_fp),
610 _("cannot visit members dumping type 0x%lx"), id);
791915db
NA
611 goto err;
612 }
a30b3e18
NA
613
614 /* Trim off the last linefeed added by ctf_dump_member(). */
615 len = strlen (str);
616 if (str[len-1] == '\n')
617 str[len-1] = '\0';
618
619 ctf_dump_append (state, str);
620 return 0;
621
622 err:
623 free (str);
8e795b46 624 return 0; /* Swallow the error. */
a30b3e18
NA
625}
626
627/* Dump the string table into the cds_items. */
628
629static int
630ctf_dump_str (ctf_file_t *fp, ctf_dump_state_t *state)
631{
632 const char *s = fp->ctf_str[CTF_STRTAB_0].cts_strs;
633
634 for (; s < fp->ctf_str[CTF_STRTAB_0].cts_strs +
635 fp->ctf_str[CTF_STRTAB_0].cts_len;)
636 {
637 char *str;
595a4d43
NA
638 if (asprintf (&str, "%lx: %s",
639 (unsigned long) (s - fp->ctf_str[CTF_STRTAB_0].cts_strs),
a30b3e18 640 s) < 0)
791915db 641 return (ctf_set_errno (fp, errno));
a30b3e18
NA
642 ctf_dump_append (state, str);
643 s += strlen (s) + 1;
644 }
645
646 return 0;
647}
648
649/* Dump a particular section of a CTF file, in textual form. Call with a
650 pointer to a NULL STATE: each call emits a dynamically allocated string
651 containing a description of one entity in the specified section, in order.
652 Only the first call (with a NULL state) may vary SECT. Once the CTF section
653 has been entirely dumped, the call returns NULL and frees and annuls the
654 STATE, ready for another section to be dumped. The returned textual content
655 may span multiple lines: between each call the FUNC is called with one
656 textual line at a time, and should return a suitably decorated line (it can
657 allocate a new one and return it if it likes). */
658
659char *
660ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect,
661 ctf_dump_decorate_f *func, void *arg)
662{
663 char *str;
664 char *line;
665 ctf_dump_state_t *state = NULL;
666
667 if (*statep == NULL)
668 {
669 /* Data collection. Transforming a call-at-a-time iterator into a
670 return-at-a-time iterator in a language without call/cc is annoying. It
671 is easiest to simply collect everything at once and then return it bit
672 by bit. The first call will take (much) longer than otherwise, but the
673 amortized time needed is the same. */
674
de07e349 675 if ((*statep = malloc (sizeof (struct ctf_dump_state))) == NULL)
a30b3e18
NA
676 {
677 ctf_set_errno (fp, ENOMEM);
678 goto end;
679 }
680 state = *statep;
681
682 memset (state, 0, sizeof (struct ctf_dump_state));
683 state->cds_fp = fp;
684 state->cds_sect = sect;
685
686 switch (sect)
687 {
688 case CTF_SECT_HEADER:
9b32cba4 689 ctf_dump_header (fp, state);
a30b3e18
NA
690 break;
691 case CTF_SECT_LABEL:
692 if (ctf_label_iter (fp, ctf_dump_label, state) < 0)
693 {
694 if (ctf_errno (fp) != ECTF_NOLABELDATA)
695 goto end; /* errno is set for us. */
696 ctf_set_errno (fp, 0);
697 }
698 break;
699 case CTF_SECT_OBJT:
700 if (ctf_dump_objts (fp, state) < 0)
701 goto end; /* errno is set for us. */
702 break;
703 case CTF_SECT_FUNC:
704 if (ctf_dump_funcs (fp, state) < 0)
705 goto end; /* errno is set for us. */
706 break;
707 case CTF_SECT_VAR:
708 if (ctf_variable_iter (fp, ctf_dump_var, state) < 0)
709 goto end; /* errno is set for us. */
710 break;
711 case CTF_SECT_TYPE:
b4f0e09c 712 if (ctf_type_iter_all (fp, ctf_dump_type, state) < 0)
a30b3e18
NA
713 goto end; /* errno is set for us. */
714 break;
715 case CTF_SECT_STR:
716 ctf_dump_str (fp, state);
717 break;
718 default:
719 ctf_set_errno (fp, ECTF_DUMPSECTUNKNOWN);
720 goto end;
721 }
722 }
723 else
724 {
725 state = *statep;
726
727 if (state->cds_sect != sect)
728 {
729 ctf_set_errno (fp, ECTF_DUMPSECTCHANGED);
730 goto end;
731 }
732 }
733
734 if (state->cds_current == NULL)
735 state->cds_current = ctf_list_next (&state->cds_items);
736 else
737 state->cds_current = ctf_list_next (state->cds_current);
738
739 if (state->cds_current == NULL)
740 goto end;
741
742 /* Hookery. There is some extra complexity to preserve linefeeds within each
743 item while removing linefeeds at the end. */
744 if (func)
745 {
746 size_t len;
747
748 str = NULL;
749 for (line = state->cds_current->cdi_item; line && *line; )
750 {
751 char *nline = line;
752 char *ret;
753
754 nline = strchr (line, '\n');
755 if (nline)
756 nline[0] = '\0';
757
758 ret = func (sect, line, arg);
9323dd86
NA
759 str = str_append (str, ret);
760 str = str_append (str, "\n");
a30b3e18
NA
761 if (ret != line)
762 free (ret);
763
764 if (nline)
765 {
766 nline[0] = '\n';
767 nline++;
768 }
769
770 line = nline;
771 }
772
773 len = strlen (str);
774
775 if (str[len-1] == '\n')
776 str[len-1] = '\0';
777 }
778 else
9323dd86
NA
779 {
780 str = strdup (state->cds_current->cdi_item);
781 if (!str)
782 {
783 ctf_set_errno (fp, ENOMEM);
784 return str;
785 }
786 }
a30b3e18
NA
787
788 ctf_set_errno (fp, 0);
789 return str;
790
791 end:
792 ctf_dump_free (state);
de07e349 793 free (state);
a30b3e18
NA
794 ctf_set_errno (fp, 0);
795 *statep = NULL;
796 return NULL;
797}
This page took 0.122604 seconds and 4 git commands to generate.