Bug 21097 - can't disambiguate between enum and other types for rust
Summary: can't disambiguate between enum and other types for rust
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: rust (show other bugs)
Version: 7.12.1
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-01-31 21:20 UTC by Shawn Walker-Salas
Modified: 2022-01-24 00:47 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2017-02-01 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Shawn Walker-Salas 2017-01-31 21:20:42 UTC
I'm working on a port of rust to another platform and I'm trying to debug a crash in one of the internal functions.

I built a copy of gdb 7.12.1 and was trying to figure out the syntax for specifying types when printing values.

This seems to work for the most part:

(gdb) ptype syntax::ast::Ident
type = struct syntax::ast::Ident {
  name: syntax::symbol::Symbol,
  ctxt: syntax::ext::hygiene::SyntaxContext,
}

However, some cases produce unexpected results:

(gdb) ptype syntax::ast::Mod  
type = struct syntax::ast::Mod {
  RUST$ENUM$DISR: syntax::ast::ItemKind,
  __0: syntax::ast::Mod,
}

Does not match what I expect from src/libsyntax/ast.rs:

pub struct Mod {
    /// A span from the first token past `{` to the last token until `}`.
    /// For `mod foo;`, the inner span ranges from the first token
    /// to the last token in the external file.
    pub inner: Span,
    pub items: Vec<P<Item>>,
}

Is this expected? What are the caveats when attempting to debug the rust compiler itself? The rust compiler was built with debug info and without optimizations enabled for debugging purposes.

Bug 20168 seems related.
Comment 1 Shawn Walker-Salas 2017-01-31 21:35:15 UTC
Another respondent to where I originally posted this query pointed out that "Your ptype is showing the enum variant ItemKind::Mod and not the type Mod, both are from syntax::ast."
Comment 2 Tom Tromey 2017-02-01 23:24:20 UTC
Confirmed even with my relatively old rustc build.
Comment 3 Tom Tromey 2017-02-01 23:31:40 UTC
I see two definitions of Mod at the same level in the debuginfo.
I didn't investigate further but this is in keeping with comment#1.
I think there's a rustc bug open about this already, I will dig it up later.

 <3><196df>: Abbrev Number: 29 (DW_TAG_structure_type)
    <196e0>   DW_AT_name        : (indirect string, offset: 0x1c7f5f): Mod
    <196e4>   DW_AT_byte_size   : 48
 <4><196e5>: Abbrev Number: 26 (DW_TAG_member)
    <196e6>   DW_AT_name        : (indirect string, offset: 0x154): RUST$ENUM$DISR
    <196ea>   DW_AT_type        : <0x16dc0>
    <196ee>   DW_AT_data_member_location: 0
 <4><196ef>: Abbrev Number: 26 (DW_TAG_member)
    <196f0>   DW_AT_name        : (indirect string, offset: 0xe8): __0
    <196f4>   DW_AT_type        : <0x196fa>
    <196f8>   DW_AT_data_member_location: 8
 <4><196f9>: Abbrev Number: 0
 <3><196fa>: Abbrev Number: 29 (DW_TAG_structure_type)
    <196fb>   DW_AT_name        : (indirect string, offset: 0x1c7f5f): Mod
    <196ff>   DW_AT_byte_size   : 40
 <4><19700>: Abbrev Number: 26 (DW_TAG_member)
    <19701>   DW_AT_name        : (indirect string, offset: 0x4c0f): inner
    <19705>   DW_AT_type        : <0x1fad05>
    <19709>   DW_AT_data_member_location: 0
 <4><1970a>: Abbrev Number: 26 (DW_TAG_member)
    <1970b>   DW_AT_name        : (indirect string, offset: 0x33cd): items
    <1970f>   DW_AT_type        : <0x1c25bd>
    <19713>   DW_AT_data_member_location: 16
Comment 4 Tom Tromey 2017-02-02 04:26:54 UTC
Maybe it is https://github.com/rust-lang/rust/issues/32924
That seems related, though the example there is a bit different.
Comment 5 Tom Tromey 2017-02-02 16:02:10 UTC
I can get the same unusual debuginfo from a simple test:

pub struct Mod {
    v: i32
}
pub enum ItemKind {
    Mod(Mod)
}

fn x() -> ItemKind {
    return ItemKind::Mod(Mod{v: 23});
}

