Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DWARF information encodes discriminant values for tagged enums incorrectly #125147

Open
sdnr1 opened this issue May 15, 2024 · 0 comments
Open

DWARF information encodes discriminant values for tagged enums incorrectly #125147

sdnr1 opened this issue May 15, 2024 · 0 comments
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-debugging Working group: Bad Rust debugging experiences

Comments

@sdnr1
Copy link

sdnr1 commented May 15, 2024

The Rust compiler emits tagged enums and their members as DW_TAG_variant_part and DW_TAG_variant DIEs in DWARF correspondingly. According to the DWARF standard, the discriminant value for each of the variant members should be LEB128 encoded. In practice, the Rust compiler does not encode these values in LEB128 encoding, thereby it is not compliant with the DWARF standard.

Furthermore, there seems to be some undefined behavior with negative discriminant values. The following examples show 2 cases of tagged enums with negative discriminants.


Example 1

Discriminant type is 32 bit signed integer.

#[repr(i32)]
pub enum Foo {
    Unit = -2,
    TwoInts(u32, u32) = -1,
    ThreeShorts{x: u16, y: u16, z: u16} = 0,
}

DWARF:

0x00000078:     DW_TAG_structure_type
                  DW_AT_name [DW_FORM_strp]     ("Foo")
                  DW_AT_byte_size [DW_FORM_data1]       (0x0c)
                  DW_AT_alignment [DW_FORM_udata]       (4)

0x0000007f:       DW_TAG_variant_part
                    DW_AT_discr [DW_FORM_ref4]  (0x00000084)

0x00000084:         DW_TAG_member
                      DW_AT_type [DW_FORM_ref4] (0x00000114 "i32")
                      DW_AT_alignment [DW_FORM_udata]   (4)
                      DW_AT_data_member_location [DW_FORM_data1]        (0x00)
                      DW_AT_artificial [DW_FORM_flag_present]   (true)

0x0000008b:         DW_TAG_variant
                      DW_AT_discr_value [DW_FORM_data8] (0x00000000fffffffe)

0x00000094:           DW_TAG_member
                        DW_AT_name [DW_FORM_strp]       ("Unit")
                        DW_AT_type [DW_FORM_ref4]       (0x000000bd "t3::Foo::Unit")
                        DW_AT_alignment [DW_FORM_udata] (4)
                        DW_AT_data_member_location [DW_FORM_data1]      (0x00)

0x0000009f:           NULL

0x000000a0:         DW_TAG_variant
                      DW_AT_discr_value [DW_FORM_data8] (0x00000000ffffffff)

0x000000a2:           DW_TAG_member
                        DW_AT_name [DW_FORM_strp]       ("TwoInts")
                        DW_AT_type [DW_FORM_ref4]       (0x000000c4 "t3::Foo::TwoInts")
                        DW_AT_alignment [DW_FORM_udata] (4)
                        DW_AT_data_member_location [DW_FORM_data1]      (0x00)

0x000000ad:           NULL

0x000000ae:         DW_TAG_variant
                      DW_AT_discr_value [DW_FORM_data1] (0x00)

0x000000b0:           DW_TAG_member
                        DW_AT_name [DW_FORM_strp]       ("ThreeShorts")
                        DW_AT_type [DW_FORM_ref4]       (0x000000e2 "t3::Foo::ThreeShorts")
                        DW_AT_alignment [DW_FORM_udata] (4)
                        DW_AT_data_member_location [DW_FORM_data1]      (0x00)

0x000000bb:           NULL

0x000000bc:         NULL

Example 2

Discriminant type is 64 bit signed integer.

#[repr(i64)]
pub enum Foo {
    Unit = -2,
    TwoInts(u32, u32) = -1,
    ThreeShorts{x: u16, y: u16, z: u16} = 0,
}

DWARF:

0x00000079:     DW_TAG_structure_type
                  DW_AT_name [DW_FORM_strp]     ("Foo")
                  DW_AT_byte_size [DW_FORM_data1]       (0x10)
                  DW_AT_alignment [DW_FORM_udata]       (8)

0x00000080:       DW_TAG_variant_part
                    DW_AT_discr [DW_FORM_ref4]  (0x00000085)

0x00000085:         DW_TAG_member
                      DW_AT_type [DW_FORM_ref4] (0x0000010e "i64")
                      DW_AT_alignment [DW_FORM_udata]   (8)
                      DW_AT_data_member_location [DW_FORM_data1]        (0x00)
                      DW_AT_artificial [DW_FORM_flag_present]   (true)

0x0000008c:         DW_TAG_variant
                      DW_AT_discr_value [DW_FORM_data1] (0xfe)

0x0000008e:           DW_TAG_member
                        DW_AT_name [DW_FORM_strp]       ("Unit")
                        DW_AT_type [DW_FORM_ref4]       (0x000000b7 "t3::Foo::Unit")
                        DW_AT_alignment [DW_FORM_udata] (8)
                        DW_AT_data_member_location [DW_FORM_data1]      (0x00)

0x00000099:           NULL

0x0000009a:         DW_TAG_variant
                      DW_AT_discr_value [DW_FORM_data1] (0xff)

0x0000009c:           DW_TAG_member
                        DW_AT_name [DW_FORM_strp]       ("TwoInts")
                        DW_AT_type [DW_FORM_ref4]       (0x000000be "t3::Foo::TwoInts")
                        DW_AT_alignment [DW_FORM_udata] (8)
                        DW_AT_data_member_location [DW_FORM_data1]      (0x00)

0x000000a7:           NULL

0x000000a8:         DW_TAG_variant
                      DW_AT_discr_value [DW_FORM_data1] (0x00)

0x000000aa:           DW_TAG_member
                        DW_AT_name [DW_FORM_strp]       ("ThreeShorts")
                        DW_AT_type [DW_FORM_ref4]       (0x000000dc "t3::Foo::ThreeShorts")
                        DW_AT_alignment [DW_FORM_udata] (8)
                        DW_AT_data_member_location [DW_FORM_data1]      (0x00)

0x000000b5:           NULL

0x000000b6:         NULL

Note that the form for DW_AT_discr_value attribute should not be DW_FORM_dataX, rather it should be DW_FORM_sdata.

Meta

rustc --version --verbose:

rustc 1.74.1 (a28077b28 2023-12-04)
binary: rustc
commit-hash: a28077b28a02b92985b3a3faecf92813155f1ea1
commit-date: 2023-12-04
host: x86_64-unknown-linux-gnu
release: 1.74.1
LLVM version: 17.0.4
@sdnr1 sdnr1 added the C-bug Category: This is a bug. label May 15, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 15, 2024
@jieyouxu jieyouxu added A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-debugging Working group: Bad Rust debugging experiences and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-debugging Working group: Bad Rust debugging experiences
Projects
None yet
Development

No branches or pull requests

3 participants