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