Recursively expand DWARF structure types, i.e. structs, unions, and enums. Also include relevant DWARF attributes in type strings to encode structure layout, for example. Example output with --debug: subprogram( formal_parameter pointer_type *mut &str { structure_type &str { member pointer_type <unnamed> { base_type u8 byte_size(1) encoding(7) } data_member_location(0), member base_type usize byte_size(8) encoding(7) data_member_location(8), } byte_size(16) alignment(8) }, ) -> base_type void; Signed-off-by: Sami Tolvanen <samitolvanen@xxxxxxxxxx> --- scripts/gendwarfksyms/dwarf.c | 129 +++++++++++++++++++++++++- scripts/gendwarfksyms/gendwarfksyms.h | 5 + 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 4ec69fce95f3..92b6ca4c5c91 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -206,9 +206,13 @@ static int process_fqn(struct state *state, struct die *cache, Dwarf_Die *die) return 0; \ } +DEFINE_PROCESS_UDATA_ATTRIBUTE(accessibility) DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment) +DEFINE_PROCESS_UDATA_ATTRIBUTE(bit_size) DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size) DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) +DEFINE_PROCESS_UDATA_ATTRIBUTE(data_bit_offset) +DEFINE_PROCESS_UDATA_ATTRIBUTE(data_member_location) /* Match functions -- die_match_callback_t */ #define DEFINE_MATCH(type) \ @@ -217,8 +221,11 @@ DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) return dwarf_tag(die) == DW_TAG_##type##_type; \ } +DEFINE_MATCH(enumerator) DEFINE_MATCH(formal_parameter) +DEFINE_MATCH(member) DEFINE_MATCH(subrange) +DEFINE_MATCH(variant) bool match_all(Dwarf_Die *die) { @@ -263,6 +270,10 @@ static int __process_list_type(struct state *state, struct die *cache, { check(process(state, cache, type)); check(process_type_attr(state, cache, die)); + check(process_accessibility_attr(state, cache, die)); + check(process_bit_size_attr(state, cache, die)); + check(process_data_bit_offset_attr(state, cache, die)); + check(process_data_member_location_attr(state, cache, die)); check(process(state, cache, ",")); return check(process_linebreak(cache, 0)); } @@ -275,6 +286,7 @@ static int __process_list_type(struct state *state, struct die *cache, } DEFINE_PROCESS_LIST_TYPE(formal_parameter) +DEFINE_PROCESS_LIST_TYPE(member) /* Container types with DW_AT_type */ static int __process_type(struct state *state, struct die *cache, @@ -307,6 +319,7 @@ DEFINE_PROCESS_TYPE(reference) DEFINE_PROCESS_TYPE(restrict) DEFINE_PROCESS_TYPE(rvalue_reference) DEFINE_PROCESS_TYPE(shared) +DEFINE_PROCESS_TYPE(template_type_parameter) DEFINE_PROCESS_TYPE(volatile) DEFINE_PROCESS_TYPE(typedef) @@ -361,6 +374,108 @@ static int process_subroutine_type(struct state *state, struct die *cache, return check(__process_subroutine_type(state, cache, die, "subroutine_type")); } +static int process_variant_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + return check(process_die_container(state, cache, die, process_type, + match_member_type)); +} + +static int process_variant_part_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + check(process(state, cache, "variant_part {")); + check(process_linebreak(cache, 1)); + check(process_die_container(state, cache, die, process_type, + match_variant_type)); + check(process_linebreak(cache, -1)); + check(process(state, cache, "},")); + return check(process_linebreak(cache, 0)); +} + +static int ___process_structure_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + switch (dwarf_tag(die)) { + case DW_TAG_member: + case DW_TAG_variant_part: + return check(process_type(state, cache, die)); + case DW_TAG_class_type: + case DW_TAG_enumeration_type: + case DW_TAG_structure_type: + case DW_TAG_template_type_parameter: + case DW_TAG_union_type: + check(process_type(state, cache, die)); + check(process(state, cache, ",")); + return check(process_linebreak(cache, 0)); + case DW_TAG_subprogram: + return 0; /* Skip member functions */ + default: + error("unexpected structure_type child: %x", dwarf_tag(die)); + return -1; + } +} + +static int __process_structure_type(struct state *state, struct die *cache, + Dwarf_Die *die, const char *type, + die_callback_t process_func, + die_match_callback_t match_func) +{ + check(process(state, cache, type)); + check(process_fqn(state, cache, die)); + check(process(state, cache, " {")); + check(process_linebreak(cache, 1)); + + check(process_die_container(state, cache, die, process_func, + match_func)); + + check(process_linebreak(cache, -1)); + check(process(state, cache, "}")); + + check(process_byte_size_attr(state, cache, die)); + check(process_alignment_attr(state, cache, die)); + + return 0; +} + +#define DEFINE_PROCESS_STRUCTURE_TYPE(structure) \ + static int process_##structure##_type( \ + struct state *state, struct die *cache, Dwarf_Die *die) \ + { \ + return check(__process_structure_type( \ + state, cache, die, #structure "_type ", \ + ___process_structure_type, match_all)); \ + } + +DEFINE_PROCESS_STRUCTURE_TYPE(class) +DEFINE_PROCESS_STRUCTURE_TYPE(structure) +DEFINE_PROCESS_STRUCTURE_TYPE(union) + +static int process_enumerator_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + Dwarf_Word value; + + check(process(state, cache, "enumerator ")); + check(process_fqn(state, cache, die)); + + if (get_udata_attr(die, DW_AT_const_value, &value)) { + check(process(state, cache, " = ")); + check(process_fmt(state, cache, "%" PRIu64, value)); + } + + check(process(state, cache, ",")); + return check(process_linebreak(cache, 0)); +} + +static int process_enumeration_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + return check(__process_structure_type(state, cache, die, + "enumeration_type ", process_type, + match_enumerator_type)); +} + static int process_base_type(struct state *state, struct die *cache, Dwarf_Die *die) { @@ -438,17 +553,27 @@ static int process_type(struct state *state, struct die *parent, Dwarf_Die *die) PROCESS_TYPE(rvalue_reference) PROCESS_TYPE(shared) PROCESS_TYPE(volatile) + /* Container types */ + PROCESS_TYPE(class) + PROCESS_TYPE(structure) + PROCESS_TYPE(union) + PROCESS_TYPE(enumeration) /* Subtypes */ + PROCESS_TYPE(enumerator) PROCESS_TYPE(formal_parameter) + PROCESS_TYPE(member) PROCESS_TYPE(subrange) + PROCESS_TYPE(template_type_parameter) + PROCESS_TYPE(variant) + PROCESS_TYPE(variant_part) /* Other types */ PROCESS_TYPE(array) PROCESS_TYPE(base) PROCESS_TYPE(subroutine) PROCESS_TYPE(typedef) default: - debug("unimplemented type: %x", tag); - break; + error("unexpected type: %x", tag); + return -1; } /* Update cache state and append to the parent (if any) */ diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/gendwarfksyms.h index 25f87485eb69..7d32ccd590f8 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -59,8 +59,13 @@ extern bool debug; #define checkp(expr) __check(expr, __res < 0, __res) /* Consistent aliases (DW_TAG_<type>_type) for DWARF tags */ +#define DW_TAG_enumerator_type DW_TAG_enumerator #define DW_TAG_formal_parameter_type DW_TAG_formal_parameter +#define DW_TAG_member_type DW_TAG_member +#define DW_TAG_template_type_parameter_type DW_TAG_template_type_parameter #define DW_TAG_typedef_type DW_TAG_typedef +#define DW_TAG_variant_part_type DW_TAG_variant_part +#define DW_TAG_variant_type DW_TAG_variant /* * symbols.c -- 2.46.0.184.g6999bdac58-goog