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

Support GDB with native rust support #37410

Closed
wants to merge 7 commits into from
Closed

Conversation

TimNN
Copy link
Contributor

@TimNN TimNN commented Oct 25, 2016

This PR aims at making the debuginfo tests pass with the newer GDB versions which have native rust support (RGDB)

To that end debuginfo tests now support three GDB prefixes:

  • gdb applicable to both GDB varieties
  • gdbg (Generic) only applicable to the old GDB
  • gdbr (Rust) only applicable to the new RGDB

Whether the GDB has rust support is detected based on it's version: GDB >= 7.11.10 is considered to have rust support.


Test updates

All tests have been updated to the new GDB version. Note that some tests currently require the GDB trunk1.


How to move forward with this PR:

I propose the following steps for moving forward with this PR:

  • Validate the general approach of this PR (the gdb-, gdbg- and gdbr- split)
  • Validate the approach taken for updating the debuginfo tests (I've checked this since there's (almost) no set language c left, which was my main concern)
  • Determine how to distinguish between the new and old GDB (and implement that)
  • Add one or more non-gating build bots with the new GDB (blocked on the previous item, can happen after this PR has been merged)
  • If the new bots pass the tests, gate on them
  • (Maybe) update the remaining tests to run without set syntax c (in a separate PR)
  • (Maybe) add tests specifically for the new GDB (in a separate PR / open an issue about this)

I'm not completely sure about the build bot related steps (cc @alexcrichton), the current approach was suggested to prevent any downtime / broken build time between a new GDB gating builder being added and this PR being merged.


Suboptimal RGDB Output

