btf: emit non-representable bitfield as void
This patch fixes an issue with mangled BTF that could occur when
a struct type contains a bitfield member which cannot be represented
in BTF. It is undefined what should happen in such cases, but we can
at least do something reasonable.
Commit
936dd627cd
"btf: do not skip members of data type with type id
BTF_VOID_TYPEID"
made a similar change for un-representable non-bitfield members, but
had an unintended side-effect of mangling BTF for un-representable
bitfields: the struct (or union) would account for the offending
bitfield in its member count but the bitfield member itself was
not emitted, making the member count incorrect.
This change ensures that non-representable bitfield members of struct
and union types are always emitted with BTF_VOID_TYPEID. This avoids
corrupting the BTF information for the entire struct or union type.
gcc/
* btfout.cc (btf_asm_sou_member): Always emit non-representable
bitfield members as having 'void' type. Refactor slightly.
gcc/testsuite/
* gcc.dg/debug/btf/btf-bitfields-4.c: Add two new checks.
This commit is contained in:
parent
33f83d3cd8
commit
f079d69d7b
2 changed files with 28 additions and 28 deletions
|
@ -922,43 +922,41 @@ 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);
|
||||
uint64_t sou_offset = dmd->dmd_offset;
|
||||
|
||||
dw2_asm_output_data (4, dmd->dmd_name_offset,
|
||||
"MEMBER '%s' idx=%u",
|
||||
dmd->dmd_name, idx);
|
||||
|
||||
/* Re-encode bitfields to BTF representation. */
|
||||
if (CTF_V2_INFO_KIND (ref_type->dtd_data.ctti_info) == CTF_K_SLICE)
|
||||
{
|
||||
ctf_id_t base_type = ref_type->dtd_u.dtu_slice.cts_type;
|
||||
if (btf_dmd_representable_bitfield_p (ctfc, dmd))
|
||||
{
|
||||
unsigned short word_offset = ref_type->dtd_u.dtu_slice.cts_offset;
|
||||
unsigned short bits = ref_type->dtd_u.dtu_slice.cts_bits;
|
||||
uint64_t sou_offset = dmd->dmd_offset;
|
||||
|
||||
/* Pack the bit offset and bitfield size together. */
|
||||
sou_offset += word_offset;
|
||||
|
||||
/* If this bitfield cannot be represented, do not output anything.
|
||||
The parent struct/union 'vlen' field has already been updated. */
|
||||
if ((bits > 0xff) || (sou_offset > 0xffffff))
|
||||
return;
|
||||
|
||||
sou_offset &= 0x00ffffff;
|
||||
sou_offset |= ((bits & 0xff) << 24);
|
||||
|
||||
dw2_asm_output_data (4, dmd->dmd_name_offset,
|
||||
"MEMBER '%s' idx=%u",
|
||||
dmd->dmd_name, idx);
|
||||
/* Refer to the base type of the slice. */
|
||||
btf_asm_type_ref ("btm_type", ctfc, get_btf_id (base_type));
|
||||
dw2_asm_output_data (4, sou_offset, "btm_offset");
|
||||
base_type = get_btf_id (ref_type->dtd_u.dtu_slice.cts_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
dw2_asm_output_data (4, dmd->dmd_name_offset,
|
||||
"MEMBER '%s' idx=%u",
|
||||
dmd->dmd_name, idx);
|
||||
btf_asm_type_ref ("btm_type", ctfc, get_btf_id (dmd->dmd_type));
|
||||
dw2_asm_output_data (4, dmd->dmd_offset, "btm_offset");
|
||||
/* Bitfield cannot be represented in BTF. Emit the member as having
|
||||
'void' type. */
|
||||
base_type = BTF_VOID_TYPEID;
|
||||
}
|
||||
}
|
||||
|
||||
btf_asm_type_ref ("btm_type", ctfc, base_type);
|
||||
dw2_asm_output_data (4, sou_offset, "btm_offset");
|
||||
}
|
||||
|
||||
/* Asm'out an enum constant following a BTF_KIND_ENUM{,64}. */
|
||||
|
||||
static void
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
/* Struct with 4 members and no bitfield (kind_flag not set). */
|
||||
/* { dg-final { scan-assembler-times "\[\t \]0x4000004\[\t \]+\[^\n\]*btt_info" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " MEMBER" 4 } } */
|
||||
/* { dg-final { scan-assembler-times " MEMBER 'unsup' idx=2\[\\r\\n\]+\[^\\r\\n\]*0\[\t \]+\[^\n\]*btm_type: void" 1 } } */
|
||||
|
||||
struct bigly
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue