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>
17 #include <elfutils/version.h>
18 #include <sys/types.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",
84 [DW_TAG_type_unit
] = "type_unit",
85 [DW_TAG_rvalue_reference_type
] = "rvalue_reference_type",
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",
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",
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",
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
123 #ifdef STB_GNU_UNIQUE
124 DW_TAG_rvalue_reference_type
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
135 DW_TAG_GNU_formal_parameter_pack
137 DW_TAG_class_template
140 return dwarf_gnu_tag_names
[tag
- DW_TAG_MIPS_loop
];
141 else if (tag
== DW_TAG_LLVM_annotation
)
142 return "LLVM_annotation";
146 static struct conf_fprintf conf_fprintf__defaults
= {
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
)
188 case DW_TAG_inheritance
:
190 a
= tag__class_member(tag
)->accessibility
;
192 case DW_TAG_subprogram
:
193 a
= tag__function(tag
)->accessibility
;
200 case DW_ACCESS_public
: return "public";
201 case DW_ACCESS_private
: return "private";
202 case DW_ACCESS_protected
: return "protected";
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
));
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
,
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
,
237 struct array_type
*at
= tag__array_type(tag
);
238 struct tag
*type
= cu__type(cu
, tag
->type
);
240 unsigned long long flat_dimensions
= 0;
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)
260 if (!flat_dimensions
)
261 flat_dimensions
= at
->nr_entries
[i
];
263 flat_dimensions
*= at
->nr_entries
[i
];
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
]);
270 printed
+= fprintf(fp
, "[]");
275 type
= tag__follow_typedef(tag
, cu
);
277 if (flat_dimensions
== 0)
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
);
287 printed
+= fprintf(fp
, "[]");
293 static size_t string_type__fprintf(const struct tag
*tag
, const char *name
,
294 const struct conf_fprintf
*conf
,
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:
307 * I.e. a variable or a class member, or:
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;
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
;
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?
348 return printed
+ fprintf(fp
, "void %s", type__name(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 ");
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 */
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
)
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
)
419 size_t printed
= fprintf(fp
, "using ::");
420 const struct tag
*decl
= cu__function(cu
, tag
->type
);
423 decl
= cu__tag(cu
, tag
->type
);
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
)
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
;
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");
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.
480 type__for_each_enumerator(type
, pos
) {
481 printed
+= fprintf(fp
, "%.*s\t%-*s = ", indent
, tabs
,
482 max_entry_name_len
, enumerator__name(pos
));
484 printed
+= fprintf(fp
, "%#llx", (unsigned long long)pos
->value
);
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__))");
501 printed
+= fprintf(fp
, " %s", conf
->suffix
);
506 static const char *tag__prefix(const struct cu
*cu
, const uint32_t tag
,
507 const struct conf_fprintf
*conf
)
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 " :
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 " &";
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
);
536 const struct tag
*type
= cu__type(cu
, tag
->type
);
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
)) {
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 ";
555 snprintf(bf
, len
, "%s %s%s",
556 __tag__name(type
, cu
,
557 tmpbf
, sizeof(tmpbf
), conf
),
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
)
571 const struct conf_fprintf
*pconf
= conf
?: &conf_fprintf__defaults
;
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!";
582 name
= base_type__name(tag__base_type(tag
), bf2
, sizeof(bf2
));
584 strncpy(bf
, name
, len
);
587 case DW_TAG_subprogram
:
588 strncpy(bf
, function__name(tag__function(tag
)), len
);
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
: {
596 type_id_t id
= tag__ptr_to_member_type(tag
)->containing_type
;
598 type
= cu__type(cu
, id
);
600 snprintf(suffix
, sizeof(suffix
), "%s::*", class__name(tag__class(type
)));
602 size_t l
= tag__id_not_found_snprintf(suffix
,
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
)) {
620 const char *prefix
= "", *suffix
= "",
621 *type_str
= __tag__name(type
, cu
, tmpbf
,
624 if (!pconf
->skip_emitting_modifier
) {
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
? "" : " ");
636 case DW_TAG_array_type
:
637 type
= cu__type(cu
, tag
->type
);
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
);
643 case DW_TAG_subroutine_type
: {
644 FILE *bfp
= fmemopen(bf
, len
, "w");
647 ftype__fprintf(tag__ftype(tag
), cu
, NULL
, 0, 0, 0, true, pconf
, bfp
);
650 snprintf(bf
, len
, "<ERROR(%s): fmemopen failed!>",
655 snprintf(bf
, len
, "%s", class_member__name(tag__class_member(tag
)));
657 case DW_TAG_variable
:
658 snprintf(bf
, len
, "%s", variable__name(tag__variable(tag
)));
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
);
668 snprintf(bf
, len
, "%s%s", tag__prefix(cu
, tag
->tag
, pconf
),
669 type__name(tag__type(tag
)) ?: "");
676 const char *tag__name(const struct tag
*tag
, const struct cu
*cu
,
677 char *bf
, size_t len
, const struct conf_fprintf
*conf
)
682 strncpy(bf
, "void", len
);
686 __tag__name(tag
, cu
, bf
+ printed
, len
- printed
, conf
);
691 static const char *variable__prefix(const struct variable
*var
)
693 switch (variable__scope(var
)) {
694 case VSCOPE_REGISTER
:
697 if (var
->external
&& var
->declaration
)
705 case VSCOPE_OPTIMIZED
:
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
);
721 printed
+= fprintf(fp
, " */\n");
726 static type_id_t
skip_llvm_annotations(const struct cu
*cu
, type_id_t id
)
733 type
= cu__type(cu
, id
);
734 if (type
== NULL
|| type
->tag
!= DW_TAG_LLVM_annotation
|| type
->type
== id
)
742 static size_t type__fprintf(struct tag
*type
, const struct cu
*cu
,
743 const char *name
, const struct conf_fprintf
*conf
,
750 struct tag
*type_expanded
= NULL
;
751 struct conf_fprintf tconf
= {
752 .type_spacing
= conf
->type_spacing
,
755 int expand_types
= conf
->expand_types
;
756 int suppress_offset_comment
= conf
->suppress_offset_comment
;
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
);
767 goto out_type_not_found
;
769 printed
= tag__has_type_loop(type
, ttype
,
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';
788 expand_types
= nr_indirections
;
789 if (!suppress_offset_comment
)
790 suppress_offset_comment
= !!nr_indirections
;
793 if (type
->recursivity_level
!= 0)
795 ++type
->recursivity_level
;
796 type_expanded
= type
;
800 int typedef_expanded
= 0;
802 while (tag__is_typedef(type
)) {
803 struct tag
*type_type
;
806 ctype
= tag__type(type
);
807 if (typedef_expanded
)
808 printed
+= fprintf(fp
, " -> %s", type__name(ctype
));
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
);
821 if (typedef_expanded
)
822 printed
+= fprintf(fp
, " */ ");
827 if (tag__is_struct(type
) || tag__is_union(type
) ||
828 tag__is_enumeration(type
)) {
832 tconf
.emit_stats
= 0;
833 tconf
.suppress_offset_comment
= suppress_offset_comment
;
836 const char *modifier
;
840 case DW_TAG_pointer_type
: {
841 type_id_t ptype_id
= skip_llvm_annotations(cu
, type
->type
);
845 struct tag
*ptype
= cu__type(cu
, ptype_id
);
847 goto out_type_not_found
;
848 n
= tag__has_type_loop(type
, ptype
, NULL
, 0, fp
);
851 if (ptype
->tag
== DW_TAG_subroutine_type
) {
852 printed
+= ftype__fprintf(tag__ftype(ptype
),
854 tconf
.type_spacing
, true,
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;
866 tconf
.type_spacing
-= 8;
874 printed
+= fprintf(fp
, "%-*s %s", tconf
.type_spacing
,
875 tag__name(type
, cu
, tbf
, sizeof(tbf
), &tconf
),
878 case DW_TAG_subroutine_type
:
879 printed
+= ftype__fprintf(tag__ftype(type
), cu
, name
, 0, 0,
880 tconf
.type_spacing
, true, &tconf
, fp
);
882 case DW_TAG_atomic_type
:
883 modifier
= "_Atomic";
885 case DW_TAG_const_type
:
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
);
902 case DW_TAG_array_type
:
903 printed
+= array_type__fprintf(type
, cu
, name
, &tconf
, fp
);
905 case DW_TAG_string_type
:
906 printed
+= string_type__fprintf(type
, name
, &tconf
, fp
);
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
?: "");
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
);
928 case DW_TAG_union_type
:
929 printed
+= union_decl__fprintf(type
, cu
, name
, &tconf
, fp
);
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
?: "");
937 printed
+= enumeration__fprintf(type
, &tconf
, fp
);
939 case DW_TAG_LLVM_annotation
: {
940 struct tag
*ttype
= cu__type(cu
, type
->type
);
945 goto out_type_not_found
;
950 --type_expanded
->recursivity_level
;
954 printed
= fprintf(fp
, "%-*s%s> %s", tconf
.type_spacing
, "<ERROR",
955 name
== namebfptr
? ": pointer to pointer to inner struct/union/enum?" : "", name
);
959 static size_t class__fprintf_cacheline_boundary(struct conf_fprintf
*conf
,
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
),
975 if (!sconf
.rel_offset
) {
976 offset
+= sconf
.base_offset
;
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
) {
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
);
1003 if (!type__name(tag__type(type
)) || sconf
.expand_types
)
1004 printed
+= fprintf(fp
, " ");
1005 printed
+= fprintf(fp
, "%s", name
);
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
;
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__))");
1040 printed
+= fprintf(fp
, sconf
.hex_fmt
?
1043 (sconf
.type_spacing
+
1044 sconf
.name_spacing
- slen
- 3),
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
);
1057 printed
+= fprintf(fp
, sconf
.hex_fmt
? " %#*x */" : " %*u */", size_spacing
, size
);
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
, " */");
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, " ",
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
?
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
;
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
) ?: "");
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
);
1163 uconf
.union_member
= 1;
1164 printed
+= fprintf(fp
, "%.*s", uconf
.indent
, tabs
);
1165 printed
+= union_member__fprintf(pos
, pos_type
, cu
, &uconf
, fp
);
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");
1183 ftype__fprintf(&func
->proto
, cu
, NULL
, 0, 0, 0, true, conf
,
1187 if (conf
->skip_emitting_errors
)
1189 snprintf(bf
, len
, "<ERROR(%s): fmemopen failed!>", __func__
);
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
,
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
;
1210 const char *name
, *stype
;
1211 size_t printed
= fprintf(fp
, "(");
1213 ftype__for_each_parameter(ftype
, pos
) {
1216 printed
+= fprintf(fp
, ", ");
1218 printed
+= fprintf(fp
, ",\n%.*s",
1222 name
= conf
->no_parm_names
? NULL
: parameter__name(pos
);
1223 type
= cu__type(cu
, pos
->tag
.type
);
1225 snprintf(sbf
, sizeof(sbf
),
1226 "<ERROR: type %d not found>", pos
->tag
.type
);
1230 if (tag__is_pointer(type
)) {
1231 if (type
->type
!= 0) {
1233 struct tag
*ptype
= cu__type(cu
, type
->type
);
1234 if (ptype
== NULL
) {
1236 tag__id_not_found_fprintf(fp
, type
->type
);
1239 n
= tag__has_type_loop(type
, ptype
, NULL
, 0, fp
);
1242 if (ptype
->tag
== DW_TAG_subroutine_type
) {
1244 ftype__fprintf(tag__ftype(ptype
),
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
);
1255 stype
= tag__name(type
, cu
, sbf
, sizeof(sbf
), conf
);
1257 printed
+= fprintf(fp
, "%s%s%s", stype
, name
? " " : "",
1261 /* No parameters? */
1263 printed
+= fprintf(fp
, "void)");
1264 else if (ftype
->unspec_parms
)
1265 printed
+= fprintf(fp
, ", ...)");
1267 printed
+= fprintf(fp
, ")");
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
)
1276 size_t printed
= 0, n
;
1277 const void *vtag
= tag
;
1280 if (indent
>= sizeof(tabs
))
1281 indent
= sizeof(tabs
) - 1;
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
);
1291 if (alias
== NULL
) {
1292 printed
+= tag__id_not_found_fprintf(fp
, exp
->ip
.tag
.type
);
1295 printed
= fprintf(fp
, "%.*s", indent
, tabs
);
1296 name
= function__name(alias
);
1297 n
= fprintf(fp
, "%s", name
);
1300 namelen
= strlen(name
);
1301 n
+= ftype__fprintf_parms(&alias
->proto
, cu
,
1302 indent
+ (namelen
+ 7) / 8,
1304 n
+= fprintf(fp
, "; /* size=%zd, low_pc=%#llx */",
1305 exp
->size
, (unsigned long long)exp
->ip
.addr
);
1307 n
= fprintf(fp
, "%s(); /* size=%zd, low_pc=%#llx */",
1308 function__name(alias
), exp
->size
,
1309 (unsigned long long)exp
->ip
.addr
);
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
));
1324 case DW_TAG_label
: {
1325 const struct label
*label
= vtag
;
1326 printed
= fprintf(fp
, "%.*s", indent
, tabs
);
1329 c
= fprintf(fp
, "%s:", label__name(label
));
1333 case DW_TAG_lexical_block
:
1334 printed
= lexblock__fprintf(vtag
, cu
, function
, indent
,
1339 printed
= fprintf(fp
, "%.*s", indent
, tabs
);
1340 n
= fprintf(fp
, "%s <%llx>", dwarf_tag_name(tag
->tag
),
1341 tag__orig_id(tag
, cu
));
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
)
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
;
1364 printed
+= fprintf(fp
, " /* low_pc=%#llx */",
1365 (unsigned long long)block
->ip
.addr
);
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,
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
);
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
);
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
;
1407 bool inlined
= !conf
->strip_inline
&& function__declared_inline(func
);
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");
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
,
1451 int indent
= conf
->indent
;
1452 uint32_t cacheline
= offset
/ conf_fprintf__cacheline_size(conf
);
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
);
1464 printed
+= fprintf(fp
, "/* --- cacheline %u boundary "
1465 "(%u bytes) was %u byte%s ago --- "
1467 cacheline_in_bytes
, cacheline_pos
,
1468 cacheline_pos
> 1 ? "s" : "");
1470 printed
+= fprintf(fp
, "%.*s", indent
, tabs
);
1472 *conf
->cachelinep
= cacheline
;
1477 static size_t class__vtable_fprintf(struct class *class, const struct conf_fprintf
*conf
, FILE *fp
)
1479 struct function
*pos
;
1482 if (class->nr_vtable_entries
== 0)
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
);
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
)
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
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
)
1538 if (!(*newline
)++) {
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
;
1551 if (has_embedded_flexible_array
) {
1552 printed
+= fprintf(fp
, "%s embedded flexible array(s)", first
? "" : ",");
1553 ++holes
->nr_embedded_flexible_array_members
;
1558 ++holes
->nr_paddings
;
1559 holes
->sum_paddings
+= padding
;
1561 printed
+= fprintf(fp
, "%s %d byte%s of padding", first
? "" : ",", padding
, padding
!= 1 ? "s" : "");
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" : "");
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" : "");
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;
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" :
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
)
1640 printed
+= fprintf(fp
, " :");
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
)));
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
) {
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
) {
1681 printed
+= fprintf(fp
, "%.*s/* XXX %d byte%s hole, "
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
,
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");
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.
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
);
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
);
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
1760 pos
->bitfield_size
!= 0)) {
1761 if (!cconf
.suppress_comments
) {
1766 printed
+= fprintf(fp
, "%.*s/* Bitfield combined"
1767 " with previous fields */\n",
1768 cconf
.indent
, tabs
);
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
) {
1780 printed
+= fprintf(fp
, "%.*s/* Bitfield combined"
1781 " with next fields */\n",
1782 cconf
.indent
, tabs
);
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
);
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
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
) {
1825 printed
+= fprintf(fp
, "\n%.*s/* XXX %d bit%s hole, "
1826 "try to pack */", cconf
.indent
, tabs
,
1828 pos
->bit_hole
!= 1 ? "s" : "");
1829 sum_bit_holes
+= pos
->bit_hole
;
1832 if (pos
->hole
> 0 && !cconf
.suppress_comments
) {
1837 printed
+= fprintf(fp
, "\n%.*s/* XXX %d byte%s hole, "
1839 cconf
.indent
, tabs
, pos
->hole
,
1840 pos
->hole
!= 1 ? "s" : "");
1841 sum_holes
+= pos
->hole
;
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
)
1856 if (pos
->bitfield_size
) {
1857 sum_bits
+= pos
->bitfield_size
;
1862 if (last
== NULL
|| /* First member */
1864 * Last member was a zero sized array, typedef, struct, etc
1868 * We moved to a new offset
1870 last
->byte_offset
!= pos
->byte_offset
) {
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.
1885 * int b:1; / 0:23 4 /
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
) {
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
)
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
);
1930 printed
+= fprintf(fp
, ", holes: %d, sum holes: %u",
1931 class->nr_holes
, sum_holes
);
1932 printed
+= fprintf(fp
, " */\n");
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
);
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",
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) {
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
);
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
);
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: "
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",
1982 class->bit_padding
);
1983 if (!cconf
.suppress_aligned_attribute
&& nr_forced_alignments
!= 0) {
1984 printed
+= fprintf(fp
, "%.*s/* forced alignments: %u",
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
);
2012 printed
+= fprintf(fp
, "%.*s/* last cacheline: %u bytes */\n",
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",
2021 class_member__name(m
), m
->byte_offset
,
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",
2032 type
->size
, sum_bytes
, sum_bits
, sum_holes
, sum_bit_holes
, size_diff
);
2034 printed
+= fprintf(fp
, "%.*s}", indent
, tabs
);
2036 if (class->is_packed
&& !cconf
.suppress_packed
)
2037 printed
+= fprintf(fp
, " __attribute__((__packed__))");
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
);
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
);
2067 struct tag
*type
= cu__type(cu
, var
->ip
.tag
.type
);
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
);
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
);
2087 struct tag
*type
= cu__type(cu
, constant
->tag
.type
);
2089 printed
+= fprintf(fp
, "const ");
2090 printed
+= type__fprintf(type
, cu
, name
, conf
, fp
);
2091 printed
+= fprintf(fp
, " = %" PRIu64
, constant__value(constant
));
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
));
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
)
2120 struct conf_fprintf tconf
;
2121 const struct conf_fprintf
*pconf
= conf
;
2124 tconf
= conf_fprintf__defaults
;
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) {
2135 if (tconf
.name_spacing
== 0) {
2136 if (tconf
.expand_types
)
2137 tconf
.name_spacing
= 55;
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
);
2157 case DW_TAG_array_type
:
2158 printed
+= array_type__fprintf(tag
, cu
, "array", pconf
, fp
);
2160 case DW_TAG_enumeration_type
:
2161 printed
+= enumeration__fprintf(tag
, pconf
, fp
);
2163 case DW_TAG_typedef
:
2164 printed
+= typedef__fprintf(tag
, cu
, pconf
, fp
);
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
);
2171 case DW_TAG_subroutine_type
:
2172 printed
+= ftype__fprintf(tag__ftype(tag
), cu
, NULL
, false, false, 0, true, pconf
, fp
);
2174 case DW_TAG_namespace
:
2175 printed
+= namespace__fprintf(tag
, cu
, pconf
, fp
);
2177 case DW_TAG_subprogram
:
2178 printed
+= function__fprintf(tag
, cu
, pconf
, fp
);
2180 case DW_TAG_union_type
:
2181 printed
+= union__fprintf(tag__type(tag
), cu
, pconf
, fp
);
2183 case DW_TAG_variable
:
2184 printed
+= variable__fprintf(tag
, cu
, pconf
, fp
);
2186 case DW_TAG_constant
: // First seen in a Go CU
2187 printed
+= constant__fprintf(tag
, cu
, pconf
, fp
);
2189 case DW_TAG_imported_declaration
:
2190 printed
+= imported_declaration__fprintf(tag
, cu
, fp
);
2192 case DW_TAG_imported_module
:
2193 printed
+= imported_module__fprintf(tag
, cu
, fp
);
2196 printed
+= fprintf(fp
, "/* %s: %s tag not supported! */",
2197 __func__
, dwarf_tag_name(tag
->tag
));
2201 if (!pconf
->no_semicolon
) {
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
;
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
);
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
)
2233 int fd
= open(filename
, O_RDONLY
), err
= -1;
2238 if (read(fd
, line
, sizeof(line
)) > 0) {
2239 *value
= atoi(line
);
2248 static long cacheline__size(void)
2250 #ifdef _SC_LEVEL1_DCACHE_LINESIZE
2251 return sysconf(_SC_LEVEL1_DCACHE_LINESIZE
);
2254 return filename__read_int("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", &value
) == 0 ? value
: -1;
2258 void dwarves__resolve_cacheline_size(const struct conf_load
*conf
, uint16_t user_cacheline_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
;
2268 size
= 64; /* Fall back to a sane value */
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
;