I've found several places where the output of RGDB is not ideal. They are tagged with // FIXME, here is an overview:

  • Trait references are not syntactically correct: type_names::&Trait2<...> (WontFix: the issue is minor and from @Manishearth below: "to properly address the trait issue we should wait for trait object support")
  • Univariant enums are printed as <error reading variable> (Fixed in GDB trunk1)
  • Unions are printed as <error reading variable> (Fixed in GDB trunk1)
  • "Nil Enums" (enum Foo {}) are printed as <error reading variable> (WontFix: the are not supposed to exist)
  • I have found no alternative for sizeof(var) in rust mode, so had to resort to set language c (Fixed in GDB trunk1)
  • I have found not way of interpreting a value as a specific enum variant, so had to resort to set language c (Fixed in GDB trunk1)
  • Before the initial run command, gdb does not realise it should be in rust mode (thus, if one want's to print statics before the run one has to explicitly set language rust) (maybe this is intended / expected behaviour, if so, someone please tell me ;) ("Expected" / current behaviour of GDB: picks up jemalloc, see Support GDB with native rust support #37410 (comment))

1: Or rather in @Manishearth's trunk, waiting to be merged upstream.


cc @alexcrichton, @michaelwoerister, #36323

@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

@TimNN
Copy link
Contributor Author

TimNN commented Oct 26, 2016

Edit: I moved the content / checklist of this comment to the original post.

@michaelwoerister
Copy link
Member

Oh nice! This has been near the top of my list of things to do for months. I give you more feedback later today.

@michaelwoerister
Copy link
Member

Validate the general approach of this PR (the gdb-, gdbg- and gdbr- split)

I think we can check this box. This is basically what we planned to do in the tools team and it allows for nice sharing of commands when writing test cases.

@michaelwoerister
Copy link
Member

Determine how to distinguish between the new and old GDB (and implement that)

There is some version detection we already do for LLDB via the output of lldb --version. What we have learned from this is:

  • the output of --version can be rather unreliable, because distros and vendors will modify it as they please,
  • but that's not much of a problem because there's still a rather limited number of general formats and we can just add logic for those as we come across them.

So I'd say it's definitely possible to go down that road. I'm not sure the feature detection approach is more stable (it depends on how stable the error message is). I'd slightly favor using the same approach we are using for LLDB.

@michaelwoerister
Copy link
Member

Ideally I'd like both versions of GDB to be tested on all gating build bots. We could let configure define a PRE_RUST_GDB and a RUST_ENABLED_GDB, both of which will be used by compiletest to run debuginfo tests. configure would take explicit arguments for both and fall back to detecting which category gdb on PATH falls into if nothing is specified. That would be backwards compatible.

Alternatively we could do auto-detection only and install a good mix of old and new GDB versions on the build bots.

What do you think, @alexcrichton?

@michaelwoerister
Copy link
Member

Specifically, in rust mode, for the command print 'basic_types_globals::I', the '...' is interpreted as an unterminated char literal, and I don't know how to fix this.

For me, just specifying I (i.e. the unqualified name of the global) seems to work in the new version.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 26, 2016

Specifically, in rust mode, for the command print 'basic_types_globals::I', the '...' is interpreted as an unterminated char literal, and I don't know how to fix this.

For me, just specifying I (i.e. the unqualified name of the global) seems to work in the new version.

Ok, I can try that.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 26, 2016

Specifically, in rust mode, for the command print 'basic_types_globals::I', the '...' is interpreted as an unterminated char literal, and I don't know how to fix this.

For me, just specifying I (i.e. the unqualified name of the global) seems to work in the new version.

That seems to have worked, I updated the two tests where I encountered this situation (basic-types-(mut)-globals) to work without set language c.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 27, 2016

I've started removing some of the set syntax c lines. While doing so, I have tagged several places as // FIXME where RGDB behaves suboptimal (type_names::&Trait2<...>) or outright bad ($4 = <error reading variable> for univariant enums).

cc @tromey, @Manishearth on the last issue.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 27, 2016

I've been removing some more set syntax c lines, and found two more FIXME's, I'm gonna start tracking all these in the top post.

// gdb-check:$3 = {{__0 = 4820353753753434}}
// gdbg-check:$3 = {{__0 = 4820353753753434}}
// FIXME
// gdbr-check:$3 = <error reading variable>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fixed. Trying on trunk in a moment, but this works from a gdb I have from august.

(gdb) p univariant_ref
$1 = (borrowed_enum::Univariant *) 0x7fff5fbff820
(gdb) ptype univariant_ref
type = union borrowed_enum::Univariant {
    borrowed_enum::TheOnlyCase;
} *

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'm currently working from the GDB that ships with Ubuntu Yakkety Yak (GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu1) 7.11.90.20161005-git). I'll see about updating to a newer version tomorrow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try and build trunk, and let me know which bugs persist.

Copy link
Contributor Author

@TimNN TimNN Oct 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Manishearth: I tried again with a trunk build (GNU gdb (GDB) 7.12.50.20161027-git) and got four different failures (in pretty tests, I see warning: Unsupported auto-load script at offset 0 in section .debug_gdb_scripts but haven't investigated further yet). Edit: I may have build gdb without python support, trying again now.

Also, I noticed, that in your snippet you did not dereference the univariant_ref, is it possible that the <error reading variable> occurs only when dereferencing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I got myself a gdb with python support and the pretty tests pass again, along with all other tests.

That is, gdb-command:print *univariant_ref still prints <error reading variable>.

@Manishearth
Copy link
Member

Manishearth commented Oct 27, 2016

Yeah, the univariant thing is a bug. Fixed in https://sourceware.org/ml/gdb-patches/2016-10/msg00778.html. Try applying that patch and let me know how many errors are left, it should fix all the univariant issues. I think to properly address the trait issue we should wait for trait object support (which may take some time), though I could try to make it look prettier for now.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 28, 2016

@Manishearth: I'll try the patch tomorrow later today.

The trait issue doesn't seem that important to me - sure, it doesn't look great but it's still easy to understand. So if there's an easy fix / you've got the time, go for it, otherwise I wouldn't bother and wait for "trait object support".

@Manishearth
Copy link
Member

The fix would be to print it as &Trait instead of struct type_name::&Trait, but that's not a major difference and really it kind of is struct type_name::&Trait (internally). I think type_name::&Trait is a string generated by rustc, too. I'll wait for trait object support, though if you want this fixed earlier, see if you can make rustc generate the right string.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 28, 2016

@Manishearth: the patch worked flawlessly, thanks!

There are currently two issues left (although I've not yet gone through all the tests which were "fixed" by simply adding set language c at the top):

@TimNN
Copy link
Contributor Author

TimNN commented Oct 28, 2016

I went through all the tests to which I previously added set language c and was able to remove all but two instances of set language c (see the FIXME section in the top post).

@Manishearth: at this point I'm most interested in whether it is possible to treat an enum value as being a specific variant in an expressions (see the recursive-struct test).

@Manishearth
Copy link
Member

You can access enum values already. Pretend the type is the struct (in case of a struct variant) or tuple struct corresponding to the variant and use named or numbered field access. E.g. use some.0 to get the innards of a Some.

That test uses arrow operators btw, those will not work for rust and you have to explicitly deref.

@alexcrichton
Copy link
Member

Alternatively we could do auto-detection only and install a good mix of old and new GDB versions on the build bots.

My absolutely ideal world would look like:

  • The configure scripts auto-detects what gdb is being used (somehow)
  • The configure script also has a flag along the lines of --assert-pre-rust-gdb
  • The bots pass these flags appropriately on two bots

It may unfortunately take awhile to get the bots online and working here, but I don't think that should block this PR. We should land this ahead of that and then flesh out the bugs once we get a real builder up and running.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 28, 2016

@Manishearth: I think I understand what you said however now the following does not seem to make much sense:

(gdb) print stack_unique.next.val
Attempting to access named field val of tuple variant recursive_struct::Opt<Box<recursive_struct::UniqueNode<u16>>>::Val, which has only anonymous fields
(gdb) print stack_unique.next.0
Variant recursive_struct::Opt<Box<recursive_struct::UniqueNode<u16>>>::Val is not a tuple variant
(gdb)

The two error messages seem contradictory to me.

This is from the recursive-struct test (without set language c) but I've extracted the relevant definitions here:

enum Opt<T> {
    Empty,
    Val { val: T }
}

struct UniqueNode<T> {
    next: Opt<Box<UniqueNode<T>>>,
    value: T
}


fn main() {
    let stack_unique: UniqueNode<u16> = UniqueNode {
        next: Val {
            val: box UniqueNode {
                next: Empty,
                value: 1,
            }
        },
        value: 0,
    };
}

Edit: The problem goes away, when adding a third variant to Opt, so I guess the problem is with option like enums (which have non-zero / pointer optimizations).

@Manishearth
Copy link
Member

Manishearth commented Oct 28, 2016

Hm, that sounds like a bug. cc @tromey

@Manishearth
Copy link
Member

Manishearth commented Oct 28, 2016

"Nil Enums" (enum Foo {}) are printed as <error reading variable> (probably expected? I'm not sure what to make of that test)

These aren't supposed to exist as values. GDB throws an error in this case (not sure why the error text isn't shown, that might be a bug)

Unions are printed as <error reading variable>

There's no support for these yet (they didn't exist when we did the rust support). I'll try to add it later.

Regarding set language rust, I think there was an issue at one point with gdb not autodetecting this but it should work now. If this still happens I think it's a bug. IIRC last time it was a rustc bug (not emitting the right dwarf language tag). It works for me on last week's nightly + gdb master.

@Manishearth
Copy link
Member

diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 9d13353..9569584 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -1736,7 +1736,9 @@ tuple structs, and tuple-like enum variants"));
        variant_type = TYPE_FIELD_TYPE (type, disr.field_no);

        if (variant_type == NULL
-       || rust_tuple_variant_type_p (variant_type))
+           || (disr.is_encoded
+               ? rust_tuple_struct_type_p (variant_type)
+               : rust_tuple_variant_type_p (variant_type)))
          error(_("Attempting to access named field %s of tuple variant %s, \
 which has only anonymous fields"),
            field_name, disr.name);

This should fix the struct variant issue. Not yet probed properly into this, it could be the wrong fix.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 28, 2016

This should fix the struct variant issue.

This did indeed fix my struct variant issues.

That test uses arrow operators btw, those will not work for rust and you have to explicitly deref.

(Emphasis mine) Just, FYI, I found that explicitly dereferencing was not necessary, just using the dot operator was sufficient.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 28, 2016

"Nil Enums" (enum Foo {}) are printed as (probably expected? I'm not sure what to make of that test)

These aren't supposed to exist as values. GDB throws an error in this case (not sure why the error text isn't shown, that might be a bug)

Yeah, I thought so, which is why I was confused that this test even exists.

Regarding set language rust, I think there was an issue at one point with gdb not autodetecting this but it should work now. If this still happens I think it's a bug. IIRC last time it was a rustc bug (not emitting the right dwarf language tag). It works for me on last week's nightly + gdb master.

set language rust is still required in to places on GDB master. Note that as soon as the gdb run command is executed, gdb correctly detects the language as rust. The problem only occurs when inspecting statics before executing run.

@TimNN
Copy link
Contributor Author

TimNN commented Oct 28, 2016

Since the test have all been updated now, I'm gonna come back on the gdb version handling:

auto-detection

No matter what approach we choose it seems as if auto-detecting is desirable / required. Since @michaelwoerister expressed concerns about the stability of the error message (which I verified: gdb 6.6 for example, has a different error message) we should choose a version based approach.

I'm not familiar with the versioning scheme used by gdb (what's the relation between 7.11.1 and 7.11.10?) but based on some guessing I would suggest treating gdb >= 7.11.10 as having rust support.

