Prep 1.29
[dwarves.git] / dwarves_fprintf.c
blobc3e7f3c0c81d6d1d2a33da2e6ee0b69a36cf8d74
1 /*
2 SPDX-License-Identifier: GPL-2.0-only
4 Copyright (C) 2006 Mandriva Conectiva S.A.
5 Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
6 Copyright (C) 2007..2009 Red Hat Inc.
7 Copyright (C) 2007..2009 Arnaldo Carvalho de Melo <acme@redhat.com>
8 */
10 #include <dwarf.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <inttypes.h>
17 #include <elfutils/version.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
22 #include "config.h"
23 #include "dwarves.h"
25 static const char *dwarf_tag_names[] = {
26 [DW_TAG_array_type] = "array_type",
27 [DW_TAG_class_type] = "class_type",
28 [DW_TAG_entry_point] = "entry_point",
29 [DW_TAG_enumeration_type] = "enumeration_type",
30 [DW_TAG_formal_parameter] = "formal_parameter",
31 [DW_TAG_imported_declaration] = "imported_declaration",
32 [DW_TAG_label] = "label",
33 [DW_TAG_lexical_block] = "lexical_block",
34 [DW_TAG_member] = "member",
35 [DW_TAG_pointer_type] = "pointer_type",
36 [DW_TAG_reference_type] = "reference_type",
37 [DW_TAG_compile_unit] = "compile_unit",
38 [DW_TAG_string_type] = "string_type",
39 [DW_TAG_structure_type] = "structure_type",
40 [DW_TAG_subroutine_type] = "subroutine_type",
41 [DW_TAG_typedef] = "typedef",
42 [DW_TAG_union_type] = "union_type",
43 [DW_TAG_unspecified_parameters] = "unspecified_parameters",
44 [DW_TAG_variant] = "variant",
45 [DW_TAG_common_block] = "common_block",
46 [DW_TAG_common_inclusion] = "common_inclusion",
47 [DW_TAG_inheritance] = "inheritance",
48 [DW_TAG_inlined_subroutine] = "inlined_subroutine",
49 [DW_TAG_module] = "module",
50 [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
51 [DW_TAG_set_type] = "set_type",
52 [DW_TAG_subrange_type] = "subrange_type",
53 [DW_TAG_with_stmt] = "with_stmt",
54 [DW_TAG_access_declaration] = "access_declaration",
55 [DW_TAG_base_type] = "base_type",
56 [DW_TAG_catch_block] = "catch_block",
57 [DW_TAG_const_type] = "const_type",
58 [DW_TAG_constant] = "constant",
59 [DW_TAG_enumerator] = "enumerator",
60 [DW_TAG_file_type] = "file_type",
61 [DW_TAG_friend] = "friend",
62 [DW_TAG_namelist] = "namelist",
63 [DW_TAG_namelist_item] = "namelist_item",
64 [DW_TAG_packed_type] = "packed_type",
65 [DW_TAG_subprogram] = "subprogram",
66 [DW_TAG_template_type_parameter] = "template_type_parameter",
67 [DW_TAG_template_value_parameter] = "template_value_parameter",
68 [DW_TAG_thrown_type] = "thrown_type",
69 [DW_TAG_try_block] = "try_block",
70 [DW_TAG_variant_part] = "variant_part",
71 [DW_TAG_variable] = "variable",
72 [DW_TAG_volatile_type] = "volatile_type",
73 [DW_TAG_dwarf_procedure] = "dwarf_procedure",
74 [DW_TAG_restrict_type] = "restrict_type",
75 [DW_TAG_interface_type] = "interface_type",
76 [DW_TAG_namespace] = "namespace",
77 [DW_TAG_imported_module] = "imported_module",
78 [DW_TAG_unspecified_type] = "unspecified_type",
79 [DW_TAG_partial_unit] = "partial_unit",
80 [DW_TAG_imported_unit] = "imported_unit",
81 [DW_TAG_condition] = "condition",
82 [DW_TAG_shared_type] = "shared_type",
83 #ifdef STB_GNU_UNIQUE
84 [DW_TAG_type_unit] = "type_unit",
85 [DW_TAG_rvalue_reference_type] = "rvalue_reference_type",
86 #endif
87 #if _ELFUTILS_PREREQ(0, 170)
88 [DW_TAG_coarray_type] = "coarray_type",
89 [DW_TAG_generic_subrange] = "generic_subrange",
90 [DW_TAG_dynamic_type] = "dynamic_type",
91 [DW_TAG_call_site] = "call_site",
92 [DW_TAG_call_site_parameter] = "call_site_parameter",
93 [DW_TAG_skeleton_unit] = "skeleton_unit",
94 [DW_TAG_immutable_type] = "immutable_type",
95 #endif
96 [DW_TAG_atomic_type] = "atomic_type",
99 static const char *dwarf_gnu_tag_names[] = {
100 [DW_TAG_MIPS_loop - DW_TAG_MIPS_loop] = "MIPS_loop",
101 [DW_TAG_format_label - DW_TAG_MIPS_loop] = "format_label",
102 [DW_TAG_function_template - DW_TAG_MIPS_loop] = "function_template",
103 [DW_TAG_class_template - DW_TAG_MIPS_loop] = "class_template",
104 #ifdef STB_GNU_UNIQUE
105 [DW_TAG_GNU_BINCL - DW_TAG_MIPS_loop] = "GNU_BINCL",
106 [DW_TAG_GNU_EINCL - DW_TAG_MIPS_loop] = "GNU_EINCL",
107 [DW_TAG_GNU_template_template_param - DW_TAG_MIPS_loop] = "GNU_template_template_param",
108 [DW_TAG_GNU_template_parameter_pack - DW_TAG_MIPS_loop] = "GNU_template_parameter_pack",
109 [DW_TAG_GNU_formal_parameter_pack - DW_TAG_MIPS_loop] = "GNU_formal_parameter_pack",
110 #endif
111 #if _ELFUTILS_PREREQ(0, 153)
112 [DW_TAG_GNU_call_site - DW_TAG_MIPS_loop] = "GNU_call_site",
113 [DW_TAG_GNU_call_site_parameter - DW_TAG_MIPS_loop] = "GNU_call_site_parameter",
114 #endif
117 const char *dwarf_tag_name(const uint32_t tag)
119 if (tag >= DW_TAG_array_type && tag <=
120 #if _ELFUTILS_PREREQ(0, 170)
121 DW_TAG_immutable_type
122 #else
123 #ifdef STB_GNU_UNIQUE
124 DW_TAG_rvalue_reference_type
125 #else
126 DW_TAG_shared_type
127 #endif
128 #endif
130 return dwarf_tag_names[tag];
131 else if (tag >= DW_TAG_MIPS_loop && tag <=
132 #if _ELFUTILS_PREREQ(0, 153)
133 DW_TAG_GNU_call_site_parameter
134 #elif STB_GNU_UNIQUE
135 DW_TAG_GNU_formal_parameter_pack
136 #else
137 DW_TAG_class_template
138 #endif
140 return dwarf_gnu_tag_names[tag - DW_TAG_MIPS_loop];
141 else if (tag == DW_TAG_LLVM_annotation)
142 return "LLVM_annotation";
143 return "INVALID";
146 static struct conf_fprintf conf_fprintf__defaults = {
147 .name_spacing = 23,
148 .type_spacing = 26,
149 .emit_stats = 1,
152 const char tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
154 static size_t union__fprintf(struct type *type, const struct cu *cu,
155 const struct conf_fprintf *conf, FILE *fp);
158 * In dwarves_emit.c we can call type__emit() using a locally setup conf_fprintf for which
159 * the conf->cacheline_size member is not setup and is thus zero, so check for that and
160 * use the default one for that case.
162 * We really need to make the *_emit*() methods to receive a conf_fprintf pointer for
163 * which conf->cacheline_size is set, all tools call:
165 * dwarves__resolve_cacheline_size(&conf_load, 0);
167 * To have a conf_load/conf_fprintf with that resolved, but that is not being passed to
168 * the *_emit*() routines, duh.
170 * Fixing this properly will entail a series of patches, so to fix this problem
171 * more quickly add this helper.
173 static uint16_t conf_fprintf__cacheline_size(const struct conf_fprintf *conf)
175 return conf->cacheline_size ?: conf_fprintf__defaults.cacheline_size;
178 size_t tag__nr_cachelines(const struct conf_fprintf *conf, const struct tag *tag, const struct cu *cu)
180 return (tag__size(tag, cu) + conf_fprintf__cacheline_size(conf) - 1) / conf_fprintf__cacheline_size(conf);
183 static const char *tag__accessibility(const struct tag *tag)
185 int a;
187 switch (tag->tag) {
188 case DW_TAG_inheritance:
189 case DW_TAG_member:
190 a = tag__class_member(tag)->accessibility;
191 break;
192 case DW_TAG_subprogram:
193 a = tag__function(tag)->accessibility;
194 break;
195 default:
196 return NULL;
199 switch (a) {
200 case DW_ACCESS_public: return "public";
201 case DW_ACCESS_private: return "private";
202 case DW_ACCESS_protected: return "protected";
205 return NULL;
208 static size_t __tag__id_not_found_snprintf(char *bf, size_t len, uint32_t id,
209 const char *fn, int line)
211 return snprintf(bf, len, "<ERROR(%s:%d): %#llx not found!>", fn, line,
212 (unsigned long long)id);
215 #define tag__id_not_found_snprintf(bf, len, id) \
216 __tag__id_not_found_snprintf(bf, len, id, __func__, __LINE__)
218 size_t tag__fprintf_decl_info(const struct tag *tag,
219 const struct cu *cu, FILE *fp)
221 return fprintf(fp, "/* <%llx> %s:%u */\n", tag__orig_id(tag, cu),
222 tag__decl_file(tag, cu), tag__decl_line(tag, cu));
223 return 0;
226 static size_t __class__fprintf(struct class *class, const struct cu *cu,
227 const struct conf_fprintf *conf, FILE *fp);
228 static size_t type__fprintf(struct tag *type, const struct cu *cu,
229 const char *name, const struct conf_fprintf *conf,
230 FILE *fp);
232 static size_t array_type__fprintf(const struct tag *tag,
233 const struct cu *cu, const char *name,
234 const struct conf_fprintf *conf,
235 FILE *fp)
237 struct array_type *at = tag__array_type(tag);
238 struct tag *type = cu__type(cu, tag->type);
239 size_t printed;
240 unsigned long long flat_dimensions = 0;
241 int i;
243 if (type == NULL)
244 return tag__id_not_found_fprintf(fp, tag->type);
246 /* Zero sized arrays? */
247 if (at->dimensions >= 1 && at->nr_entries[0] == 0 && tag__is_const(type))
248 type = cu__type(cu, type->type);
250 printed = type__fprintf(type, cu, name, conf, fp);
251 for (i = 0; i < at->dimensions; ++i) {
252 if (conf->flat_arrays || at->is_vector) {
254 * Seen on the Linux kernel on tun_filter:
256 * __u8 addr[0][ETH_ALEN];
258 if (at->nr_entries[i] == 0 && i == 0)
259 break;
260 if (!flat_dimensions)
261 flat_dimensions = at->nr_entries[i];
262 else
263 flat_dimensions *= at->nr_entries[i];
264 } else {
265 bool single_member = conf->last_member && conf->first_member;
267 if (at->nr_entries[i] != 0 || !conf->last_member || single_member || conf->union_member)
268 printed += fprintf(fp, "[%u]", at->nr_entries[i]);
269 else
270 printed += fprintf(fp, "[]");
274 if (at->is_vector) {
275 type = tag__follow_typedef(tag, cu);
277 if (flat_dimensions == 0)
278 flat_dimensions = 1;
279 printed += fprintf(fp, " __attribute__ ((__vector_size__ (%llu)))",
280 flat_dimensions * tag__size(type, cu));
281 } else if (conf->flat_arrays) {
282 bool single_member = conf->last_member && conf->first_member;
284 if (flat_dimensions != 0 || !conf->last_member || single_member || conf->union_member)
285 printed += fprintf(fp, "[%llu]", flat_dimensions);
286 else
287 printed += fprintf(fp, "[]");
290 return printed;
293 static size_t string_type__fprintf(const struct tag *tag, const char *name,
294 const struct conf_fprintf *conf,
295 FILE *fp)
297 struct string_type *st = tag__string_type(tag);
299 return fprintf(fp, "string %*s[%u]", conf->type_spacing - 5, name, st->nr_entries);
303 * Here we're printing either:
305 * union bar baz;
307 * I.e. a variable or a class member, or:
309 * union {
310 * u32 a;
311 * u16 b;
312 * } baz;
314 * I.e. a "inline" union, with or without that 'baz' name (unnamed union member),
315 * or we are expanding unions, i.e. using 'pahole -E/--expand_types'.
317 static size_t union_decl__fprintf(const struct tag *type, const struct cu *cu, const char *name,
318 const struct conf_fprintf *conf, FILE *fp)
320 struct type *ctype = tag__type(type);
322 if (type__name(ctype) != NULL && !conf->expand_types)
323 return fprintf(fp, "union %-*s %s", conf->type_spacing - 6, type__name(ctype), name ?: "");
325 struct conf_fprintf tconf = *conf;
326 tconf.type_spacing -= 8;
327 tconf.suffix = name;
329 return union__fprintf(ctype, cu, &tconf, fp);
332 size_t typedef__fprintf(const struct tag *tag, const struct cu *cu,
333 const struct conf_fprintf *conf, FILE *fp)
335 struct type *type = tag__type(tag);
336 const struct conf_fprintf *pconf = conf ?: &conf_fprintf__defaults;
337 const struct tag *tag_type;
338 const struct tag *ptr_type;
339 char bf[512];
340 int is_pointer = 0;
341 size_t printed = fprintf(fp, "typedef ");
344 * Check for void (humm, perhaps we should have a fake void tag instance
345 * to avoid all these checks?
347 if (tag->type == 0)
348 return printed + fprintf(fp, "void %s", type__name(type));
349 next_type:
350 tag_type = cu__type(cu, tag->type);
351 if (tag_type == NULL) {
352 printed += tag__id_not_found_fprintf(fp, tag->type);
353 return printed + fprintf(fp, " %s", type__name(type));
356 switch (tag_type->tag) {
357 case DW_TAG_atomic_type:
358 printed += fprintf(fp, "_Atomic ");
359 tag = tag_type;
360 goto next_type;
361 case DW_TAG_array_type:
362 return printed + array_type__fprintf(tag_type, cu, type__name(type), pconf, fp);
363 case DW_TAG_pointer_type:
364 if (tag_type->type == 0) /* void pointer */
365 break;
366 ptr_type = cu__type(cu, tag_type->type);
367 if (ptr_type == NULL) {
368 printed += tag__id_not_found_fprintf(fp, tag_type->type);
369 return printed + fprintf(fp, " *%s", type__name(type));
371 if (ptr_type->tag != DW_TAG_subroutine_type)
372 break;
373 tag_type = ptr_type;
374 is_pointer = 1;
375 /* Fall thru */
376 case DW_TAG_subroutine_type:
377 return printed + ftype__fprintf(tag__ftype(tag_type), cu, type__name(type),
378 0, is_pointer, 0, true, pconf, fp);
379 case DW_TAG_class_type:
380 case DW_TAG_structure_type: {
381 struct type *ctype = tag__type(tag_type);
383 if (type__name(ctype) != NULL && !pconf->expand_types)
384 return printed + fprintf(fp, "struct %s %s", type__name(ctype), type__name(type));
386 struct conf_fprintf tconf = *pconf;
387 struct class *cclass = tag__class(tag_type);
389 if (!tconf.suppress_comments)
390 class__find_holes(cclass);
392 tconf.type_spacing -= 8;
393 tconf.suffix = type__name(type);
394 return printed + __class__fprintf(cclass, cu, &tconf, fp);
396 case DW_TAG_union_type:
397 return printed + union_decl__fprintf(tag_type, cu, type__name(type), pconf, fp);
398 case DW_TAG_enumeration_type: {
399 struct type *ctype = tag__type(tag_type);
401 if (type__name(ctype) != NULL)
402 return printed + fprintf(fp, "enum %s %s", type__name(ctype), type__name(type));
404 struct conf_fprintf tconf = *pconf;
406 tconf.suffix = type__name(type);
407 return printed + enumeration__fprintf(tag_type, &tconf, fp);
411 return printed + fprintf(fp, "%s %s",
412 tag__name(tag_type, cu, bf, sizeof(bf), pconf), type__name(type));
415 static size_t imported_declaration__fprintf(const struct tag *tag,
416 const struct cu *cu, FILE *fp)
418 char bf[BUFSIZ];
419 size_t printed = fprintf(fp, "using ::");
420 const struct tag *decl = cu__function(cu, tag->type);
422 if (decl == NULL) {
423 decl = cu__tag(cu, tag->type);
424 if (decl == NULL)
425 return printed + tag__id_not_found_fprintf(fp, tag->type);
428 return printed + fprintf(fp, "%s", tag__name(decl, cu, bf, sizeof(bf), NULL));
431 static size_t imported_module__fprintf(const struct tag *tag,
432 const struct cu *cu, FILE *fp)
434 const struct tag *module = cu__tag(cu, tag->type);
435 const char *name = "<IMPORTED MODULE ERROR!>";
437 if (tag__is_namespace(module))
438 name = namespace__name(tag__namespace(module));
440 return fprintf(fp, "using namespace %s", name);
443 static int enumeration__max_entry_name_len(struct type *type)
445 if (type->max_tag_name_len)
446 goto out;
448 struct enumerator *pos;
450 type__for_each_enumerator(type, pos) {
451 int len = strlen(enumerator__name(pos));
453 if (type->max_tag_name_len < len)
454 type->max_tag_name_len = len;
456 out:
457 return type->max_tag_name_len;
460 size_t enumeration__fprintf(const struct tag *tag, const struct conf_fprintf *conf, FILE *fp)
462 struct type *type = tag__type(tag);
463 struct enumerator *pos;
464 int max_entry_name_len = enumeration__max_entry_name_len(type);
465 size_t printed = fprintf(fp, "enum%s%s", type__name(type) ? " " : "", type__name(type) ?: "");
466 int indent = conf->indent;
468 if (indent >= (int)sizeof(tabs))
469 indent = sizeof(tabs) - 1;
471 if (type->nr_members) {
472 printed += fprintf(fp, " {\n");
473 } else {
474 // enum x86_intercept_stage in the Linux kernel comes just as a forward
475 // declaration, but then BTF isn't setting the type->declaration to mark
476 // it as such, do the best we can and assume is a forward decl.
477 return printed;
480 type__for_each_enumerator(type, pos) {
481 printed += fprintf(fp, "%.*s\t%-*s = ", indent, tabs,
482 max_entry_name_len, enumerator__name(pos));
483 if (conf->hex_fmt)
484 printed += fprintf(fp, "%#llx", (unsigned long long)pos->value);
485 else
486 printed += fprintf(fp, type->is_signed_enum ? "%lld" : "%llu",
487 (unsigned long long)pos->value);
488 printed += fprintf(fp, ",\n");
491 printed += fprintf(fp, "%.*s}", indent, tabs);
494 * XXX: find out how to precisely determine the max size for an
495 * enumeration, use sizeof(int) for now.
497 if (type->size / 8 != sizeof(int))
498 printed += fprintf(fp, " %s", "__attribute__((__packed__))");
500 if (conf->suffix)
501 printed += fprintf(fp, " %s", conf->suffix);
503 return printed;
506 static const char *tag__prefix(const struct cu *cu, const uint32_t tag,
507 const struct conf_fprintf *conf)
509 switch (tag) {
510 case DW_TAG_enumeration_type: return "enum ";
511 case DW_TAG_structure_type:
512 return (!conf->classes_as_structs &&
513 cu->language == DW_LANG_C_plus_plus) ? "class " :
514 "struct ";
515 case DW_TAG_class_type:
516 return conf->classes_as_structs ? "struct " : "class ";
517 case DW_TAG_union_type: return "union ";
518 case DW_TAG_pointer_type: return " *";
519 case DW_TAG_reference_type: return " &";
522 return "";
525 static const char *__tag__name(const struct tag *tag, const struct cu *cu,
526 char *bf, size_t len,
527 const struct conf_fprintf *conf);
529 static const char *tag__ptr_name(const struct tag *tag, const struct cu *cu,
530 char *bf, size_t len, const char *ptr_suffix,
531 const struct conf_fprintf *conf)
533 if (tag->type == 0) /* No type == void */
534 snprintf(bf, len, "void %s", ptr_suffix);
535 else {
536 const struct tag *type = cu__type(cu, tag->type);
538 if (type == NULL) {
539 size_t l = tag__id_not_found_snprintf(bf, len, tag->type);
540 snprintf(bf + l, len - l, " %s", ptr_suffix);
541 } else if (!tag__has_type_loop(tag, type, bf, len, NULL)) {
542 char tmpbf[1024];
543 const char *const_pointer = "";
545 if (tag__is_const(type)) {
546 struct tag *next_type = cu__type(cu, type->type);
548 if (next_type && tag__is_pointer(next_type)) {
549 if (!(conf && conf->skip_emitting_modifier))
550 const_pointer = "const ";
551 type = next_type;
555 snprintf(bf, len, "%s %s%s",
556 __tag__name(type, cu,
557 tmpbf, sizeof(tmpbf), conf),
558 const_pointer,
559 ptr_suffix);
563 return bf;
566 static const char *__tag__name(const struct tag *tag, const struct cu *cu,
567 char *bf, size_t len,
568 const struct conf_fprintf *conf)
570 struct tag *type;
571 const struct conf_fprintf *pconf = conf ?: &conf_fprintf__defaults;
573 if (tag == NULL)
574 strncpy(bf, "void", len);
575 else switch (tag->tag) {
576 case DW_TAG_base_type: {
577 const struct base_type *bt = tag__base_type(tag);
578 const char *name = "nameless base type!";
579 char bf2[64];
581 if (bt->name)
582 name = base_type__name(tag__base_type(tag), bf2, sizeof(bf2));
584 strncpy(bf, name, len);
586 break;
587 case DW_TAG_subprogram:
588 strncpy(bf, function__name(tag__function(tag)), len);
589 break;
590 case DW_TAG_pointer_type:
591 return tag__ptr_name(tag, cu, bf, len, "*", conf);
592 case DW_TAG_reference_type:
593 return tag__ptr_name(tag, cu, bf, len, "&", conf);
594 case DW_TAG_ptr_to_member_type: {
595 char suffix[512];
596 type_id_t id = tag__ptr_to_member_type(tag)->containing_type;
598 type = cu__type(cu, id);
599 if (type != NULL)
600 snprintf(suffix, sizeof(suffix), "%s::*", class__name(tag__class(type)));
601 else {
602 size_t l = tag__id_not_found_snprintf(suffix,
603 sizeof(suffix),
604 id);
605 snprintf(suffix + l, sizeof(suffix) - l, "::*");
608 return tag__ptr_name(tag, cu, bf, len, suffix, conf);
610 case DW_TAG_volatile_type:
611 case DW_TAG_const_type:
612 case DW_TAG_restrict_type:
613 case DW_TAG_atomic_type:
614 case DW_TAG_unspecified_type:
615 type = cu__type(cu, tag->type);
616 if (type == NULL && tag->type != 0)
617 tag__id_not_found_snprintf(bf, len, tag->type);
618 else if (!tag__has_type_loop(tag, type, bf, len, NULL)) {
619 char tmpbf[128];
620 const char *prefix = "", *suffix = "",
621 *type_str = __tag__name(type, cu, tmpbf,
622 sizeof(tmpbf),
623 pconf);
624 if (!pconf->skip_emitting_modifier) {
625 switch (tag->tag) {
626 case DW_TAG_volatile_type: prefix = "volatile "; break;
627 case DW_TAG_const_type: prefix = "const "; break;
628 case DW_TAG_restrict_type: suffix = " restrict"; break;
629 case DW_TAG_atomic_type: prefix = "_Atomic "; break;
632 snprintf(bf, len, "%s%s%s%s", prefix, type_str, suffix,
633 pconf->no_parm_names ? "" : " ");
635 break;
636 case DW_TAG_array_type:
637 type = cu__type(cu, tag->type);
638 if (type == NULL)
639 tag__id_not_found_snprintf(bf, len, tag->type);
640 else if (!tag__has_type_loop(tag, type, bf, len, NULL))
641 return __tag__name(type, cu, bf, len, pconf);
642 break;
643 case DW_TAG_subroutine_type: {
644 FILE *bfp = fmemopen(bf, len, "w");
646 if (bfp != NULL) {
647 ftype__fprintf(tag__ftype(tag), cu, NULL, 0, 0, 0, true, pconf, bfp);
648 fclose(bfp);
649 } else
650 snprintf(bf, len, "<ERROR(%s): fmemopen failed!>",
651 __func__);
653 break;
654 case DW_TAG_member:
655 snprintf(bf, len, "%s", class_member__name(tag__class_member(tag)));
656 break;
657 case DW_TAG_variable:
658 snprintf(bf, len, "%s", variable__name(tag__variable(tag)));
659 break;
660 case DW_TAG_LLVM_annotation:
661 type = cu__type(cu, tag->type);
662 if (type == NULL && tag->type != 0)
663 tag__id_not_found_snprintf(bf, len, tag->type);
664 else if (!tag__has_type_loop(tag, type, bf, len, NULL))
665 __tag__name(type, cu, bf, len, conf);
666 break;
667 default:
668 snprintf(bf, len, "%s%s", tag__prefix(cu, tag->tag, pconf),
669 type__name(tag__type(tag)) ?: "");
670 break;
673 return bf;
676 const char *tag__name(const struct tag *tag, const struct cu *cu,
677 char *bf, size_t len, const struct conf_fprintf *conf)
679 int printed = 0;
681 if (tag == NULL) {
682 strncpy(bf, "void", len);
683 return bf;
686 __tag__name(tag, cu, bf + printed, len - printed, conf);
688 return bf;
691 static const char *variable__prefix(const struct variable *var)
693 switch (variable__scope(var)) {
694 case VSCOPE_REGISTER:
695 return "register ";
696 case VSCOPE_UNKNOWN:
697 if (var->external && var->declaration)
698 return "extern ";
699 break;
700 case VSCOPE_GLOBAL:
701 if (!var->external)
702 return "static ";
703 break;
704 case VSCOPE_LOCAL:
705 case VSCOPE_OPTIMIZED:
706 break;
708 return NULL;
711 static size_t type__fprintf_stats(struct type *type, const struct cu *cu,
712 const struct conf_fprintf *conf, FILE *fp)
714 size_t printed = fprintf(fp, "\n%.*s/* size: %d, cachelines: %zd, members: %u",
715 conf->indent, tabs, type->size,
716 tag__nr_cachelines(conf, type__tag(type), cu), type->nr_members);
718 if (type->nr_static_members != 0)
719 printed += fprintf(fp, ", static members: %u */\n", type->nr_static_members);
720 else
721 printed += fprintf(fp, " */\n");
723 return printed;
726 static type_id_t skip_llvm_annotations(const struct cu *cu, type_id_t id)
728 struct tag *type;
730 for (;;) {
731 if (id == 0)
732 break;
733 type = cu__type(cu, id);
734 if (type == NULL || type->tag != DW_TAG_LLVM_annotation || type->type == id)
735 break;
736 id = type->type;
739 return id;
742 static size_t type__fprintf(struct tag *type, const struct cu *cu,
743 const char *name, const struct conf_fprintf *conf,
744 FILE *fp)
746 char tbf[128];
747 char namebf[256];
748 char namebfptr[258];
749 struct type *ctype;
750 struct tag *type_expanded = NULL;
751 struct conf_fprintf tconf = {
752 .type_spacing = conf->type_spacing,
754 size_t printed = 0;
755 int expand_types = conf->expand_types;
756 int suppress_offset_comment = conf->suppress_offset_comment;
758 if (type == NULL)
759 goto out_type_not_found;
761 if (conf->expand_pointers) {
762 int nr_indirections = 0;
764 while (tag__is_pointer(type) && type->type != 0) {
765 struct tag *ttype = cu__type(cu, type->type);
766 if (ttype == NULL)
767 goto out_type_not_found;
768 else {
769 printed = tag__has_type_loop(type, ttype,
770 NULL, 0, fp);
771 if (printed)
772 return printed;
774 type = ttype;
775 ++nr_indirections;
778 if (nr_indirections > 0) {
779 const size_t len = strlen(name);
780 if (len + nr_indirections >= sizeof(namebf))
781 goto out_type_not_found;
782 memset(namebf, '*', nr_indirections);
783 memcpy(namebf + nr_indirections, name, len);
784 namebf[len + nr_indirections] = '\0';
785 name = namebf;
788 expand_types = nr_indirections;
789 if (!suppress_offset_comment)
790 suppress_offset_comment = !!nr_indirections;
792 /* Avoid loops */
793 if (type->recursivity_level != 0)
794 expand_types = 0;
795 ++type->recursivity_level;
796 type_expanded = type;
799 if (expand_types) {
800 int typedef_expanded = 0;
802 while (tag__is_typedef(type)) {
803 struct tag *type_type;
804 int n;
806 ctype = tag__type(type);
807 if (typedef_expanded)
808 printed += fprintf(fp, " -> %s", type__name(ctype));
809 else {
810 printed += fprintf(fp, "/* typedef %s", type__name(ctype));
811 typedef_expanded = 1;
813 type_type = cu__type(cu, type->type);
814 if (type_type == NULL)
815 goto out_type_not_found;
816 n = tag__has_type_loop(type, type_type, NULL, 0, fp);
817 if (n)
818 return printed + n;
819 type = type_type;
821 if (typedef_expanded)
822 printed += fprintf(fp, " */ ");
825 tconf = *conf;
827 if (tag__is_struct(type) || tag__is_union(type) ||
828 tag__is_enumeration(type)) {
829 inner_struct:
830 tconf.prefix = NULL;
831 tconf.suffix = name;
832 tconf.emit_stats = 0;
833 tconf.suppress_offset_comment = suppress_offset_comment;
836 const char *modifier;
838 next_type:
839 switch (type->tag) {
840 case DW_TAG_pointer_type: {
841 type_id_t ptype_id = skip_llvm_annotations(cu, type->type);
843 if (ptype_id != 0) {
844 int n;
845 struct tag *ptype = cu__type(cu, ptype_id);
846 if (ptype == NULL)
847 goto out_type_not_found;
848 n = tag__has_type_loop(type, ptype, NULL, 0, fp);
849 if (n)
850 return printed + n;
851 if (ptype->tag == DW_TAG_subroutine_type) {
852 printed += ftype__fprintf(tag__ftype(ptype),
853 cu, name, 0, 1,
854 tconf.type_spacing, true,
855 &tconf, fp);
856 break;
858 if ((tag__is_struct(ptype) || tag__is_union(ptype) ||
859 tag__is_enumeration(ptype)) && type__name(tag__type(ptype)) == NULL) {
860 if (name == namebfptr)
861 goto out_type_not_found;
862 snprintf(namebfptr, sizeof(namebfptr), "* %.*s", (int)sizeof(namebfptr) - 3, name);
863 tconf.rel_offset = 1;
864 name = namebfptr;
865 type = ptype;
866 tconf.type_spacing -= 8;
867 goto inner_struct;
870 /* Fall Thru */
872 default:
873 print_default:
874 printed += fprintf(fp, "%-*s %s", tconf.type_spacing,
875 tag__name(type, cu, tbf, sizeof(tbf), &tconf),
876 name);
877 break;
878 case DW_TAG_subroutine_type:
879 printed += ftype__fprintf(tag__ftype(type), cu, name, 0, 0,
880 tconf.type_spacing, true, &tconf, fp);
881 break;
882 case DW_TAG_atomic_type:
883 modifier = "_Atomic";
884 goto print_modifier;
885 case DW_TAG_const_type:
886 modifier = "const";
887 print_modifier: {
888 if (!conf->skip_emitting_modifier) {
889 size_t modifier_printed = fprintf(fp, "%s ", modifier);
890 tconf.type_spacing -= modifier_printed;
891 printed += modifier_printed;
894 struct tag *ttype = cu__type(cu, type->type);
895 if (ttype) {
896 type = ttype;
897 goto next_type;
900 goto print_default;
902 case DW_TAG_array_type:
903 printed += array_type__fprintf(type, cu, name, &tconf, fp);
904 break;
905 case DW_TAG_string_type:
906 printed += string_type__fprintf(type, name, &tconf, fp);
907 break;
908 case DW_TAG_class_type:
909 case DW_TAG_structure_type:
910 ctype = tag__type(type);
912 if (type__name(ctype) != NULL && !expand_types) {
913 printed += fprintf(fp, "%s %-*s %s",
914 (type->tag == DW_TAG_class_type &&
915 !tconf.classes_as_structs) ? "class" : "struct",
916 tconf.type_spacing - 7,
917 type__name(ctype), name ?: "");
918 } else {
919 struct class *cclass = tag__class(type);
921 if (!tconf.suppress_comments)
922 class__find_holes(cclass);
924 tconf.type_spacing -= 8;
925 printed += __class__fprintf(cclass, cu, &tconf, fp);
927 break;
928 case DW_TAG_union_type:
929 printed += union_decl__fprintf(type, cu, name, &tconf, fp);
930 break;
931 case DW_TAG_enumeration_type:
932 ctype = tag__type(type);
934 if (type__name(ctype) != NULL && !expand_types)
935 printed += fprintf(fp, "enum %-*s %s", tconf.type_spacing - 5, type__name(ctype), name ?: "");
936 else
937 printed += enumeration__fprintf(type, &tconf, fp);
938 break;
939 case DW_TAG_LLVM_annotation: {
940 struct tag *ttype = cu__type(cu, type->type);
941 if (ttype) {
942 type = ttype;
943 goto next_type;
945 goto out_type_not_found;
948 out:
949 if (type_expanded)
950 --type_expanded->recursivity_level;
952 return printed;
953 out_type_not_found:
954 printed = fprintf(fp, "%-*s%s> %s", tconf.type_spacing, "<ERROR",
955 name == namebfptr ? ": pointer to pointer to inner struct/union/enum?" : "", name);
956 goto out;
959 static size_t class__fprintf_cacheline_boundary(struct conf_fprintf *conf,
960 uint32_t offset,
961 FILE *fp);
963 static size_t class_member__fprintf(struct class_member *member, bool union_member,
964 struct tag *type, const struct cu *cu,
965 struct conf_fprintf *conf, FILE *fp)
967 const int size = member->byte_size;
968 int member_alignment_printed = 0;
969 struct conf_fprintf sconf = *conf;
970 uint32_t offset = member->byte_offset;
971 size_t printed = 0, printed_cacheline = 0;
972 const char *cm_name = class_member__name(member),
973 *name = cm_name;
975 if (!sconf.rel_offset) {
976 offset += sconf.base_offset;
977 if (!union_member)
978 sconf.base_offset = offset;
981 if (member->bitfield_offset < 0)
982 offset += member->byte_size;
984 if (!conf->suppress_comments)
985 printed_cacheline = class__fprintf_cacheline_boundary(conf, offset, fp);
987 if (member->tag.tag == DW_TAG_inheritance) {
988 name = "<ancestor>";
989 printed += fprintf(fp, "/* ");
992 if (member->is_static)
993 printed += fprintf(fp, "static ");
995 /* For struct-like constructs, the name of the member cannot be
996 * conflated with the name of its type, otherwise __attribute__ are
997 * printed in the wrong order.
999 if (tag__is_union(type) || tag__is_struct(type) ||
1000 tag__is_enumeration(type)) {
1001 printed += type__fprintf(type, cu, NULL, &sconf, fp);
1002 if (name) {
1003 if (!type__name(tag__type(type)) || sconf.expand_types)
1004 printed += fprintf(fp, " ");
1005 printed += fprintf(fp, "%s", name);
1007 } else {
1008 printed += type__fprintf(type, cu, name, &sconf, fp);
1011 if (member->is_static) {
1012 if (member->const_value != 0)
1013 printed += fprintf(fp, " = %" PRIu64, member->const_value);
1014 } else if (member->bitfield_size != 0) {
1015 printed += fprintf(fp, ":%u", member->bitfield_size);
1018 if (!sconf.suppress_aligned_attribute && member->alignment != 0) {
1019 member_alignment_printed = fprintf(fp, " __attribute__((__aligned__(%u)))", member->alignment);
1020 printed += member_alignment_printed;
1023 fputc(';', fp);
1024 ++printed;
1026 if ((tag__is_union(type) || tag__is_struct(type) ||
1027 tag__is_enumeration(type)) &&
1028 /* Look if is a type defined inline */
1029 type__name(tag__type(type)) == NULL) {
1030 if (!sconf.suppress_offset_comment) {
1031 /* Check if this is a anonymous union */
1032 int slen = member_alignment_printed + (cm_name ? (int)strlen(cm_name) : -1);
1033 int size_spacing = 5;
1035 if (tag__is_struct(type) && tag__class(type)->is_packed && !conf->suppress_packed) {
1036 int packed_len = sizeof("__attribute__((__packed__))");
1037 slen += packed_len;
1040 printed += fprintf(fp, sconf.hex_fmt ?
1041 "%*s/* %#5x" :
1042 "%*s/* %5u",
1043 (sconf.type_spacing +
1044 sconf.name_spacing - slen - 3),
1045 " ", offset);
1047 if (member->bitfield_size != 0) {
1048 unsigned int bitfield_offset = member->bitfield_offset;
1050 if (member->bitfield_offset < 0)
1051 bitfield_offset = member->byte_size * 8 + member->bitfield_offset;
1053 printed += fprintf(fp, sconf.hex_fmt ? ":%#2x" : ":%2u", bitfield_offset);
1054 size_spacing -= 3;
1057 printed += fprintf(fp, sconf.hex_fmt ? " %#*x */" : " %*u */", size_spacing, size);
1059 } else {
1060 int spacing = sconf.type_spacing + sconf.name_spacing - printed;
1062 if (member->tag.tag == DW_TAG_inheritance) {
1063 const size_t p = fprintf(fp, " */");
1064 printed += p;
1065 spacing -= p;
1067 if (!sconf.suppress_offset_comment) {
1068 int size_spacing = 5;
1070 printed += fprintf(fp, sconf.hex_fmt ?
1071 "%*s/* %#5x" : "%*s/* %5u",
1072 spacing > 0 ? spacing : 0, " ",
1073 offset);
1075 if (member->bitfield_size != 0) {
1076 unsigned int bitfield_offset = member->bitfield_offset;
1078 if (member->bitfield_offset < 0)
1079 bitfield_offset = member->byte_size * 8 + member->bitfield_offset;
1081 printed += fprintf(fp, sconf.hex_fmt ?
1082 ":%#2x" : ":%2u",
1083 bitfield_offset);
1084 size_spacing -= 3;
1087 printed += fprintf(fp, sconf.hex_fmt ?
1088 " %#*x */" : " %*u */",
1089 size_spacing, size);
1092 return printed + printed_cacheline;
1095 static size_t struct_member__fprintf(struct class_member *member,
1096 struct tag *type, const struct cu *cu,
1097 struct conf_fprintf *conf, FILE *fp)
1099 return class_member__fprintf(member, false, type, cu, conf, fp);
1102 static size_t union_member__fprintf(struct class_member *member,
1103 struct tag *type, const struct cu *cu,
1104 struct conf_fprintf *conf, FILE *fp)
1106 return class_member__fprintf(member, true, type, cu, conf, fp);
1109 static size_t union__fprintf(struct type *type, const struct cu *cu,
1110 const struct conf_fprintf *conf, FILE *fp)
1112 struct class_member *pos;
1113 size_t printed = 0;
1114 int indent = conf->indent;
1115 struct conf_fprintf uconf;
1116 uint32_t initial_union_cacheline;
1117 uint32_t cacheline = 0; /* This will only be used if this is the outermost union */
1119 if (indent >= (int)sizeof(tabs))
1120 indent = sizeof(tabs) - 1;
1122 if (conf->prefix != NULL)
1123 printed += fprintf(fp, "%s ", conf->prefix);
1124 printed += fprintf(fp, "union%s%s {\n", type__name(type) ? " " : "",
1125 type__name(type) ?: "");
1127 uconf = *conf;
1128 uconf.indent = indent + 1;
1131 * If structs embedded in unions, nameless or not, have a size which isn't
1132 * isn't a multiple of the union size, then it must be packed, even if
1133 * it has no holes nor padding, as an array of such unions would have the
1134 * natural alignments of non-multiple structs inside it broken.
1136 union__infer_packed_attributes(type, cu);
1139 * We may be called directly or from tag__fprintf, so keep sure
1140 * we keep track of the cacheline we're in.
1142 * If we're being called from an outer structure, i.e. union within
1143 * struct, class or another union, then this will already have a
1144 * value and we'll continue to use it.
1146 if (uconf.cachelinep == NULL)
1147 uconf.cachelinep = &cacheline;
1149 * Save the cacheline we're in, then, after each union member, get
1150 * back to it. Else we'll end up showing cacheline boundaries in
1151 * just the first of a multi struct union, for instance.
1153 initial_union_cacheline = *uconf.cachelinep;
1154 type__for_each_member(type, pos) {
1155 struct tag *pos_type = cu__type(cu, pos->tag.type);
1157 if (pos_type == NULL) {
1158 printed += fprintf(fp, "%.*s", uconf.indent, tabs);
1159 printed += tag__id_not_found_fprintf(fp, pos->tag.type);
1160 continue;
1163 uconf.union_member = 1;
1164 printed += fprintf(fp, "%.*s", uconf.indent, tabs);
1165 printed += union_member__fprintf(pos, pos_type, cu, &uconf, fp);
1166 fputc('\n', fp);
1167 ++printed;
1168 *uconf.cachelinep = initial_union_cacheline;
1171 return printed + fprintf(fp, "%.*s}%s%s", indent, tabs,
1172 conf->suffix ? " " : "", conf->suffix ?: "");
1175 const char *function__prototype_conf(const struct function *func,
1176 const struct cu *cu,
1177 const struct conf_fprintf *conf,
1178 char *bf, size_t len)
1180 FILE *bfp = fmemopen(bf, len, "w");
1182 if (bfp != NULL) {
1183 ftype__fprintf(&func->proto, cu, NULL, 0, 0, 0, true, conf,
1184 bfp);
1185 fclose(bfp);
1186 } else {
1187 if (conf->skip_emitting_errors)
1188 return NULL;
1189 snprintf(bf, len, "<ERROR(%s): fmemopen failed!>", __func__);
1192 return bf;
1195 const char *function__prototype(const struct function *func,
1196 const struct cu *cu, char *bf, size_t len)
1198 return function__prototype_conf(func, cu, &conf_fprintf__defaults,
1199 bf, len);
1202 size_t ftype__fprintf_parms(const struct ftype *ftype,
1203 const struct cu *cu, int indent,
1204 const struct conf_fprintf *conf, FILE *fp)
1206 struct parameter *pos;
1207 int first_parm = 1;
1208 char sbf[128];
1209 struct tag *type;
1210 const char *name, *stype;
1211 size_t printed = fprintf(fp, "(");
1213 ftype__for_each_parameter(ftype, pos) {
1214 if (!first_parm) {
1215 if (indent == 0)
1216 printed += fprintf(fp, ", ");
1217 else
1218 printed += fprintf(fp, ",\n%.*s",
1219 indent, tabs);
1220 } else
1221 first_parm = 0;
1222 name = conf->no_parm_names ? NULL : parameter__name(pos);
1223 type = cu__type(cu, pos->tag.type);
1224 if (type == NULL) {
1225 snprintf(sbf, sizeof(sbf),
1226 "<ERROR: type %d not found>", pos->tag.type);
1227 stype = sbf;
1228 goto print_it;
1230 if (tag__is_pointer(type)) {
1231 if (type->type != 0) {
1232 int n;
1233 struct tag *ptype = cu__type(cu, type->type);
1234 if (ptype == NULL) {
1235 printed +=
1236 tag__id_not_found_fprintf(fp, type->type);
1237 continue;
1239 n = tag__has_type_loop(type, ptype, NULL, 0, fp);
1240 if (n)
1241 return printed + n;
1242 if (ptype->tag == DW_TAG_subroutine_type) {
1243 printed +=
1244 ftype__fprintf(tag__ftype(ptype),
1245 cu, name, 0, 1, 0,
1246 true, conf, fp);
1247 continue;
1250 } else if (type->tag == DW_TAG_subroutine_type) {
1251 printed += ftype__fprintf(tag__ftype(type), cu, name,
1252 true, 0, 0, 0, conf, fp);
1253 continue;
1255 stype = tag__name(type, cu, sbf, sizeof(sbf), conf);
1256 print_it:
1257 printed += fprintf(fp, "%s%s%s", stype, name ? " " : "",
1258 name ?: "");
1261 /* No parameters? */
1262 if (first_parm)
1263 printed += fprintf(fp, "void)");
1264 else if (ftype->unspec_parms)
1265 printed += fprintf(fp, ", ...)");
1266 else
1267 printed += fprintf(fp, ")");
1268 return printed;
1271 static size_t function__tag_fprintf(const struct tag *tag, const struct cu *cu,
1272 struct function *function, uint16_t indent,
1273 const struct conf_fprintf *conf, FILE *fp)
1275 char bf[512];
1276 size_t printed = 0, n;
1277 const void *vtag = tag;
1278 int c;
1280 if (indent >= sizeof(tabs))
1281 indent = sizeof(tabs) - 1;
1282 c = indent * 8;
1284 switch (tag->tag) {
1285 case DW_TAG_inlined_subroutine: {
1286 const struct inline_expansion *exp = vtag;
1287 const struct tag *talias = cu__function(cu, exp->ip.tag.type);
1288 struct function *alias = tag__function(talias);
1289 const char *name;
1291 if (alias == NULL) {
1292 printed += tag__id_not_found_fprintf(fp, exp->ip.tag.type);
1293 break;
1295 printed = fprintf(fp, "%.*s", indent, tabs);
1296 name = function__name(alias);
1297 n = fprintf(fp, "%s", name);
1298 size_t namelen = 0;
1299 if (name != NULL)
1300 namelen = strlen(name);
1301 n += ftype__fprintf_parms(&alias->proto, cu,
1302 indent + (namelen + 7) / 8,
1303 conf, fp);
1304 n += fprintf(fp, "; /* size=%zd, low_pc=%#llx */",
1305 exp->size, (unsigned long long)exp->ip.addr);
1306 #if 0
1307 n = fprintf(fp, "%s(); /* size=%zd, low_pc=%#llx */",
1308 function__name(alias), exp->size,
1309 (unsigned long long)exp->ip.addr);
1310 #endif
1311 c = 69;
1312 printed += n;
1314 break;
1315 case DW_TAG_variable:
1316 printed = fprintf(fp, "%.*s", indent, tabs);
1317 n = fprintf(fp, "%s %s; /* scope: %s */",
1318 variable__type_name(vtag, cu, bf, sizeof(bf)),
1319 variable__name(vtag),
1320 variable__scope_str(vtag));
1321 c += n;
1322 printed += n;
1323 break;
1324 case DW_TAG_label: {
1325 const struct label *label = vtag;
1326 printed = fprintf(fp, "%.*s", indent, tabs);
1327 fputc('\n', fp);
1328 ++printed;
1329 c = fprintf(fp, "%s:", label__name(label));
1330 printed += c;
1332 break;
1333 case DW_TAG_lexical_block:
1334 printed = lexblock__fprintf(vtag, cu, function, indent,
1335 conf, fp);
1336 fputc('\n', fp);
1337 return printed + 1;
1338 default:
1339 printed = fprintf(fp, "%.*s", indent, tabs);
1340 n = fprintf(fp, "%s <%llx>", dwarf_tag_name(tag->tag),
1341 tag__orig_id(tag, cu));
1342 c += n;
1343 printed += n;
1344 break;
1346 return printed + fprintf(fp, "%-*.*s// %5u\n", 70 - c, 70 - c, " ",
1347 tag__decl_line(tag, cu));
1350 size_t lexblock__fprintf(const struct lexblock *block, const struct cu *cu,
1351 struct function *function, uint16_t indent,
1352 const struct conf_fprintf *conf, FILE *fp)
1354 struct tag *pos;
1355 size_t printed;
1357 if (indent >= sizeof(tabs))
1358 indent = sizeof(tabs) - 1;
1359 printed = fprintf(fp, "%.*s{", indent, tabs);
1360 if (block->ip.addr != 0) {
1361 uint64_t offset = block->ip.addr - function->lexblock.ip.addr;
1363 if (offset == 0)
1364 printed += fprintf(fp, " /* low_pc=%#llx */",
1365 (unsigned long long)block->ip.addr);
1366 else
1367 printed += fprintf(fp, " /* %s+%#llx */",
1368 function__name(function),
1369 (unsigned long long)offset);
1371 printed += fprintf(fp, "\n");
1372 list_for_each_entry(pos, &block->tags, node)
1373 printed += function__tag_fprintf(pos, cu, function, indent + 1,
1374 conf, fp);
1375 printed += fprintf(fp, "%.*s}", indent, tabs);
1377 if (function->lexblock.ip.addr != block->ip.addr)
1378 printed += fprintf(fp, " /* lexblock size=%d */", block->size);
1380 return printed;
1383 size_t ftype__fprintf(const struct ftype *ftype, const struct cu *cu,
1384 const char *name, const int inlined,
1385 const int is_pointer, int type_spacing, bool is_prototype,
1386 const struct conf_fprintf *conf, FILE *fp)
1388 struct tag *type = cu__type(cu, ftype->tag.type);
1389 char sbf[128];
1390 const char *stype = tag__name(type, cu, sbf, sizeof(sbf), conf);
1391 size_t printed = fprintf(fp, "%s%-*s %s%s%s%s",
1392 inlined ? "inline " : "",
1393 type_spacing, stype,
1394 is_prototype ? "(" : "",
1395 is_pointer ? "*" : "", name ?: "",
1396 is_prototype ? ")" : "");
1398 return printed + ftype__fprintf_parms(ftype, cu, 0, conf, fp);
1401 static size_t function__fprintf(const struct tag *tag, const struct cu *cu,
1402 const struct conf_fprintf *conf, FILE *fp)
1404 struct function *func = tag__function(tag);
1405 struct ftype *ftype = func->btf ? tag__ftype(cu__type(cu, func->proto.tag.type)) : &func->proto;
1406 size_t printed = 0;
1407 bool inlined = !conf->strip_inline && function__declared_inline(func);
1408 int i;
1410 if (tag->attributes)
1411 for (i = 0; i < tag->attributes->cnt; ++i)
1412 printed += fprintf(fp, "%s ", tag->attributes->values[i]);
1414 if (func->virtuality == DW_VIRTUALITY_virtual ||
1415 func->virtuality == DW_VIRTUALITY_pure_virtual)
1416 printed += fprintf(fp, "virtual ");
1418 printed += ftype__fprintf(ftype, cu, function__name(func),
1419 inlined, 0, 0, false, conf, fp);
1421 if (func->virtuality == DW_VIRTUALITY_pure_virtual)
1422 printed += fprintf(fp, " = 0");
1424 return printed;
1427 size_t function__fprintf_stats(const struct tag *tag, const struct cu *cu,
1428 const struct conf_fprintf *conf, FILE *fp)
1430 struct function *func = tag__function(tag);
1431 size_t printed = lexblock__fprintf(&func->lexblock, cu, func, 0, conf, fp);
1433 printed += fprintf(fp, "/* size: %d", function__size(func));
1434 if (func->lexblock.nr_variables > 0)
1435 printed += fprintf(fp, ", variables: %u",
1436 func->lexblock.nr_variables);
1437 if (func->lexblock.nr_labels > 0)
1438 printed += fprintf(fp, ", goto labels: %u",
1439 func->lexblock.nr_labels);
1440 if (func->lexblock.nr_inline_expansions > 0)
1441 printed += fprintf(fp, ", inline expansions: %u (%d bytes)",
1442 func->lexblock.nr_inline_expansions,
1443 func->lexblock.size_inline_expansions);
1444 return printed + fprintf(fp, " */\n");
1447 static size_t class__fprintf_cacheline_boundary(struct conf_fprintf *conf,
1448 uint32_t offset,
1449 FILE *fp)
1451 int indent = conf->indent;
1452 uint32_t cacheline = offset / conf_fprintf__cacheline_size(conf);
1453 size_t printed = 0;
1455 if (cacheline > *conf->cachelinep) {
1456 const uint32_t cacheline_pos = offset % conf_fprintf__cacheline_size(conf);
1457 const uint32_t cacheline_in_bytes = offset - cacheline_pos;
1459 if (cacheline_pos == 0)
1460 printed += fprintf(fp, "/* --- cacheline %u boundary "
1461 "(%u bytes) --- */\n", cacheline,
1462 cacheline_in_bytes);
1463 else
1464 printed += fprintf(fp, "/* --- cacheline %u boundary "
1465 "(%u bytes) was %u byte%s ago --- "
1466 "*/\n", cacheline,
1467 cacheline_in_bytes, cacheline_pos,
1468 cacheline_pos > 1 ? "s" : "");
1470 printed += fprintf(fp, "%.*s", indent, tabs);
1472 *conf->cachelinep = cacheline;
1474 return printed;
1477 static size_t class__vtable_fprintf(struct class *class, const struct conf_fprintf *conf, FILE *fp)
1479 struct function *pos;
1480 size_t printed = 0;
1482 if (class->nr_vtable_entries == 0)
1483 goto out;
1485 printed += fprintf(fp, "%.*s/* vtable has %u entries: {\n",
1486 conf->indent, tabs, class->nr_vtable_entries);
1488 list_for_each_entry(pos, &class->vtable, vtable_node) {
1489 printed += fprintf(fp, "%.*s [%d] = %s(%s), \n",
1490 conf->indent, tabs, pos->vtable_entry,
1491 function__name(pos),
1492 function__linkage_name(pos));
1495 printed += fprintf(fp, "%.*s} */", conf->indent, tabs);
1496 out:
1497 return printed;
1500 struct member_types_holes {
1501 uint16_t nr_paddings;
1502 uint16_t nr_with_bit_paddings;
1503 uint16_t nr_with_holes;
1504 uint16_t nr_with_bit_holes;
1505 uint16_t total_nr_holes;
1506 uint16_t total_nr_bit_holes;
1507 uint16_t nr_flexible_array_members;
1508 uint16_t nr_embedded_flexible_array_members;
1509 uint32_t sum_paddings;
1510 uint32_t sum_bit_paddings;
1513 static size_t class__fprintf_member_type_holes(struct class *class, const struct cu *cu,
1514 struct member_types_holes *holes,
1515 uint8_t *newline, const struct conf_fprintf *conf, FILE *fp)
1517 size_t printed = 0;
1518 uint16_t padding;
1519 uint8_t nr_holes, nr_bit_holes, bit_padding;
1520 bool first = true, has_embedded_flexible_array, has_flexible_array;
1522 * We may not yet have looked for holes and paddings in this member's
1523 * struct type.
1525 class__find_holes(class);
1526 class__infer_packed_attributes(class, cu);
1528 padding = class->padding;
1529 bit_padding = class->bit_padding;
1530 nr_holes = class->nr_holes;
1531 nr_bit_holes = class->nr_bit_holes;
1532 has_flexible_array = class__has_flexible_array(class, cu);
1533 has_embedded_flexible_array = class__has_embedded_flexible_array(class, cu);
1535 if (!padding && !bit_padding && !nr_holes && !nr_bit_holes && !has_flexible_array && !has_embedded_flexible_array)
1536 return 0;
1538 if (!(*newline)++) {
1539 fputc('\n', fp);
1540 ++printed;
1543 printed += fprintf(fp, "\n%.*s/* XXX last struct has", conf->indent, tabs);
1545 if (has_flexible_array) {
1546 printed += fprintf(fp, " a flexible array");
1547 ++holes->nr_flexible_array_members;
1548 first = false;
1551 if (has_embedded_flexible_array) {
1552 printed += fprintf(fp, "%s embedded flexible array(s)", first ? "" : ",");
1553 ++holes->nr_embedded_flexible_array_members;
1554 first = false;
1557 if (padding) {
1558 ++holes->nr_paddings;
1559 holes->sum_paddings += padding;
1561 printed += fprintf(fp, "%s %d byte%s of padding", first ? "" : ",", padding, padding != 1 ? "s" : "");
1562 first = false;
1565 if (bit_padding) {
1566 ++holes->nr_with_bit_paddings;
1567 holes->sum_bit_paddings += bit_padding;
1569 printed += fprintf(fp, "%s %d bit%s of padding", first ? "" : ",", bit_padding, bit_padding != 1 ? "s" : "");
1570 first = false;
1573 if (nr_holes) {
1574 ++holes->nr_with_holes;
1575 holes->total_nr_holes += nr_holes;
1577 printed += fprintf(fp, "%s %d hole%s", first ? "" : ",", nr_holes, nr_holes != 1 ? "s" : "");
1578 first = false;
1581 if (nr_bit_holes) {
1582 ++holes->nr_with_bit_holes;
1583 holes->total_nr_bit_holes += nr_bit_holes;
1585 printed += fprintf(fp, "%s %d bit hole%s", first ? "" : ",", nr_bit_holes, nr_bit_holes != 1 ? "s" : "");
1588 return printed + fprintf(fp, " */");
1591 static size_t __class__fprintf(struct class *class, const struct cu *cu,
1592 const struct conf_fprintf *conf, FILE *fp)
1594 struct type *type = &class->type;
1595 size_t last_size = 0, size;
1596 uint8_t newline = 0;
1597 uint16_t nr_forced_alignments = 0, nr_forced_alignment_holes = 0;
1598 uint32_t sum_forced_alignment_holes = 0;
1599 uint32_t sum_bytes = 0, sum_bits = 0;
1600 uint32_t sum_holes = 0;
1601 uint32_t sum_bit_holes = 0;
1602 struct member_types_holes member_types_holes = { 0, };
1603 uint32_t cacheline = 0;
1604 int size_diff = 0;
1605 int first = 1;
1606 struct class_member *pos, *last = NULL;
1607 struct tag *tag_pos;
1608 const char *current_accessibility = NULL;
1609 struct conf_fprintf cconf = conf ? *conf : conf_fprintf__defaults;
1610 const uint16_t t = type->namespace.tag.tag;
1611 size_t printed = fprintf(fp, "%s%s%s%s%s",
1612 cconf.prefix ?: "", cconf.prefix ? " " : "",
1613 ((cconf.classes_as_structs ||
1614 t == DW_TAG_structure_type) ? "struct" :
1615 t == DW_TAG_class_type ? "class" :
1616 "interface"),
1617 type__name(type) ? " " : "",
1618 type__name(type) ?: "");
1619 int indent = cconf.indent;
1621 if (indent >= (int)sizeof(tabs))
1622 indent = sizeof(tabs) - 1;
1624 if (cconf.cachelinep == NULL)
1625 cconf.cachelinep = &cacheline;
1627 cconf.indent = indent + 1;
1628 cconf.no_semicolon = 0;
1630 class__infer_packed_attributes(class, cu);
1632 /* First look if we have DW_TAG_inheritance */
1633 type__for_each_tag(type, tag_pos) {
1634 const char *accessibility;
1636 if (tag_pos->tag != DW_TAG_inheritance)
1637 continue;
1639 if (first) {
1640 printed += fprintf(fp, " :");
1641 first = 0;
1642 } else
1643 printed += fprintf(fp, ",");
1645 pos = tag__class_member(tag_pos);
1647 if (pos->virtuality == DW_VIRTUALITY_virtual)
1648 printed += fprintf(fp, " virtual");
1650 accessibility = tag__accessibility(tag_pos);
1651 if (accessibility != NULL)
1652 printed += fprintf(fp, " %s", accessibility);
1654 struct tag *pos_type = cu__type(cu, tag_pos->type);
1655 if (pos_type != NULL)
1656 printed += fprintf(fp, " %s",
1657 type__name(tag__type(pos_type)));
1658 else
1659 printed += tag__id_not_found_fprintf(fp, tag_pos->type);
1662 printed += fprintf(fp, " {\n");
1664 if (class->pre_bit_hole > 0 && !cconf.suppress_comments) {
1665 if (!newline++) {
1666 fputc('\n', fp);
1667 ++printed;
1669 printed += fprintf(fp, "%.*s/* XXX %d bit%s hole, "
1670 "try to pack */\n", cconf.indent, tabs,
1671 class->pre_bit_hole,
1672 class->pre_bit_hole != 1 ? "s" : "");
1673 sum_bit_holes += class->pre_bit_hole;
1676 if (class->pre_hole > 0 && !cconf.suppress_comments) {
1677 if (!newline++) {
1678 fputc('\n', fp);
1679 ++printed;
1681 printed += fprintf(fp, "%.*s/* XXX %d byte%s hole, "
1682 "try to pack */\n",
1683 cconf.indent, tabs, class->pre_hole,
1684 class->pre_hole != 1 ? "s" : "");
1685 sum_holes += class->pre_hole;
1688 type__for_each_tag(type, tag_pos) {
1689 const char *accessibility = tag__accessibility(tag_pos);
1691 if (accessibility != NULL &&
1692 accessibility != current_accessibility) {
1693 current_accessibility = accessibility;
1694 printed += fprintf(fp, "%.*s%s:\n\n",
1695 cconf.indent - 1, tabs,
1696 accessibility);
1699 if (tag_pos->tag != DW_TAG_member &&
1700 tag_pos->tag != DW_TAG_inheritance) {
1701 if (!cconf.show_only_data_members) {
1702 printed += tag__fprintf(tag_pos, cu, &cconf, fp);
1703 printed += fprintf(fp, "\n\n");
1705 continue;
1707 pos = tag__class_member(tag_pos);
1709 if (!cconf.suppress_aligned_attribute && pos->alignment != 0) {
1710 uint32_t forced_alignment_hole = last ? last->hole : class->pre_hole;
1712 if (forced_alignment_hole != 0) {
1713 ++nr_forced_alignment_holes;
1714 sum_forced_alignment_holes += forced_alignment_hole;
1716 ++nr_forced_alignments;
1719 * These paranoid checks doesn't make much sense on
1720 * DW_TAG_inheritance, have to understand why virtual public
1721 * ancestors make the offset go backwards...
1723 if (last != NULL && tag_pos->tag == DW_TAG_member &&
1725 * kmemcheck bitfield tricks use zero sized arrays as markers
1726 * all over the place.
1728 last_size != 0) {
1729 if (last->bit_hole != 0 && pos->bitfield_size) {
1730 uint8_t bitfield_size = last->bit_hole;
1731 struct tag *pos_type = cu__type(cu, pos->tag.type);
1733 if (pos_type == NULL) {
1734 printed += fprintf(fp, "%.*s", cconf.indent, tabs);
1735 printed += tag__id_not_found_fprintf(fp, pos->tag.type);
1736 goto next_member;
1739 * Now check if this isn't something like 'unsigned :N' with N > 0,
1740 * i.e. _explicitely_ adding a bit hole.
1742 if (last->byte_offset != pos->byte_offset) {
1743 printed += fprintf(fp, "\n%.*s/* Force alignment to the next boundary: */\n", cconf.indent, tabs);
1744 bitfield_size = 0;
1747 printed += fprintf(fp, "%.*s", cconf.indent, tabs);
1748 printed += type__fprintf(pos_type, cu, "", &cconf, fp);
1749 printed += fprintf(fp, ":%u;\n", bitfield_size);
1752 if (pos->byte_offset < last->byte_offset ||
1753 (pos->byte_offset == last->byte_offset &&
1754 last->bitfield_size == 0 &&
1756 * This is just when transitioning from a non-bitfield to
1757 * a bitfield, think about zero sized arrays in the middle
1758 * of a struct.
1760 pos->bitfield_size != 0)) {
1761 if (!cconf.suppress_comments) {
1762 if (!newline++) {
1763 fputc('\n', fp);
1764 ++printed;
1766 printed += fprintf(fp, "%.*s/* Bitfield combined"
1767 " with previous fields */\n",
1768 cconf.indent, tabs);
1770 } else {
1771 const ssize_t cc_last_size = ((ssize_t)pos->byte_offset -
1772 (ssize_t)last->byte_offset);
1773 if (cc_last_size > 0 &&
1774 (size_t)cc_last_size < last_size) {
1775 if (!cconf.suppress_comments) {
1776 if (!newline++) {
1777 fputc('\n', fp);
1778 ++printed;
1780 printed += fprintf(fp, "%.*s/* Bitfield combined"
1781 " with next fields */\n",
1782 cconf.indent, tabs);
1788 if (newline) {
1789 fputc('\n', fp);
1790 newline = 0;
1791 ++printed;
1794 struct tag *pos_type = cu__type(cu, pos->tag.type);
1795 if (pos_type == NULL) {
1796 printed += fprintf(fp, "%.*s", cconf.indent, tabs);
1797 printed += tag__id_not_found_fprintf(fp, pos->tag.type);
1798 goto next_member;
1801 cconf.last_member = list_is_last(&tag_pos->node, &type->namespace.tags);
1802 cconf.first_member = last == NULL;
1804 size = pos->byte_size;
1805 if (tag_pos->tag == DW_TAG_inheritance && pos->hole < 0) {
1806 // Using the padding of an ancestor class
1807 size += pos->hole;
1810 printed += fprintf(fp, "%.*s", cconf.indent, tabs);
1811 printed += struct_member__fprintf(pos, pos_type, cu, &cconf, fp);
1813 if (tag__is_struct(pos_type) && !cconf.suppress_comments) {
1814 struct class *tclass = tag__class(pos_type);
1816 printed += class__fprintf_member_type_holes(tclass, cu, &member_types_holes,
1817 &newline, &cconf, fp);
1820 if (pos->bit_hole != 0 && !cconf.suppress_comments) {
1821 if (!newline++) {
1822 fputc('\n', fp);
1823 ++printed;
1825 printed += fprintf(fp, "\n%.*s/* XXX %d bit%s hole, "
1826 "try to pack */", cconf.indent, tabs,
1827 pos->bit_hole,
1828 pos->bit_hole != 1 ? "s" : "");
1829 sum_bit_holes += pos->bit_hole;
1832 if (pos->hole > 0 && !cconf.suppress_comments) {
1833 if (!newline++) {
1834 fputc('\n', fp);
1835 ++printed;
1837 printed += fprintf(fp, "\n%.*s/* XXX %d byte%s hole, "
1838 "try to pack */",
1839 cconf.indent, tabs, pos->hole,
1840 pos->hole != 1 ? "s" : "");
1841 sum_holes += pos->hole;
1844 fputc('\n', fp);
1845 ++printed;
1846 #if 0
1848 * This one was being skipped but caused problems with:
1849 * http://article.gmane.org/gmane.comp.debugging.dwarves/185
1850 * http://www.spinics.net/lists/dwarves/msg00119.html
1852 if (pos->virtuality == DW_VIRTUALITY_virtual)
1853 goto next_member;
1854 #endif
1856 if (pos->bitfield_size) {
1857 sum_bits += pos->bitfield_size;
1858 } else {
1859 sum_bytes += size;
1862 if (last == NULL || /* First member */
1864 * Last member was a zero sized array, typedef, struct, etc
1866 last_size == 0 ||
1868 * We moved to a new offset
1870 last->byte_offset != pos->byte_offset) {
1871 last_size = size;
1872 } else if (last->bitfield_size == 0 && pos->bitfield_size != 0) {
1874 * Transitioned from from a non-bitfield to a
1875 * bitfield sharing the same offset
1878 * Compensate by removing the size of the
1879 * last member that is "inside" this new
1880 * member at the same offset.
1882 * E.g.:
1883 * struct foo {
1884 * u8 a; / 0 1 /
1885 * int b:1; / 0:23 4 /
1888 last_size = size;
1890 next_member:
1891 last = pos;
1895 * BTF doesn't have alignment info, for now use this infor from the loader
1896 * to avoid adding the forced bitfield paddings and have btfdiff happy.
1898 if (class->padding != 0 && type->alignment == 0 && cconf.has_alignment_info &&
1899 !cconf.suppress_force_paddings && last != NULL) {
1900 tag_pos = cu__type(cu, last->tag.type);
1901 size = tag__size(tag_pos, cu);
1903 if (is_power_of_2(size) && class->padding > cu->addr_size) {
1904 int added_padding;
1905 int bit_size = size * 8;
1907 printed += fprintf(fp, "\n%.*s/* Force padding: */\n", cconf.indent, tabs);
1909 for (added_padding = 0; added_padding < class->padding; added_padding += size) {
1910 printed += fprintf(fp, "%.*s", cconf.indent, tabs);
1911 printed += type__fprintf(tag_pos, cu, "", &cconf, fp);
1912 printed += fprintf(fp, ":%u;\n", bit_size);
1917 if (!cconf.show_only_data_members)
1918 class__vtable_fprintf(class, &cconf, fp);
1920 if (!cconf.emit_stats)
1921 goto out;
1923 printed += type__fprintf_stats(type, cu, &cconf, fp);
1925 if (sum_holes > 0 || sum_bit_holes > 0) {
1926 if (sum_bytes > 0) {
1927 printed += fprintf(fp, "%.*s/* sum members: %u",
1928 cconf.indent, tabs, sum_bytes);
1929 if (sum_holes > 0)
1930 printed += fprintf(fp, ", holes: %d, sum holes: %u",
1931 class->nr_holes, sum_holes);
1932 printed += fprintf(fp, " */\n");
1934 if (sum_bits > 0) {
1935 printed += fprintf(fp, "%.*s/* sum bitfield members: %u bits",
1936 cconf.indent, tabs, sum_bits);
1937 if (sum_bit_holes > 0)
1938 printed += fprintf(fp, ", bit holes: %d, sum bit holes: %u bits",
1939 class->nr_bit_holes, sum_bit_holes);
1940 else
1941 printed += fprintf(fp, " (%u bytes)", sum_bits / 8);
1942 printed += fprintf(fp, " */\n");
1945 if (class->padding > 0)
1946 printed += fprintf(fp, "%.*s/* padding: %u */\n",
1947 cconf.indent,
1948 tabs, class->padding);
1950 if (member_types_holes.nr_with_holes > 0 ||
1951 member_types_holes.nr_with_bit_holes > 0 ||
1952 member_types_holes.nr_with_bit_paddings > 0) {
1953 bool first = true;
1955 printed += fprintf(fp, "%.*s/* member types with ", cconf.indent, tabs);
1956 if (member_types_holes.nr_with_holes > 0) {
1957 printed += fprintf(fp, "holes: %u, total: %u",
1958 member_types_holes.nr_with_holes, member_types_holes.total_nr_holes);
1959 first = false;
1961 if (member_types_holes.nr_with_bit_holes > 0) {
1962 printed += fprintf(fp, "%sbit holes: %u, total: %u", first ? "" : ", ",
1963 member_types_holes.nr_with_bit_holes, member_types_holes.total_nr_bit_holes);
1964 first = false;
1966 if (member_types_holes.nr_with_bit_paddings > 0) {
1967 printed += fprintf(fp, "%sbit paddings: %u, total: %u bit%s", first ? "" : ", ",
1968 member_types_holes.nr_with_bit_paddings,
1969 member_types_holes.sum_bit_paddings,
1970 member_types_holes.sum_bit_paddings > 1 ? "s" : "");
1972 printed += fprintf(fp, " */\n");
1974 if (member_types_holes.nr_paddings > 0)
1975 printed += fprintf(fp, "%.*s/* paddings: %u, sum paddings: "
1976 "%u */\n",
1977 cconf.indent, tabs,
1978 member_types_holes.nr_paddings, member_types_holes.sum_paddings);
1979 if (class->bit_padding > 0)
1980 printed += fprintf(fp, "%.*s/* bit_padding: %u bits */\n",
1981 cconf.indent, tabs,
1982 class->bit_padding);
1983 if (!cconf.suppress_aligned_attribute && nr_forced_alignments != 0) {
1984 printed += fprintf(fp, "%.*s/* forced alignments: %u",
1985 cconf.indent, tabs,
1986 nr_forced_alignments);
1987 if (nr_forced_alignment_holes != 0) {
1988 printed += fprintf(fp, ", forced holes: %u, sum forced holes: %u",
1989 nr_forced_alignment_holes,
1990 sum_forced_alignment_holes);
1992 printed += fprintf(fp, " */\n");
1994 if (member_types_holes.nr_flexible_array_members > 0 ||
1995 member_types_holes.nr_embedded_flexible_array_members > 0) {
1996 printed += fprintf(fp, "%.*s/* flexible array members: ",
1997 cconf.indent, tabs);
1999 if (member_types_holes.nr_flexible_array_members > 0)
2000 printed += fprintf(fp, "end: %u", member_types_holes.nr_flexible_array_members);
2002 if (member_types_holes.nr_embedded_flexible_array_members > 0) {
2003 printed += fprintf(fp, "%smiddle: %u",
2004 member_types_holes.nr_flexible_array_members ? ", " : "",
2005 member_types_holes.nr_embedded_flexible_array_members);
2008 printed += fprintf(fp, " */\n");
2010 cacheline = (cconf.base_offset + type->size) % conf_fprintf__cacheline_size(conf);
2011 if (cacheline != 0)
2012 printed += fprintf(fp, "%.*s/* last cacheline: %u bytes */\n",
2013 cconf.indent, tabs,
2014 cacheline);
2015 if (cconf.show_first_biggest_size_base_type_member &&
2016 type->nr_members != 0) {
2017 struct class_member *m = type__find_first_biggest_size_base_type_member(type, cu);
2019 printed += fprintf(fp, "%.*s/* first biggest size base type member: %s %u %zd */\n",
2020 cconf.indent, tabs,
2021 class_member__name(m), m->byte_offset,
2022 m->byte_size);
2025 size_diff = type->size * 8 - (sum_bytes * 8 + sum_bits + sum_holes * 8 + sum_bit_holes +
2026 class->padding * 8 + class->bit_padding);
2027 if (size_diff && type->nr_members != 0)
2028 printed += fprintf(fp, "\n%.*s/* BRAIN FART ALERT! %d bytes != "
2029 "%u (member bytes) + %u (member bits) "
2030 "+ %u (byte holes) + %u (bit holes), diff = %d bits */\n",
2031 cconf.indent, tabs,
2032 type->size, sum_bytes, sum_bits, sum_holes, sum_bit_holes, size_diff);
2033 out:
2034 printed += fprintf(fp, "%.*s}", indent, tabs);
2036 if (class->is_packed && !cconf.suppress_packed)
2037 printed += fprintf(fp, " __attribute__((__packed__))");
2039 if (cconf.suffix)
2040 printed += fprintf(fp, " %s", cconf.suffix);
2043 * A class that was marked packed by class__infer_packed_attributes
2044 * because it has an alignment that is different than its natural
2045 * alignment, should not print the __alignment__ here, just the
2046 * __packed__ attribute.
2048 if (!cconf.suppress_aligned_attribute && type->alignment != 0 && !class->is_packed)
2049 printed += fprintf(fp, " __attribute__((__aligned__(%u)))", type->alignment);
2051 return printed;
2054 size_t class__fprintf(struct class *class, const struct cu *cu, FILE *fp)
2056 return __class__fprintf(class, cu, NULL, fp);
2059 static size_t variable__fprintf(const struct tag *tag, const struct cu *cu,
2060 const struct conf_fprintf *conf, FILE *fp)
2062 const struct variable *var = tag__variable(tag);
2063 const char *name = variable__name(var);
2064 size_t printed = 0;
2066 if (name != NULL) {
2067 struct tag *type = cu__type(cu, var->ip.tag.type);
2068 if (type != NULL) {
2069 const char *varprefix = variable__prefix(var);
2071 if (varprefix != NULL)
2072 printed += fprintf(fp, "%s", varprefix);
2073 printed += type__fprintf(type, cu, name, conf, fp);
2076 return printed;
2079 static size_t constant__fprintf(const struct tag *tag, const struct cu *cu,
2080 const struct conf_fprintf *conf, FILE *fp)
2082 struct constant *constant = tag__constant(tag);
2083 const char *name = constant__name(constant);
2084 size_t printed = 0;
2086 if (name != NULL) {
2087 struct tag *type = cu__type(cu, constant->tag.type);
2088 if (type != NULL) {
2089 printed += fprintf(fp, "const ");
2090 printed += type__fprintf(type, cu, name, conf, fp);
2091 printed += fprintf(fp, " = %" PRIu64, constant__value(constant));
2094 return printed;
2097 static size_t namespace__fprintf(const struct tag *tag, const struct cu *cu,
2098 const struct conf_fprintf *conf, FILE *fp)
2100 struct namespace *space = tag__namespace(tag);
2101 struct conf_fprintf cconf = *conf;
2102 size_t printed = fprintf(fp, "namespace %s {\n", namespace__name(space));
2103 struct tag *pos;
2105 ++cconf.indent;
2106 cconf.no_semicolon = 0;
2108 namespace__for_each_tag(space, pos) {
2109 printed += tag__fprintf(pos, cu, &cconf, fp);
2110 printed += fprintf(fp, "\n\n");
2113 return fprintf(fp, "%.*s}", conf->indent, tabs);
2116 size_t tag__fprintf(struct tag *tag, const struct cu *cu,
2117 const struct conf_fprintf *conf, FILE *fp)
2119 size_t printed = 0;
2120 struct conf_fprintf tconf;
2121 const struct conf_fprintf *pconf = conf;
2123 if (conf == NULL) {
2124 tconf = conf_fprintf__defaults;
2125 pconf = &tconf;
2127 if (tconf.expand_types)
2128 tconf.name_spacing = 55;
2129 else if (tag__is_union(tag))
2130 tconf.name_spacing = 21;
2131 } else if (conf->name_spacing == 0 || conf->type_spacing == 0) {
2132 tconf = *conf;
2133 pconf = &tconf;
2135 if (tconf.name_spacing == 0) {
2136 if (tconf.expand_types)
2137 tconf.name_spacing = 55;
2138 else
2139 tconf.name_spacing = tag__is_union(tag) ? 21 : 23;
2141 if (tconf.type_spacing == 0)
2142 tconf.type_spacing = 26;
2145 if (pconf->expand_types)
2146 ++tag->recursivity_level;
2148 if (pconf->show_decl_info) {
2149 printed += fprintf(fp, "%.*s", pconf->indent, tabs);
2150 printed += fprintf(fp, "/* Used at: %s */\n", cu->name);
2151 printed += fprintf(fp, "%.*s", pconf->indent, tabs);
2152 printed += tag__fprintf_decl_info(tag, cu, fp);
2154 printed += fprintf(fp, "%.*s", pconf->indent, tabs);
2156 switch (tag->tag) {
2157 case DW_TAG_array_type:
2158 printed += array_type__fprintf(tag, cu, "array", pconf, fp);
2159 break;
2160 case DW_TAG_enumeration_type:
2161 printed += enumeration__fprintf(tag, pconf, fp);
2162 break;
2163 case DW_TAG_typedef:
2164 printed += typedef__fprintf(tag, cu, pconf, fp);
2165 break;
2166 case DW_TAG_class_type:
2167 case DW_TAG_interface_type:
2168 case DW_TAG_structure_type:
2169 printed += __class__fprintf(tag__class(tag), cu, pconf, fp);
2170 break;
2171 case DW_TAG_subroutine_type:
2172 printed += ftype__fprintf(tag__ftype(tag), cu, NULL, false, false, 0, true, pconf, fp);
2173 break;
2174 case DW_TAG_namespace:
2175 printed += namespace__fprintf(tag, cu, pconf, fp);
2176 break;
2177 case DW_TAG_subprogram:
2178 printed += function__fprintf(tag, cu, pconf, fp);
2179 break;
2180 case DW_TAG_union_type:
2181 printed += union__fprintf(tag__type(tag), cu, pconf, fp);
2182 break;
2183 case DW_TAG_variable:
2184 printed += variable__fprintf(tag, cu, pconf, fp);
2185 break;
2186 case DW_TAG_constant: // First seen in a Go CU
2187 printed += constant__fprintf(tag, cu, pconf, fp);
2188 break;
2189 case DW_TAG_imported_declaration:
2190 printed += imported_declaration__fprintf(tag, cu, fp);
2191 break;
2192 case DW_TAG_imported_module:
2193 printed += imported_module__fprintf(tag, cu, fp);
2194 break;
2195 default:
2196 printed += fprintf(fp, "/* %s: %s tag not supported! */",
2197 __func__, dwarf_tag_name(tag->tag));
2198 break;
2201 if (!pconf->no_semicolon) {
2202 fputc(';', fp);
2203 ++printed;
2206 if (tag__is_function(tag) && !pconf->suppress_comments) {
2207 const struct function *func = tag__function(tag);
2209 if (func->linkage_name)
2210 printed += fprintf(fp, " /* linkage=%s */", function__linkage_name(func));
2213 if (pconf->expand_types)
2214 --tag->recursivity_level;
2216 return printed;
2219 void cus__print_error_msg(const char *progname, const struct cus *cus,
2220 const char *filename, const int err)
2222 if (err == -EINVAL || (cus != NULL && cus__empty(cus)))
2223 fprintf(stderr, "%s: couldn't load debugging info from %s\n",
2224 progname, filename);
2225 else
2226 fprintf(stderr, "%s: %s\n", progname, strerror(-err));
2229 #ifndef _SC_LEVEL1_DCACHE_LINESIZE
2230 int filename__read_int(const char *filename, int *value)
2232 char line[64];
2233 int fd = open(filename, O_RDONLY), err = -1;
2235 if (fd < 0)
2236 return -1;
2238 if (read(fd, line, sizeof(line)) > 0) {
2239 *value = atoi(line);
2240 err = 0;
2243 close(fd);
2244 return err;
2246 #endif
2248 static long cacheline__size(void)
2250 #ifdef _SC_LEVEL1_DCACHE_LINESIZE
2251 return sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
2252 #else
2253 int value;
2254 return filename__read_int("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", &value) == 0 ? value : -1;
2255 #endif
2258 void dwarves__resolve_cacheline_size(const struct conf_load *conf, uint16_t user_cacheline_size)
2260 uint16_t size;
2262 if (user_cacheline_size == 0) {
2263 long sys_cacheline_size = cacheline__size();
2265 if (sys_cacheline_size > 0)
2266 size = sys_cacheline_size;
2267 else
2268 size = 64; /* Fall back to a sane value */
2269 } else
2270 size = user_cacheline_size;
2272 if (conf && conf->conf_fprintf)
2273 conf->conf_fprintf->cacheline_size = size;
2275 conf_fprintf__defaults.cacheline_size = size;