Message ID | 20240411210250.17026-1-david.faust@oracle.com |
---|---|
State | New |
Headers | show |
Series | btf: fix a possibly misleading asm debug comment | expand |
On 4/11/24 14:02, David Faust wrote: > This patch fixes a small error that could occur in the debug comment > when emitting a type reference with btf_asm_type_ref. > > While working on a previous patch, I noticed the following in the asm > output for the test btf-bitfields-4.c: > > ... > .long 0x39 # MEMBER 'c' idx=3 > .long 0x6 # btm_type: (BTF_KIND_UNKN '') > ... > .long 0x34 # TYPE 6 BTF_KIND_INT 'char' > > The type for member 'c' is correct, but the comment for the member > incorrectly reads "BTF_KIND_UNKN ''". This was caused by an > incorrect type lookup in btf_asm_type_ref that could happen if the > source file has types which can be represented in CTF but not in BTF. > > This patch fixes the issue by changing btf_asm_type_ref to work fully > in the CTF ID space until writing out the final BTF ID. That ensures > types are correctly identified when writing the asm debug comments, > like the following fixed comment for the above case. > > ... > .long 0x39 # MEMBER 'c' idx=3 > .long 0x6 # btm_type: (BTF_KIND_INT 'char') > ... > > Note that there was no problem with the actual BTF information, the > only error was in the comment. This patch does not change the output > BTF information, and no tests were affected. > > Tested on x86_64-linux-gnu and x86_64-linux-gnu host for > bpf-unknown-none target. Sanity checked by compiling kernel BPF > selftests. > Thanks. The code is easier to follow now too. LGTM. > gcc/ > * btfout.cc (btf_asm_type_ref): Convert IDs to BTF internally and > fix potentially looking up wrong type for asm debug comment info. > Split into... > (btf_asm_datasec_type_ref): ... This. New. > (btf_asm_datasec_entry): Call it here, instead of btf_asm_type_ref. > (btf_asm_type, btf_asm_array, btf_asm_varent, btf_asm_sou_member) > (btf_asm_func_arg, btf_asm_func_type): Adapt btf_asm_type_ref call. > --- > gcc/btfout.cc | 84 ++++++++++++++++++++++++++++++--------------------- > 1 file changed, 50 insertions(+), 34 deletions(-) > > diff --git a/gcc/btfout.cc b/gcc/btfout.cc > index e1ada41b1f4..24bef3acfd1 100644 > --- a/gcc/btfout.cc > +++ b/gcc/btfout.cc > @@ -738,36 +738,22 @@ btf_dmd_representable_bitfield_p (ctf_container_ref ctfc, ctf_dmdef_t *dmd) > /* Asm'out a reference to another BTF type. */ > > static void > -btf_asm_type_ref (const char *prefix, ctf_container_ref ctfc, ctf_id_t ref_id) > +btf_asm_type_ref (const char *prefix, ctf_container_ref ctfc, ctf_id_t ctf_id) > { > - if (ref_id == BTF_VOID_TYPEID || ref_id == BTF_INVALID_TYPEID) > + ctf_id_t btf_id = get_btf_id (ctf_id); > + if (btf_id == BTF_VOID_TYPEID || btf_id == BTF_INVALID_TYPEID) > { > /* There is no explicit void type. > Also handle any invalid refs that made it this far, just in case. */ > - dw2_asm_output_data (4, ref_id, "%s: void", prefix); > - } > - else if (ref_id >= num_types_added + 1 > - && ref_id < num_types_added + num_vars_added + 1) > - { > - /* Ref to a variable. Should only appear in DATASEC entries. */ > - ctf_id_t var_id = btf_relative_var_id (ref_id); > - ctf_dvdef_ref dvd = ctfc->ctfc_vars_list[var_id]; > - dw2_asm_output_data (4, ref_id, "%s: (BTF_KIND_VAR '%s')", > - prefix, dvd->dvd_name); > - > - } > - else if (ref_id >= num_types_added + num_vars_added + 1) > - { > - /* Ref to a FUNC record. */ > - size_t func_id = btf_relative_func_id (ref_id); > - ctf_dtdef_ref ref_type = (*funcs)[func_id]; > - dw2_asm_output_data (4, ref_id, "%s: (BTF_KIND_FUNC '%s')", > - prefix, get_btf_type_name (ref_type)); > + dw2_asm_output_data (4, btf_id, "%s: void", prefix); > } > else > { > - /* Ref to a standard type in the types list. */ > - ctf_dtdef_ref ref_type = ctfc->ctfc_types_list[ref_id]; > + gcc_assert (btf_id <= num_types_added); > + > + /* Ref to a standard type in the types list. Note: take care that we > + must index the type list by the original CTF id, not the BTF id. */ > + ctf_dtdef_ref ref_type = ctfc->ctfc_types_list[ctf_id]; > uint32_t ref_kind > = get_btf_kind (CTF_V2_INFO_KIND (ref_type->dtd_data.ctti_info)); > > @@ -775,12 +761,43 @@ btf_asm_type_ref (const char *prefix, ctf_container_ref ctfc, ctf_id_t ref_id) > ? btf_kind_name (BTF_KIND_ENUM) > : btf_kind_name (ref_kind); > > - dw2_asm_output_data (4, ref_id, "%s: (BTF_KIND_%s '%s')", > + dw2_asm_output_data (4, btf_id, "%s: (BTF_KIND_%s '%s')", > prefix, kind_name, > get_btf_type_name (ref_type)); > } > } > > +/* Asm'out a reference to a BTF_KIND_VAR or BTF_KIND_FUNC type. These type > + kinds are BTF-specific, and should only be referred to by entries in > + BTF_KIND_DATASEC records. */ > + > +static void > +btf_asm_datasec_type_ref (const char *prefix, ctf_container_ref ctfc, > + ctf_id_t btf_id) > +{ > + if (btf_id >= num_types_added + 1 > + && btf_id < num_types_added + num_vars_added + 1) > + { > + /* Ref to a variable. Should only appear in DATASEC entries. */ > + ctf_id_t var_id = btf_relative_var_id (btf_id); > + ctf_dvdef_ref dvd = ctfc->ctfc_vars_list[var_id]; > + dw2_asm_output_data (4, btf_id, "%s: (BTF_KIND_VAR '%s')", > + prefix, dvd->dvd_name); > + > + } > + else if (btf_id >= num_types_added + num_vars_added + 1) > + { > + /* Ref to a FUNC record. */ > + size_t func_id = btf_relative_func_id (btf_id); > + ctf_dtdef_ref ref_type = (*funcs)[func_id]; > + dw2_asm_output_data (4, btf_id, "%s: (BTF_KIND_FUNC '%s')", > + prefix, get_btf_type_name (ref_type)); > + } > + else > + /* The caller should not be calling this. */ > + gcc_unreachable (); > +} > + > /* Asm'out a BTF type. This routine is responsible for the bulk of the task > of converting CTF types to their BTF representation. */ > > @@ -887,7 +904,7 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) > break; > } > > - ctf_id_t ref_id = get_btf_id (dtd->dtd_data.ctti_type); > + ctf_id_t ref_id = dtd->dtd_data.ctti_type; > btf_asm_type_ref ("btt_type", ctfc, ref_id); > } > > @@ -896,8 +913,8 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) > static void > btf_asm_array (ctf_container_ref ctfc, ctf_arinfo_t arr) > { > - btf_asm_type_ref ("bta_elem_type", ctfc, get_btf_id (arr.ctr_contents)); > - btf_asm_type_ref ("bta_index_type", ctfc, get_btf_id (arr.ctr_index)); > + btf_asm_type_ref ("bta_elem_type", ctfc, arr.ctr_contents); > + btf_asm_type_ref ("bta_index_type", ctfc, arr.ctr_index); > dw2_asm_output_data (4, arr.ctr_nelems, "bta_nelems"); > } > > @@ -906,12 +923,11 @@ btf_asm_array (ctf_container_ref ctfc, ctf_arinfo_t arr) > static void > btf_asm_varent (ctf_container_ref ctfc, ctf_dvdef_ref var) > { > - ctf_id_t ref_id = get_btf_id (var->dvd_type); > dw2_asm_output_data (4, var->dvd_name_offset, "TYPE %u BTF_KIND_VAR '%s'", > (*(btf_var_ids->get (var)) + num_types_added + 1), > var->dvd_name); > dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_VAR, 0, 0), "btv_info"); > - btf_asm_type_ref ("btv_type", ctfc, ref_id); > + btf_asm_type_ref ("btv_type", ctfc, var->dvd_type); > dw2_asm_output_data (4, var->dvd_visibility, "btv_linkage"); > } > > @@ -922,7 +938,7 @@ static void > btf_asm_sou_member (ctf_container_ref ctfc, ctf_dmdef_t * dmd, unsigned int idx) > { > ctf_dtdef_ref ref_type = ctfc->ctfc_types_list[dmd->dmd_type]; > - ctf_id_t base_type = get_btf_id (dmd->dmd_type); > + ctf_id_t base_type = dmd->dmd_type; > uint64_t sou_offset = dmd->dmd_offset; > > dw2_asm_output_data (4, dmd->dmd_name_offset, > @@ -949,7 +965,7 @@ btf_asm_sou_member (ctf_container_ref ctfc, ctf_dmdef_t * dmd, unsigned int idx) > sou_offset |= ((bits & 0xff) << 24); > > /* Refer to the base type of the slice. */ > - base_type = get_btf_id (ref_type->dtd_u.dtu_slice.cts_type); > + base_type = ref_type->dtd_u.dtu_slice.cts_type; > } > } > > @@ -989,7 +1005,7 @@ btf_asm_func_arg (ctf_container_ref ctfc, ctf_func_arg_t * farg, > > btf_asm_type_ref ("farg_type", ctfc, (btf_removed_type_p (farg->farg_type) > ? BTF_VOID_TYPEID > - : get_btf_id (farg->farg_type))); > + : farg->farg_type)); > } > > /* Asm'out a BTF_KIND_FUNC type. */ > @@ -1004,7 +1020,7 @@ btf_asm_func_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd, ctf_id_t id) > dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_FUNC, 0, dtd->linkage), > "btt_info: kind=%u, kflag=%u, linkage=%u", > BTF_KIND_FUNC, 0, dtd->linkage); > - btf_asm_type_ref ("btt_type", ctfc, get_btf_id (ref_id)); > + btf_asm_type_ref ("btt_type", ctfc, ref_id); > } > > /* Collect the name for the DATASEC reference required to be output as a > @@ -1037,7 +1053,7 @@ static void > btf_asm_datasec_entry (ctf_container_ref ctfc, struct btf_var_secinfo info) > { > const char *symbol_name = get_name_for_datasec_entry (ctfc, info.type); > - btf_asm_type_ref ("bts_type", ctfc, info.type); > + btf_asm_datasec_type_ref ("bts_type", ctfc, info.type); > if (!btf_with_core_debuginfo_p () || symbol_name == NULL) > dw2_asm_output_data (4, info.offset, "bts_offset"); > else
diff --git a/gcc/btfout.cc b/gcc/btfout.cc index e1ada41b1f4..24bef3acfd1 100644 --- a/gcc/btfout.cc +++ b/gcc/btfout.cc @@ -738,36 +738,22 @@ btf_dmd_representable_bitfield_p (ctf_container_ref ctfc, ctf_dmdef_t *dmd) /* Asm'out a reference to another BTF type. */ static void -btf_asm_type_ref (const char *prefix, ctf_container_ref ctfc, ctf_id_t ref_id) +btf_asm_type_ref (const char *prefix, ctf_container_ref ctfc, ctf_id_t ctf_id) { - if (ref_id == BTF_VOID_TYPEID || ref_id == BTF_INVALID_TYPEID) + ctf_id_t btf_id = get_btf_id (ctf_id); + if (btf_id == BTF_VOID_TYPEID || btf_id == BTF_INVALID_TYPEID) { /* There is no explicit void type. Also handle any invalid refs that made it this far, just in case. */ - dw2_asm_output_data (4, ref_id, "%s: void", prefix); - } - else if (ref_id >= num_types_added + 1 - && ref_id < num_types_added + num_vars_added + 1) - { - /* Ref to a variable. Should only appear in DATASEC entries. */ - ctf_id_t var_id = btf_relative_var_id (ref_id); - ctf_dvdef_ref dvd = ctfc->ctfc_vars_list[var_id]; - dw2_asm_output_data (4, ref_id, "%s: (BTF_KIND_VAR '%s')", - prefix, dvd->dvd_name); - - } - else if (ref_id >= num_types_added + num_vars_added + 1) - { - /* Ref to a FUNC record. */ - size_t func_id = btf_relative_func_id (ref_id); - ctf_dtdef_ref ref_type = (*funcs)[func_id]; - dw2_asm_output_data (4, ref_id, "%s: (BTF_KIND_FUNC '%s')", - prefix, get_btf_type_name (ref_type)); + dw2_asm_output_data (4, btf_id, "%s: void", prefix); } else { - /* Ref to a standard type in the types list. */ - ctf_dtdef_ref ref_type = ctfc->ctfc_types_list[ref_id]; + gcc_assert (btf_id <= num_types_added); + + /* Ref to a standard type in the types list. Note: take care that we + must index the type list by the original CTF id, not the BTF id. */ + ctf_dtdef_ref ref_type = ctfc->ctfc_types_list[ctf_id]; uint32_t ref_kind = get_btf_kind (CTF_V2_INFO_KIND (ref_type->dtd_data.ctti_info)); @@ -775,12 +761,43 @@ btf_asm_type_ref (const char *prefix, ctf_container_ref ctfc, ctf_id_t ref_id) ? btf_kind_name (BTF_KIND_ENUM) : btf_kind_name (ref_kind); - dw2_asm_output_data (4, ref_id, "%s: (BTF_KIND_%s '%s')", + dw2_asm_output_data (4, btf_id, "%s: (BTF_KIND_%s '%s')", prefix, kind_name, get_btf_type_name (ref_type)); } } +/* Asm'out a reference to a BTF_KIND_VAR or BTF_KIND_FUNC type. These type + kinds are BTF-specific, and should only be referred to by entries in + BTF_KIND_DATASEC records. */ + +static void +btf_asm_datasec_type_ref (const char *prefix, ctf_container_ref ctfc, + ctf_id_t btf_id) +{ + if (btf_id >= num_types_added + 1 + && btf_id < num_types_added + num_vars_added + 1) + { + /* Ref to a variable. Should only appear in DATASEC entries. */ + ctf_id_t var_id = btf_relative_var_id (btf_id); + ctf_dvdef_ref dvd = ctfc->ctfc_vars_list[var_id]; + dw2_asm_output_data (4, btf_id, "%s: (BTF_KIND_VAR '%s')", + prefix, dvd->dvd_name); + + } + else if (btf_id >= num_types_added + num_vars_added + 1) + { + /* Ref to a FUNC record. */ + size_t func_id = btf_relative_func_id (btf_id); + ctf_dtdef_ref ref_type = (*funcs)[func_id]; + dw2_asm_output_data (4, btf_id, "%s: (BTF_KIND_FUNC '%s')", + prefix, get_btf_type_name (ref_type)); + } + else + /* The caller should not be calling this. */ + gcc_unreachable (); +} + /* Asm'out a BTF type. This routine is responsible for the bulk of the task of converting CTF types to their BTF representation. */ @@ -887,7 +904,7 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) break; } - ctf_id_t ref_id = get_btf_id (dtd->dtd_data.ctti_type); + ctf_id_t ref_id = dtd->dtd_data.ctti_type; btf_asm_type_ref ("btt_type", ctfc, ref_id); } @@ -896,8 +913,8 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) static void btf_asm_array (ctf_container_ref ctfc, ctf_arinfo_t arr) { - btf_asm_type_ref ("bta_elem_type", ctfc, get_btf_id (arr.ctr_contents)); - btf_asm_type_ref ("bta_index_type", ctfc, get_btf_id (arr.ctr_index)); + btf_asm_type_ref ("bta_elem_type", ctfc, arr.ctr_contents); + btf_asm_type_ref ("bta_index_type", ctfc, arr.ctr_index); dw2_asm_output_data (4, arr.ctr_nelems, "bta_nelems"); } @@ -906,12 +923,11 @@ btf_asm_array (ctf_container_ref ctfc, ctf_arinfo_t arr) static void btf_asm_varent (ctf_container_ref ctfc, ctf_dvdef_ref var) { - ctf_id_t ref_id = get_btf_id (var->dvd_type); dw2_asm_output_data (4, var->dvd_name_offset, "TYPE %u BTF_KIND_VAR '%s'", (*(btf_var_ids->get (var)) + num_types_added + 1), var->dvd_name); dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_VAR, 0, 0), "btv_info"); - btf_asm_type_ref ("btv_type", ctfc, ref_id); + btf_asm_type_ref ("btv_type", ctfc, var->dvd_type); dw2_asm_output_data (4, var->dvd_visibility, "btv_linkage"); } @@ -922,7 +938,7 @@ static void btf_asm_sou_member (ctf_container_ref ctfc, ctf_dmdef_t * dmd, unsigned int idx) { ctf_dtdef_ref ref_type = ctfc->ctfc_types_list[dmd->dmd_type]; - ctf_id_t base_type = get_btf_id (dmd->dmd_type); + ctf_id_t base_type = dmd->dmd_type; uint64_t sou_offset = dmd->dmd_offset; dw2_asm_output_data (4, dmd->dmd_name_offset, @@ -949,7 +965,7 @@ btf_asm_sou_member (ctf_container_ref ctfc, ctf_dmdef_t * dmd, unsigned int idx) sou_offset |= ((bits & 0xff) << 24); /* Refer to the base type of the slice. */ - base_type = get_btf_id (ref_type->dtd_u.dtu_slice.cts_type); + base_type = ref_type->dtd_u.dtu_slice.cts_type; } } @@ -989,7 +1005,7 @@ btf_asm_func_arg (ctf_container_ref ctfc, ctf_func_arg_t * farg, btf_asm_type_ref ("farg_type", ctfc, (btf_removed_type_p (farg->farg_type) ? BTF_VOID_TYPEID - : get_btf_id (farg->farg_type))); + : farg->farg_type)); } /* Asm'out a BTF_KIND_FUNC type. */ @@ -1004,7 +1020,7 @@ btf_asm_func_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd, ctf_id_t id) dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_FUNC, 0, dtd->linkage), "btt_info: kind=%u, kflag=%u, linkage=%u", BTF_KIND_FUNC, 0, dtd->linkage); - btf_asm_type_ref ("btt_type", ctfc, get_btf_id (ref_id)); + btf_asm_type_ref ("btt_type", ctfc, ref_id); } /* Collect the name for the DATASEC reference required to be output as a @@ -1037,7 +1053,7 @@ static void btf_asm_datasec_entry (ctf_container_ref ctfc, struct btf_var_secinfo info) { const char *symbol_name = get_name_for_datasec_entry (ctfc, info.type); - btf_asm_type_ref ("bts_type", ctfc, info.type); + btf_asm_datasec_type_ref ("bts_type", ctfc, info.type); if (!btf_with_core_debuginfo_p () || symbol_name == NULL) dw2_asm_output_data (4, info.offset, "bts_offset"); else