pub fn main() {
    match x() {
        ItemKind::Mod(z) => {
            println!("{}", z.v);
        }
    }
}


This yields:

 <2><5d>: Abbrev Number: 7 (DW_TAG_structure_type)
    <5e>   DW_AT_name        : (indirect string, offset: 0x353): Mod
    <62>   DW_AT_byte_size   : 4
 <3><63>: Abbrev Number: 8 (DW_TAG_member)
    <64>   DW_AT_name        : (indirect string, offset: 0x141): __0
    <68>   DW_AT_type        : <0x6e>
    <6c>   DW_AT_data_member_location: 0
 <3><6d>: Abbrev Number: 0
 <2><6e>: Abbrev Number: 7 (DW_TAG_structure_type)
    <6f>   DW_AT_name        : (indirect string, offset: 0x353): Mod
    <73>   DW_AT_byte_size   : 4
 <3><74>: Abbrev Number: 8 (DW_TAG_member)
    <75>   DW_AT_name        : (indirect string, offset: 0x351): v
    <79>   DW_AT_type        : <0x5e9>
    <7d>   DW_AT_data_member_location: 0
 <3><7e>: Abbrev Number: 0


However, I couldn't get gdb to print the wrong type here.
So, something else must be going on.
Comment 6 Tom Tromey 2017-02-02 17:01:59 UTC
I had an outdated gdb.  With my simple test case and a new
gdb build I get:

(gdb) ptype q::Mod
type = struct q::Mod (
  q::Mod,
)

... which is the wrong Mod.
Also the output here is weird.  Ideally it would print Mod(q::Mod).
Comment 7 Tom Tromey 2017-02-03 04:11:37 UTC
> Also the output here is weird.  Ideally it would print Mod(q::Mod).

Err... we shouldn't really access this directly.
But 'ptype q::ItemKind' prints:

type = enum q::ItemKind {
  Mod,
}

... where I think Mod(Mod) would perhaps be more useful.
Comment 8 Tom Tromey 2017-02-03 04:25:59 UTC
(In reply to Tom Tromey from comment #7)

> But 'ptype q::ItemKind' prints:

This happens because the DWARF for ItemKind doesn't have a name for
the first member.

 <2><50>: Abbrev Number: 5 (DW_TAG_union_type)
    <51>   DW_AT_name        : (indirect string, offset: 0x357): ItemKind
    <55>   DW_AT_byte_size   : 4
 <3><56>: Abbrev Number: 6 (DW_TAG_member)
    <57>   DW_AT_type        : <0x5d>
    <5b>   DW_AT_data_member_location: 0
 <3><5c>: Abbrev Number: 0


The "skip_to" logic in rust_print_type is wrong for this type.
Manually setting skip_to=0 makes it print the right thing.
Maybe this code is assuming that an enum must have more than one
member.
Comment 9 Sourceware Commits 2017-02-04 05:23:04 UTC
The master branch has been updated by Tom Tromey <tromey@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f0fd41c1926984fd1a524ff551286cba694539a0

commit f0fd41c1926984fd1a524ff551286cba694539a0
Author: Tom Tromey <tom@tromey.com>
Date:   Fri Feb 3 22:11:46 2017 -0700

    Fix ptype of single-member Rust enums
    
    While looking into PR rust/21097, I found that ptype of a
    single-element enum in Rust did not always format the result properly.
    In particular, it would leave out the members of a tuple struct.
    Further testing showed that it also did the wrong thing for ordinary
    struct members as well.
    
    This patch fixes these problems.  I'm marking it as being associated
    with the PR, since that is where the discovery was made; but this
    doesn't actually fix that PR (which I think ultimately is due to a
    Rust compiler bug).
    
    Built and regtested on x86-64 Fedora 25, using the system Rust
    compiler.  I'm checking this in.
    
    2017-02-03  Tom Tromey  <tom@tromey.com>
    
    	PR rust/21097:
    	* rust-lang.c (rust_print_type) <TYPE_CODE_UNION>: Handle enums
    	with a single member.
    
    2017-02-03  Tom Tromey  <tom@tromey.com>
    
    	PR rust/21097:
    	* gdb.rust/simple.exp: Add new tests.
Comment 10 Tom Tromey 2022-01-24 00:47:51 UTC
This works now, presumably because the Rust compiler bug was fixed.