In recent discussion in BPF mailing list ([1]) participants agreed to add a new DWARF representation for "btf_type_tag" annotations. The agreed representation of void pointers uses unspecified types. For example, consider the following C code: struct alpha { void __attribute__((btf_type_tag("__alpha_a"))) *a; } g; And corresponding DWARF: 0x29: DW_TAG_structure_type DW_AT_name ("alpha") 0x2e: DW_TAG_member DW_AT_name ("a") DW_AT_type (0x38 "void *") 0x38: DW_TAG_pointer_type DW_AT_type (0x41 "void") 0x41: DW_TAG_unspecified_type DW_AT_name ("void") 0x43: DW_TAG_LLVM_annotation DW_AT_name ("btf:type_tag") DW_AT_const_value ("__alpha_a") This is a preparatory patch for new type tags representation support, specifically it adds `struct unspecified_type` and a new `cu` field `struct cu::unspecified_types`. These would be used in a subsequent patch to recode type tags attached to DW_TAG_unspecified_type as in the example above. [1] Mailing list discussion regarding `btf:type_tag` Various approaches are discussed, Solution #2 is accepted https://lore.kernel.org/bpf/87r0w9jjoq.fsf@xxxxxxxxxx/ Signed-off-by: Eduard Zingerman <eddyz87@xxxxxxxxx> --- dwarf_loader.c | 36 ++++++++++++++++++++++++++++++++++-- dwarves.c | 1 + dwarves.h | 17 +++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/dwarf_loader.c b/dwarf_loader.c index ccf3194..dfed334 100644 --- a/dwarf_loader.c +++ b/dwarf_loader.c @@ -165,14 +165,19 @@ static struct dwarf_cu *dwarf_cu__new(struct cu *cu) return dwarf_cu; } +static void unspecified_type__delete(struct cu *cu, struct unspecified_type *utype); + static void dwarf_cu__delete(struct cu *cu) { if (cu == NULL || cu->priv == NULL) return; struct dwarf_cu *dcu = cu->priv; + struct list_head *pos, *n; // dcu->hash_tags & dcu->hash_types are on cu->obstack + list_for_each_safe(pos, n, &cu->unspecified_types) + unspecified_type__delete(cu, container_of(pos, struct unspecified_type, node)); cu__free(cu, dcu); cu->priv = NULL; } @@ -1386,6 +1391,33 @@ static struct tag *die__create_new_tag(Dwarf_Die *die, struct cu *cu) return tag; } +static struct tag *die__create_new_unspecified_type(Dwarf_Die *die, struct cu *cu, + struct conf_load *conf) +{ + struct unspecified_type *tag; + + tag = tag__alloc_with_spec(cu, sizeof(struct unspecified_type)); + if (tag == NULL) + return NULL; + + tag__init(&tag->tag, cu, die); + INIT_LIST_HEAD(&tag->node); + + tag->name = attr_string(die, DW_AT_name, conf); + + list_add(&tag->node, &cu->unspecified_types); + + return &tag->tag; +} + +static void unspecified_type__delete(struct cu *cu, struct unspecified_type *utype) +{ + struct dwarf_tag *dtag = utype->tag.priv; + + cu__free(cu, dtag); + cu__free(cu, utype); +} + static struct btf_type_tag_ptr_type *die__create_new_btf_type_tag_ptr_type(Dwarf_Die *die, struct cu *cu) { struct btf_type_tag_ptr_type *tag; @@ -2186,10 +2218,10 @@ static struct tag *__die__process_tag(Dwarf_Die *die, struct cu *cu, case DW_TAG_volatile_type: case DW_TAG_atomic_type: tag = die__create_new_tag(die, cu); break; - case DW_TAG_unspecified_type: - tag = die__create_new_tag(die, cu); break; case DW_TAG_pointer_type: tag = die__create_new_pointer_tag(die, cu, conf); break; + case DW_TAG_unspecified_type: + tag = die__create_new_unspecified_type(die, cu, conf); break; case DW_TAG_ptr_to_member_type: tag = die__create_new_ptr_to_member_type(die, cu); break; case DW_TAG_enumeration_type: diff --git a/dwarves.c b/dwarves.c index ed5c348..f989250 100644 --- a/dwarves.c +++ b/dwarves.c @@ -681,6 +681,7 @@ struct cu *cu__new(const char *name, uint8_t addr_size, cu->dfops = NULL; INIT_LIST_HEAD(&cu->tags); INIT_LIST_HEAD(&cu->tool_list); + INIT_LIST_HEAD(&cu->unspecified_types); cu->addr_size = addr_size; cu->extra_dbg_info = 0; diff --git a/dwarves.h b/dwarves.h index 54771d1..509ffbc 100644 --- a/dwarves.h +++ b/dwarves.h @@ -246,6 +246,7 @@ struct cu { struct list_head node; struct list_head tags; struct list_head tool_list; /* To be used by tools such as ctracer */ + struct list_head unspecified_types; struct ptr_table types_table; struct ptr_table functions_table; struct ptr_table tags_table; @@ -686,6 +687,22 @@ static inline struct btf_type_tag_type *tag__btf_type_tag(struct tag *tag) return (struct btf_type_tag_type *)tag; } +/** struct unspecified_type - representation of DW_TAG_unspecified_type. + * + * @name - DW_AT_name associated with this tag + * @node - a node for cu::unspecified_types list + */ +struct unspecified_type { + struct tag tag; + const char *name; + struct list_head node; +}; + +static inline struct unspecified_type *tag__unspecified_type(struct tag *tag) +{ + return (struct unspecified_type *)tag; +} + /** struct namespace - base class for enums, structs, unions, typedefs, etc * * @tags - class_member, enumerators, etc -- 2.40.1