[gcc r14-9325] ctf: fix incorrect CTF for multi-dimensional array types
https://gcc.gnu.org/g:5d24bf3afd1bea3e51b87fb7ff24c21e29913999 commit r14-9325-g5d24bf3afd1bea3e51b87fb7ff24c21e29913999 Author: Cupertino Miranda Date: Thu Feb 29 10:56:13 2024 -0800 ctf: fix incorrect CTF for multi-dimensional array types PR debug/114186 DWARF DIEs of type DW_TAG_subrange_type are linked together to represent the information about the subsequent dimensions. The CTF processing was so far working through them in the opposite (incorrect) order. While fixing the issue, refactor the code a bit for readability. co-authored-By: Indu Bhagat gcc/ PR debug/114186 * dwarf2ctf.cc (gen_ctf_array_type): Invoke the ctf_add_array () in the correct order of the dimensions. (gen_ctf_subrange_type): Refactor out handling of DW_TAG_subrange_type DIE to here. gcc/testsuite/ PR debug/114186 * gcc.dg/debug/ctf/ctf-array-6.c: Add test. Diff: --- gcc/dwarf2ctf.cc | 158 +-- gcc/testsuite/gcc.dg/debug/ctf/ctf-array-6.c | 14 +++ 2 files changed, 89 insertions(+), 83 deletions(-) diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc index dca86edfffa..77d6bf89689 100644 --- a/gcc/dwarf2ctf.cc +++ b/gcc/dwarf2ctf.cc @@ -349,105 +349,97 @@ gen_ctf_pointer_type (ctf_container_ref ctfc, dw_die_ref ptr_type) return ptr_type_id; } -/* Generate CTF for an array type. */ +/* Recursively generate CTF for array dimensions starting at DIE C (of type + DW_TAG_subrange_type) until DIE LAST (of type DW_TAG_subrange_type) is + reached. ARRAY_ELEMS_TYPE_ID is base type for the array. */ static ctf_id_t -gen_ctf_array_type (ctf_container_ref ctfc, dw_die_ref array_type) +gen_ctf_subrange_type (ctf_container_ref ctfc, ctf_id_t array_elems_type_id, + dw_die_ref c, dw_die_ref last) { - dw_die_ref c; - ctf_id_t array_elems_type_id = CTF_NULL_TYPEID; + ctf_arinfo_t arinfo; + ctf_id_t array_node_type_id = CTF_NULL_TYPEID; - int vector_type_p = get_AT_flag (array_type, DW_AT_GNU_vector); - if (vector_type_p) -return array_elems_type_id; + dw_attr_node *upper_bound_at; + dw_die_ref array_index_type; + uint32_t array_num_elements; - dw_die_ref array_elems_type = ctf_get_AT_type (array_type); + if (dw_get_die_tag (c) == DW_TAG_subrange_type) +{ + /* When DW_AT_upper_bound is used to specify the size of an +array in DWARF, it is usually an unsigned constant +specifying the upper bound index of the array. However, +for unsized arrays, such as foo[] or bar[0], +DW_AT_upper_bound is a signed integer constant +instead. */ + + upper_bound_at = get_AT (c, DW_AT_upper_bound); + if (upper_bound_at + && AT_class (upper_bound_at) == dw_val_class_unsigned_const) + /* This is the upper bound index. */ + array_num_elements = get_AT_unsigned (c, DW_AT_upper_bound) + 1; + else if (get_AT (c, DW_AT_count)) + array_num_elements = get_AT_unsigned (c, DW_AT_count); + else + { + /* This is a VLA of some kind. */ + array_num_elements = 0; + } +} + else +gcc_unreachable (); - /* First, register the type of the array elements if needed. */ - array_elems_type_id = gen_ctf_type (ctfc, array_elems_type); + /* Ok, mount and register the array type. Note how the array + type we register here is the type of the elements in + subsequent "dimensions", if there are any. */ + arinfo.ctr_nelems = array_num_elements; - /* DWARF array types pretend C supports multi-dimensional arrays. - So for the type int[N][M], the array type DIE contains two - subrange_type children, the first with upper bound N-1 and the - second with upper bound M-1. + array_index_type = ctf_get_AT_type (c); + arinfo.ctr_index = gen_ctf_type (ctfc, array_index_type); - CTF, on the other hand, just encodes each array type in its own - array type CTF struct. Therefore we have to iterate on the - children and create all the needed types. */ + if (c == last) +arinfo.ctr_contents = array_elems_type_id; + else +arinfo.ctr_contents = gen_ctf_subrange_type (ctfc, array_elems_type_id, +dw_get_die_sib (c), last); - c = dw_get_die_child (array_type); - gcc_assert (c); - do -{ - ctf_arinfo_t arinfo; - dw_die_ref array_index_type; - uint32_t array_num_elements; + if (!ctf_type_exists (ctfc, c, &array_node_type_id)) +array_node_type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, c); - c = dw_get_die_sib (c); + return array_node_type_id; +} - if (dw_get_die_tag (c) == DW_TAG_subrange_type) - { - dw_attr_node *upper_bound_at; - - array_index_type = ctf_get_AT_type (c); - - /* When DW_AT_upper_bound is used to specify the size of an -a
[gcc r14-9906] ctf: fix PR debug/112878
https://gcc.gnu.org/g:5c869aa8a4538b218d9e59de6c96133971e7b965 commit r14-9906-g5c869aa8a4538b218d9e59de6c96133971e7b965 Author: Indu Bhagat Date: Wed Apr 10 17:27:52 2024 -0700 ctf: fix PR debug/112878 PR debug/112878: ICE: in ctf_add_slice, at ctfc.cc:499 with _BitInt > 255 in a struct and -gctf1 The CTF generation in GCC does not have a mechanism to roll-back an already added type. In this testcase presented in the PR, we hit a representation limit in CTF slices (for a member of a struct) and ICE, after the type for struct (CTF_K_STRUCT) has already been added to the container. To exit gracefully instead, we now check for both the offset and size of the bitfield to be explicitly <= 255. If the check fails, we emit the member with type CTF_K_UNKNOWN. Note that, the value 255 stems from the existing binutils libctf checks which were motivated to guard against malformed inputs. Although it is not accurate to say that this is a CTF representation limit, mark the code with TBD_CTF_REPRESENTATION_LIMIT for now so that this can be taken care of with the next format version bump, when libctf's checks for the slice data can be lifted as well. gcc/ChangeLog: PR debug/112878 * dwarf2ctf.cc (gen_ctf_sou_type): Check for conditions before call to ctf_add_slice. Use CTF_K_UNKNOWN type if fail. gcc/testsuite/ChangeLog: PR debug/112878 * gcc.dg/debug/ctf/ctf-bitfields-5.c: New test. Diff: --- gcc/dwarf2ctf.cc | 15 ++- gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-5.c | 17 + 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc index 77d6bf89689..dc59569fe56 100644 --- a/gcc/dwarf2ctf.cc +++ b/gcc/dwarf2ctf.cc @@ -606,11 +606,16 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, uint32_t kind) if (attr) bitpos += AT_unsigned (attr); - field_type_id = ctf_add_slice (ctfc, CTF_ADD_NONROOT, -field_type_id, -bitpos - field_location, -bitsize, -c); + /* This is not precisely a TBD_CTF_REPRESENTATION_LIMIT, but +surely something to look at for the next format version bump +for CTF. */ + if (bitsize <= 255 && (bitpos - field_location) <= 255) + field_type_id = ctf_add_slice (ctfc, CTF_ADD_NONROOT, + field_type_id, + bitpos - field_location, + bitsize, c); + else + field_type_id = gen_ctf_unknown_type (ctfc); } /* Add the field type to the struct or union type. */ diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-5.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-5.c new file mode 100644 index 000..fee8228647c --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-5.c @@ -0,0 +1,17 @@ +/* Bitfield where the bit offset is > 255 is not allowed in CTF. + + PR debug/112878. + This testcase is to ensure graceful handling. No slices are expected. */ + +/* { dg-do compile { target bitint } } */ +/* { dg-options "-O0 -gctf -dA" } */ + +/* No slices are expected, but a struct with one member is expected. + CTF_K_UNKNOWN is also expected. */ +/* { dg-final { scan-assembler-times "cts_type" 0 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x1a01\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"unknown.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +struct { + _BitInt(282) a : 280; +} b;
[gcc r14-9907] btf: do not skip members of data type with type id BTF_VOID_TYPEID
https://gcc.gnu.org/g:936dd627cd90bdfa3f796712c043406958131d7c commit r14-9907-g936dd627cd90bdfa3f796712c043406958131d7c Author: Indu Bhagat Date: Mon Apr 8 11:01:45 2024 -0700 btf: do not skip members of data type with type id BTF_VOID_TYPEID The previous fix in gen_ctf_sou_type () exposes an issue in BTF generation, however: BTF emission was currently decrementing the vlen (indicating the number of members) to skip members of type CTF_K_UNKNOWN altogether, but still emitting the BTF for the corresponding member (in output_asm_btf_sou_fields ()). One can see malformed BTF by executing the newly added CTF testcase (gcc.dg/debug/ctf/ctf-bitfields-5.c) with -gbtf instead or even existing btf-struct-2.c without this patch. To fix the issue, it makes sense to rather _not_ skip members of data type of type id BTF_VOID_TYPEID. gcc/ChangeLog: * btfout.cc (btf_asm_type): Do not skip emitting members of unknown type. gcc/testsuite/ChangeLog: * gcc.dg/debug/btf/btf-bitfields-4.c: Update the vlen check. * gcc.dg/debug/btf/btf-struct-2.c: Check that member named 'f' with void data type is emitted. Diff: --- gcc/btfout.cc| 5 - gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-4.c | 6 +++--- gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c| 9 + 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/gcc/btfout.cc b/gcc/btfout.cc index 4a8ec4d1ff0..ab491f0297f 100644 --- a/gcc/btfout.cc +++ b/gcc/btfout.cc @@ -820,11 +820,6 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) /* Set kflag if this member is a representable bitfield. */ if (btf_dmd_representable_bitfield_p (ctfc, dmd)) btf_kflag = 1; - - /* Struct members that refer to unsupported types or bitfield formats -shall be skipped. These are marked during preprocessing. */ - else if (!btf_emit_id_p (dmd->dmd_type)) - btf_vlen -= 1; } } diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-4.c b/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-4.c index c00c8b3d87f..d4a6ef6a1eb 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-4.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-4.c @@ -6,14 +6,14 @@ In this test, we construct a structure such that the bitfield will have an offset so large as to be unrepresentable in BTF. We expect that the resulting BTF will describe the rest of the structure, ignoring the - non-representable bitfield. */ + non-representable bitfield by simply using void data type for the same. */ /* { dg-do compile } */ /* { dg-options "-O0 -gbtf -dA" } */ /* { dg-require-effective-target size32plus } */ -/* Struct with 3 members and no bitfield (kind_flag not set). */ -/* { dg-final { scan-assembler-times "\[\t \]0x403\[\t \]+\[^\n\]*btt_info" 1 } } */ +/* Struct with 4 members and no bitfield (kind_flag not set). */ +/* { dg-final { scan-assembler-times "\[\t \]0x404\[\t \]+\[^\n\]*btt_info" 1 } } */ struct bigly { diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c b/gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c index e9ff06883db..fa7231be75c 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c @@ -2,14 +2,15 @@ unsupported type. BTF does not support vector types (among other things). When - generating BTF for a struct (or union) type, members which refer to - unsupported types should be skipped. */ + generating BTF for a struct (or union) type. Members which refer to + unsupported types should not be skipped, however. */ /* { dg-do compile } */ /* { dg-options "-O0 -gbtf -dA" } */ -/* Expect a struct with only 2 members - 'f' should not be present. */ -/* { dg-final { scan-assembler-times "\[\t \]0x402\[\t \]+\[^\n\]*btt_info" 1 } } */ +/* Expect a struct with 3 members - 'f' is present but is of data type void. */ +/* { dg-final { scan-assembler-times "\[\t \]0x403\[\t \]+\[^\n\]*btt_info" 1 } } */ +/* { dg-final { scan-assembler-times " MEMBER 'f' idx=1\[\\r\\n\]+\[^\\r\\n\]*0\[\t \]+\[^\n\]*btm_type: void" 1 } } */ struct with_float {