build system

@alexcrichton and @michaelwoerister have expressed somewhat contrary opinions on this point. Irrespective of which approach we implement, I propose

  • to have the gdb-kind detection in compiletest (otherwise we'll have to duplicate that the logic between rustbuild & configure)
  • to add an option to compiletest, rustbuild & configure to specify the gdb executable (defaulting to gdb)

Which leaves us with two other requests (which may both be implemented):

  • @michaelwoerister expressed interest in having one bot test two gdb versions. To accomplish this I propose adding a gdb-extra option to rustbuild & configure, which defaults to "unset" and, if set, causes compiletest to be invoked twice, once for gdb and once for gdb-extra.
  • @alexcrichton expressed interest in asserting the kind of gdb. To accomplish this I propose adding a assert-gdb-kind=pre-rust|post-rust option to rustbuild, configure & compiletest, defaulting to "unset". If this option is set, compiletest will validate the assertion. This has the drawback of delaying the assertion until compiletest is run. (An analogous option could be added for gdb-extra.

@Manishearth
Copy link
Member

I have found not way of interpreting a value as a specific enum variant, so had to resort to set language c

Is this still the case?

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Nov 4, 2016
Support GDB with native rust support

This PR aims at making the debuginfo tests pass with the newer GDB versions which have native rust support (RGDB)

To that end debuginfo tests now support three GDB prefixes:
- `gdb` applicable to both GDB varieties
- `gdbg` (**G**eneric) only applicable to the old GDB
- `gdbr` (**R**ust) only applicable to the new RGDB

Whether the GDB has rust support is detected based on it's version: GDB >= 7.11.10 is considered to have rust support.

---

**Test updates**

All tests have been updated to the new GDB version. Note that some tests currently require the GDB trunk<sup>1</sup>.

---

**How to move forward with this PR:**

I propose the following steps for moving forward with this PR:
- [x] Validate the general approach of this PR (the `gdb-`, `gdbg-` and `gdbr-` split)
- [x] Validate the approach taken for updating the debuginfo tests (I've checked this since there's (almost) no `set language c` left, which was my main concern)
- [x] Determine how to distinguish between the new and old GDB (and implement that)
- [ ] Add one or more non-gating build bots with the new GDB (blocked on the previous item, can happen after this PR has been merged)
- [ ] If the new bots pass the tests, gate on them
- [x] \(Maybe) update the remaining tests to run without `set syntax c` (in a separate PR)
- [ ] \(Maybe) add tests specifically for the new GDB (in a separate PR / open an issue about this)

I'm not completely sure about the build bot related steps (cc @alexcrichton), the current approach was suggested to prevent any downtime / broken build time between a new GDB gating builder being added and this PR being merged.

---

**Suboptimal RGDB Output**

I've found several places where the output of RGDB is not ideal. They are tagged with `// FIXME`, here is an overview:
- [x] Trait references are not syntactically correct: `type_names::&Trait2<...>` (**WontFix**: the issue is minor and from @Manishearth below: "to properly address the trait issue we should wait for trait object support")
- [x] Univariant enums are printed as `<error reading variable>` (**Fixed** in GDB trunk<sup>1<sup>)
- [x] Unions are printed as `<error reading variable>` (**Fixed** in GDB trunk<sup>1</sup>)
- [x] "Nil Enums" (`enum Foo {}`) are printed as `<error reading variable>` (**WontFix**: the are not supposed to exist)
- [x] I have found no alternative for `sizeof(var)` in rust mode, so had to resort to `set language c` (**Fixed** in GDB trunk<sup>1</sup>)
- [x] I have found not way of interpreting a value as a specific enum variant, so had to resort to `set language c` (**Fixed** in GDB trunk<sup>1</sup>)
- [x] Before the initial `run` command, gdb does not realise it should be in rust mode (thus, if one want's to print statics before the run one has to explicitly `set language rust`) (maybe this is intended / expected behaviour, if so, someone please tell me ;) (**"Expected"** / current behaviour of GDB: picks up jemalloc, see rust-lang#37410 (comment))

<sup>1</sup>: Or rather in @Manishearth's trunk, waiting to be merged upstream.

---

cc @alexcrichton, @michaelwoerister, rust-lang#36323
@bors
Copy link
Contributor

bors commented Nov 5, 2016

⌛ Testing commit f7107f3 with merge 9d34708...

@bors
Copy link
Contributor

bors commented Nov 5, 2016

💔 Test failed - auto-win-msvc-64-cargotest

bors added a commit that referenced this pull request Nov 5, 2016
@TimNN
Copy link
Contributor Author

TimNN commented Nov 5, 2016

I fixed the android failure (#37597 (comment)).

@alexcrichton
Copy link
Member

@TimNN awesome thanks! I'll update the rollup

@alexcrichton
Copy link
Member

@bors: r+ force clean

@bors
Copy link
Contributor

bors commented Nov 5, 2016

📌 Commit d2cb515 has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Nov 5, 2016

⌛ Testing commit d2cb515 with merge 366636e...

@bors
Copy link
Contributor

bors commented Nov 5, 2016

💔 Test failed - auto-win-gnu-32-opt-rustbuild

@TimNN
Copy link
Contributor Author

TimNN commented Nov 5, 2016

I fixed the windows failure (although that seems to have been fixed in the rollup already).

bors added a commit that referenced this pull request Nov 6, 2016
@alexcrichton
Copy link
Member

Hm I must have botched the merge but this was landed in #37597, so closing.

@TimNN TimNN deleted the gdb-next-gen branch November 6, 2016 16:57
@michaelwoerister
Copy link
Member

🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants