@@ -117,6 +117,29 @@ static void dwarf_tag__set_spec(struct dwarf_tag *dtag, dwarf_off_ref spec)
117117 * (dwarf_off_ref * )(dtag + 1 ) = spec ;
118118}
119119
120+ enum type_tag_kind {
121+ /* Corresponds to type tags of form:
122+ *
123+ * DW_TAG_LLVM_annotation
124+ * DW_AT_name ("btf:type_tag")
125+ * DW_AT_const_value ("...")
126+ *
127+ * Such entries could be subordinate to any DWARF type.
128+ * The tag applies to the parent type.
129+ */
130+ TYPE_TAG_SELF = 1u ,
131+ /* Corresponds to type tags of form:
132+ *
133+ * DW_TAG_LLVM_annotation
134+ * DW_AT_name ("btf_type_tag")
135+ * DW_AT_const_value ("...")
136+ *
137+ * Such entries are subordinate to DW_TAG_pointer_type type only.
138+ * The tag applies to DW_AT_type of the pointer.
139+ */
140+ TYPE_TAG_POINTEE = 2u
141+ };
142+
120143struct dwarf_cu {
121144 struct hlist_head * hash_tags ;
122145 struct hlist_head * hash_types ;
@@ -125,6 +148,7 @@ struct dwarf_cu {
125148 struct dwarf_tag * last_type_lookup ;
126149 struct cu * cu ;
127150 struct dwarf_cu * type_unit ;
151+ enum type_tag_kind effective_type_tag_kind ;
128152};
129153
130154static int dwarf_cu__init (struct dwarf_cu * dcu , struct cu * cu )
@@ -153,6 +177,7 @@ static int dwarf_cu__init(struct dwarf_cu *dcu, struct cu *cu)
153177 // To avoid a per-lookup check against NULL in dwarf_cu__find_type_by_ref()
154178 dcu -> last_type_lookup = & sentinel_dtag ;
155179 ptr_table__init (& dcu -> type_tags );
180+ dcu -> effective_type_tag_kind = TYPE_TAG_POINTEE ;
156181 return 0 ;
157182}
158183
@@ -232,6 +257,20 @@ static void cu__hash(struct cu *cu, struct tag *tag)
232257 hashtags__hash (hashtable , tag -> priv );
233258}
234259
260+ /* Change impostor->priv->id to match tag->priv->id and replace `tag`
261+ * by `impostor` in the `cu` types/tags table.
262+ */
263+ static void cu__hash_impersonate (struct cu * cu , struct tag * tag , struct tag * impostor )
264+ {
265+ struct dwarf_tag * dimpostor = impostor -> priv ;
266+ struct dwarf_tag * dtag = tag -> priv ;
267+
268+ hlist_del_init (& dimpostor -> hash_node );
269+ hlist_del_init (& dtag -> hash_node );
270+ dimpostor -> id = dtag -> id ;
271+ cu__hash (cu , impostor );
272+ }
273+
235274static struct dwarf_tag * dwarf_cu__find_tag_by_ref (const struct dwarf_cu * cu ,
236275 const struct dwarf_off_ref * ref )
237276{
@@ -980,28 +1019,34 @@ static void type_tags_writer__init(struct type_tags_writer *writer,
9801019 * treat `writer->dcu->type_tags` as a stream of records with the
9811020 * following format:
9821021 *
983- * ... parent-pointer tag-value* NULL ...
984- * ^ ^ ^
985- * | | '----- terminator
986- * struct tag* char*
1022+ * ... parent-pointer ( tag-value tag-kind) * NULL ...
1023+ * ^ ^ ^ ^
1024+ * | | | '----- terminator
1025+ * struct tag* char* enum type_tag_kind
9871026 */
9881027static int add_btf_type_tag (struct type_tags_writer * writer , Dwarf_Die * die ,
9891028 struct conf_load * conf )
9901029{
9911030 struct ptr_table * type_tags = & writer -> dcu -> type_tags ;
9921031 const char * name , * value ;
1032+ uintptr_t kind = 0 ;
9931033 uint32_t ignored ;
9941034 int ret = 0 ;
9951035
9961036 if (conf -> skip_encoding_btf_type_tag )
9971037 return 0 ;
9981038
9991039 name = attr_string (die , DW_AT_name , conf );
1000- if (strcmp (name , "btf_type_tag" ) != 0 )
1040+ kind = strcmp (name , "btf_type_tag" ) == 0 ? TYPE_TAG_POINTEE : kind ;
1041+ kind = strcmp (name , "btf:type_tag" ) == 0 ? TYPE_TAG_SELF : kind ;
1042+ if (!kind )
10011043 return 0 ;
10021044
10031045 value = attr_string (die , DW_AT_const_value , conf );
10041046
1047+ if (kind == TYPE_TAG_SELF )
1048+ writer -> dcu -> effective_type_tag_kind = TYPE_TAG_SELF ;
1049+
10051050 if (!writer -> started ) {
10061051 writer -> started = true;
10071052 /* Terminate previous record */
@@ -1016,7 +1061,11 @@ static int add_btf_type_tag(struct type_tags_writer *writer, Dwarf_Die *die,
10161061 return ret ;
10171062 }
10181063
1019- return ptr_table__add (type_tags , (void * )value , & ignored );
1064+ ret = ptr_table__add (type_tags , (void * )value , & ignored );
1065+ if (ret )
1066+ return ret ;
1067+
1068+ return ptr_table__add (type_tags , (void * )kind , & ignored );
10201069}
10211070
10221071/* Collect all type tag values attached to `parent` and save those in
@@ -1510,6 +1559,7 @@ static struct tag *die__create_new_unspecified_type(Dwarf_Die *die, struct cu *c
15101559 INIT_LIST_HEAD (& tag -> node );
15111560
15121561 tag -> name = attr_string (die , DW_AT_name , conf );
1562+ add_child_btf_type_tags (die , cu , & tag -> tag , conf );
15131563
15141564 list_add (& tag -> node , & cu -> unspecified_types );
15151565
@@ -1611,9 +1661,7 @@ static struct tag *die__create_new_base_type(Dwarf_Die *die, struct cu *cu, stru
16111661 if (base == NULL )
16121662 return NULL ;
16131663
1614- if (dwarf_haschildren (die ))
1615- fprintf (stderr , "%s: DW_TAG_base_type WITH children!\n" ,
1616- __func__ );
1664+ add_child_btf_type_tags (die , cu , & base -> tag , conf );
16171665
16181666 return & base -> tag ;
16191667}
@@ -1628,11 +1676,15 @@ static struct tag *die__create_new_typedef(Dwarf_Die *die, struct cu *cu, struct
16281676 if (add_child_llvm_annotations (die , -1 , conf , & tdef -> namespace .annots ))
16291677 return NULL ;
16301678
1679+ if (add_child_btf_type_tags (die , cu , & tdef -> namespace .tag , conf ))
1680+ return NULL ;
1681+
16311682 return & tdef -> namespace .tag ;
16321683}
16331684
1634- static struct tag * die__create_new_array (Dwarf_Die * die , struct cu * cu )
1685+ static struct tag * die__create_new_array (Dwarf_Die * die , struct cu * cu , struct conf_load * conf )
16351686{
1687+ struct type_tags_writer ttw ;
16361688 Dwarf_Die child ;
16371689 /* "64 dimensions will be enough for everybody." acme, 2006 */
16381690 const uint8_t max_dimensions = 64 ;
@@ -1645,19 +1697,29 @@ static struct tag *die__create_new_array(Dwarf_Die *die, struct cu *cu)
16451697 if (!dwarf_haschildren (die ) || dwarf_child (die , & child ) != 0 )
16461698 return & array -> tag ;
16471699
1700+ type_tags_writer__init (& ttw , cu -> priv , & array -> tag );
16481701 die = & child ;
16491702 do {
1650- if (dwarf_tag (die ) == DW_TAG_subrange_type ) {
1703+ switch (dwarf_tag (die )) {
1704+ case DW_TAG_subrange_type :
16511705 nr_entries [array -> dimensions ++ ] = attr_upper_bound (die );
16521706 if (array -> dimensions == max_dimensions ) {
16531707 fprintf (stderr , "%s: only %u dimensions are "
16541708 "supported!\n" ,
16551709 __FUNCTION__ , max_dimensions );
1656- break ;
1710+ goto _break_loop ;
16571711 }
1658- } else
1712+ break ;
1713+ case DW_TAG_LLVM_annotation :
1714+ if (add_btf_type_tag (& ttw , die , conf ))
1715+ goto out_free ;
1716+ break ;
1717+ default :
16591718 cu__tag_not_handled (die );
1719+ break ;
1720+ }
16601721 } while (dwarf_siblingof (die , die ) == 0 );
1722+ _break_loop :
16611723
16621724 array -> nr_entries = memdup (nr_entries ,
16631725 array -> dimensions * sizeof (uint32_t ), cu );
@@ -1754,6 +1816,7 @@ static struct tag *die__create_new_constant(Dwarf_Die *die, struct cu *cu, struc
17541816static struct tag * die__create_new_subroutine_type (Dwarf_Die * die ,
17551817 struct cu * cu , struct conf_load * conf )
17561818{
1819+ struct type_tags_writer ttw ;
17571820 Dwarf_Die child ;
17581821 struct ftype * ftype = ftype__new (die , cu );
17591822 struct tag * tag ;
@@ -1764,6 +1827,7 @@ static struct tag *die__create_new_subroutine_type(Dwarf_Die *die,
17641827 if (!dwarf_haschildren (die ) || dwarf_child (die , & child ) != 0 )
17651828 goto out ;
17661829
1830+ type_tags_writer__init (& ttw , cu -> priv , & ftype -> tag );
17671831 die = & child ;
17681832 do {
17691833 uint32_t id ;
@@ -1778,6 +1842,10 @@ static struct tag *die__create_new_subroutine_type(Dwarf_Die *die,
17781842 case DW_TAG_unspecified_parameters :
17791843 ftype -> unspec_parms = 1 ;
17801844 continue ;
1845+ case DW_TAG_LLVM_annotation :
1846+ if (add_btf_type_tag (& ttw , die , conf ))
1847+ goto out_delete ;
1848+ continue ;
17811849 default :
17821850 tag = die__process_tag (die , cu , 0 , conf );
17831851 if (tag == NULL )
@@ -1817,6 +1885,7 @@ static struct tag *die__create_new_enumeration(Dwarf_Die *die, struct cu *cu, st
18171885{
18181886 Dwarf_Die child ;
18191887 struct type * enumeration = type__new (die , cu , conf );
1888+ struct type_tags_writer ttw ;
18201889
18211890 if (enumeration == NULL )
18221891 return NULL ;
@@ -1832,19 +1901,27 @@ static struct tag *die__create_new_enumeration(Dwarf_Die *die, struct cu *cu, st
18321901 goto out ;
18331902 }
18341903
1904+ type_tags_writer__init (& ttw , cu -> priv , & enumeration -> namespace .tag );
18351905 die = & child ;
18361906 do {
18371907 struct enumerator * enumerator ;
18381908
1839- if (dwarf_tag (die ) != DW_TAG_enumerator ) {
1909+ switch (dwarf_tag (die )) {
1910+ case DW_TAG_enumerator :
1911+ enumerator = enumerator__new (die , cu , conf );
1912+ if (enumerator == NULL )
1913+ goto out_delete ;
1914+
1915+ enumeration__add (enumeration , enumerator );
1916+ break ;
1917+ case DW_TAG_LLVM_annotation :
1918+ if (add_btf_type_tag (& ttw , die , conf ))
1919+ goto out_delete ;
1920+ break ;
1921+ default :
18401922 cu__tag_not_handled (die );
1841- continue ;
1923+ break ;
18421924 }
1843- enumerator = enumerator__new (die , cu , conf );
1844- if (enumerator == NULL )
1845- goto out_delete ;
1846-
1847- enumeration__add (enumeration , enumerator );
18481925 } while (dwarf_siblingof (die , die ) == 0 );
18491926out :
18501927 return & enumeration -> namespace .tag ;
@@ -1857,8 +1934,10 @@ static int die__process_class(Dwarf_Die *die, struct type *class,
18571934 struct cu * cu , struct conf_load * conf )
18581935{
18591936 const bool is_union = tag__is_union (& class -> namespace .tag );
1937+ struct type_tags_writer ttw ;
18601938 int member_idx = 0 ;
18611939
1940+ type_tags_writer__init (& ttw , cu -> priv , & class -> namespace .tag );
18621941 do {
18631942 switch (dwarf_tag (die )) {
18641943 case DW_TAG_subrange_type : // XXX: ADA stuff, its a type tho, will have other entries referencing it...
@@ -1906,6 +1985,8 @@ static int die__process_class(Dwarf_Die *die, struct type *class,
19061985 }
19071986 continue ;
19081987 case DW_TAG_LLVM_annotation :
1988+ if (add_btf_type_tag (& ttw , die , conf ))
1989+ return - ENOMEM ;
19091990 if (add_llvm_annotation (die , -1 , conf , & class -> namespace .annots ))
19101991 return - ENOMEM ;
19111992 continue ;
@@ -2243,7 +2324,7 @@ static struct tag *__die__process_tag(Dwarf_Die *die, struct cu *cu,
22432324 case DW_TAG_imported_unit :
22442325 return NULL ; // We don't support imported units yet, so to avoid segfaults
22452326 case DW_TAG_array_type :
2246- tag = die__create_new_array (die , cu ); break ;
2327+ tag = die__create_new_array (die , cu , conf ); break ;
22472328 case DW_TAG_string_type : // FORTRAN stuff, looks like an array
22482329 tag = die__create_new_string_type (die , cu ); break ;
22492330 case DW_TAG_base_type :
@@ -2866,11 +2947,20 @@ static struct btf_type_tag_type *new_btf_type_tag_type(struct cu *cu,
28662947 *
28672948 * tag3 -> tag2 -> tag1
28682949 *
2869- * And complete the chain as follows for each type tag group:
2950+ * And for kind == TYPE_TAG_POINTEE complete the chain as follows for
2951+ * each type tag group:
28702952 *
28712953 * '*' -> tag3 -> tag2 -> tag1 -> int
2954+ *
2955+ * For kind == TYPE_TAG_SELF the tag1..3 would be applied to `int`
2956+ * entry itself, thus complete the chain as below:
2957+ *
2958+ * tag3 -> tag2 -> tag1 -> int
2959+ *
2960+ * And do cu__hash_impersonate(cu, int, tag3), so that each lookup of
2961+ * `int` by Dwarf_Off would return `tag3`.
28722962 */
2873- static int dwarf_cu__recode_type_tags (struct cu * cu )
2963+ static int dwarf_cu__recode_type_tags (struct cu * cu , enum type_tag_kind target_kind )
28742964{
28752965 struct dwarf_cu * dcu = cu -> priv ;
28762966 void * * entries = dcu -> type_tags .entries ;
@@ -2885,12 +2975,18 @@ static int dwarf_cu__recode_type_tags(struct cu *cu)
28852975 struct btf_type_tag_type * prev = NULL ;
28862976
28872977 while (i < N ) {
2888- const char * value = entries [i ++ ];
2978+ const char * value ;
2979+ uintptr_t kind ;
28892980 uint32_t id ;
28902981
2891- if (value == NULL )
2982+ value = entries [i ++ ];
2983+ if (value == NULL || i >= N )
28922984 break ;
28932985
2986+ kind = (uintptr_t )entries [i ++ ];
2987+ if (kind != target_kind )
2988+ continue ;
2989+
28942990 last = new_btf_type_tag_type (cu , value );
28952991 if (last == NULL )
28962992 return - ENOMEM ;
@@ -2912,27 +3008,56 @@ static int dwarf_cu__recode_type_tags(struct cu *cu)
29123008 if (first == NULL )
29133009 continue ;
29143010
2915- /* Type tags are recoded *after* main recode phase,
2916- * so parent->type is valid.
2917- *
2918- * parent last first parent->type
2919- * | | | |
2920- * '*' -> tag3 -> tag2 -> tag1 -> int
2921- */
2922- first -> tag .type = parent -> type ;
2923- parent -> type = tag__small_id (& last -> tag );
3011+ switch (target_kind ) {
3012+ case TYPE_TAG_POINTEE :
3013+ /* For POINTEE type tags are recoded *after*
3014+ * main recode phase, so parent->type is valid.
3015+ *
3016+ * parent last first parent->type
3017+ * | | | |
3018+ * '*' -> tag3 -> tag2 -> tag1 -> int
3019+ */
3020+ first -> tag .type = parent -> type ;
3021+ parent -> type = tag__small_id (& last -> tag );
3022+ break ;
3023+ case TYPE_TAG_SELF :
3024+ /* For SELF type tags are recoded *before*
3025+ * main recode phase, so dcu->hash_types
3026+ * changes would be visible during that phase.
3027+ *
3028+ * last first parent
3029+ * | | |
3030+ * tag3 -> tag2 -> tag1 -> int
3031+ * ^ |
3032+ * '-----------------------'
3033+ * copy parent->tag.priv->id
3034+ */
3035+ first -> tag .type = tag__small_id (parent );
3036+ cu__hash_impersonate (cu , parent , & last -> tag );
3037+ break ;
3038+ }
29243039 }
29253040
29263041 return 0 ;
29273042}
29283043
29293044static int cu__recode_dwarf_types (struct cu * cu )
29303045{
3046+ struct dwarf_cu * dcu = cu -> priv ;
3047+
3048+ if (dcu -> effective_type_tag_kind == TYPE_TAG_SELF &&
3049+ dwarf_cu__recode_type_tags (cu , TYPE_TAG_SELF ) != 0 )
3050+ return -1 ;
3051+
29313052 if (cu__recode_dwarf_types_table (cu , & cu -> types_table , 1 ) ||
29323053 cu__recode_dwarf_types_table (cu , & cu -> tags_table , 0 ) ||
29333054 cu__recode_dwarf_types_table (cu , & cu -> functions_table , 0 ))
29343055 return -1 ;
2935- dwarf_cu__recode_type_tags (cu );
3056+
3057+ if (dcu -> effective_type_tag_kind == TYPE_TAG_POINTEE &&
3058+ dwarf_cu__recode_type_tags (cu , TYPE_TAG_POINTEE ) != 0 )
3059+ return -1 ;
3060+
29363061 return 0 ;
29373062}
29383063
0 commit comments