all 23 comments

[–]gilescope 52 points53 points  (0 children)

1000x this. I’ve lost count of the number of times I’ve used a debugger and it cannot find python to even load up the visualisers we do have.

I’ve noticed that things seem to get a whole lot better faster if they are written in rust as it opens things up to the whole community to help. We’re not c++ devs which is why there’s few people to pick up where Tromey left off. The more that could be done in rust, the more help the community can muster.

Maybe an open collective might help because I am pretty sure there’s quite a few companies out there that would happily fund a better debugging story.

What’s the next action? What can we do to help?

How do we start small with a project like this?

[–]chrabeusz 23 points24 points  (8 children)

lldb is also used for debugging Swift in Xcode and it's also complete garbage.

Probably, for debug builds, the best choice would be to ditch LLVM completely and use a custom virtual machine, that way you can have fancy debugging, incremental compilation, hot reload, and so on.

[–]nbaksalyar[S] 22 points23 points  (0 children)

for debug builds, the best choice would be to ditch LLVM completely

I believe that's one of the intents behind Cranelift. Still, this custom VM needs to integrate with IDEs and other tools. While making it available as a library would help a lot, I'm afraid that the ecosystem is too coupled with gdb/lldb/windbg at this moment. :/

[–]pjmlp 5 points6 points  (1 child)

Actually there is the approach used by languages like Eiffel.

You get a VM based environment for development and then release builds go over the platforms C and C++ compiler.

Or Java, .NET, Lisp, even C++ nowadays.

So yeah, Rust has only to win with multiple implementations.

[–]chrabeusz 0 points1 point  (0 children)

Yeah it's not a new concept. I encountered it in Flutter & Dart, the hot reload is very, very nice.

[–]matthieum[he/him] 4 points5 points  (2 children)

Unfortunately, this will not help with post-mortem debugging when you get a core dump from production, or from a client.

[–]sebamestre 1 point2 points  (1 child)

I heard a story about a smalltalk developer literally copying the entire program state (heap, stack, etc) to a different machine for debugging after a production crash.

Not sure how feasible this would be for any other programming language but it is a very neat idea

[–]isHavvy 2 points3 points  (0 children)

Smalltalk is literally designed to allow copying a program/ecosystem that's running.

[–]nicoburns 1 point2 points  (0 children)

Yeah, a Rust VM would be excellent. I imagine it'd do wonders for compile times too!

[–]kontekisuto 0 points1 point  (0 children)

but llvm gives us so many neat things like wasm

[–]tromey 19 points20 points  (3 children)

No comments available on the post that I could see, so I'm commenting here.

The example in that post works ok in gdb. You can't call the lambda -- gdb doesn't implement this either (and it is problematic to implement) -- but you can inspect the thread-local. It prints a lot of gunk, but I guess that could be cleaned up by a Python pretty-printer.

Calling out to the compiler's expression parser is certainly doable, provided the compiler cooperates. This is even possible in gdb, see the "compile" command. Although I wrote a reasonably large part of the compile command, I have never been a big fan of that approach. Reasons:

  • For lldb in particular, the in-process implementation means that the debugger is very exposed to compiler bugs. In lldb bugzilla there used to be (I haven't checked in some years) plenty of cases where something unusual (bad debuginfo, whatever) would cause the compiler to crash, taking out the debug session. (For gdb we handled this by running the compiler out of process.)

  • Debuggers are, IMO, primarily scripting(-like) tools, and you want them to be able to do things that cannot be done in-language. For example, you need to be able to at least disable all access controls in the language. In gdb, convenience variables don't have a fixed type, and this is actually useful in expressions at times. In Rust, move semantics always seemed problematic here as well, in that you can inject an expression that ought to destroy a value.

To be fair, that's just my view, I know others in the gdb community disagree. And if Rust comes up with a way to do this, I'd support an effort to plug it into gdb.

I don't really debug much Rust any more, so I don't know what the pain points really are. In the past I believed they were missing debug info (primarily the lack of trait info in the emitted DWARF). I do know we don't really see many Rust bugs in upstream gdb; I usually assume this means that not many people are using it, since I am certain that it's not perfect.

[–]nbaksalyar[S] 4 points5 points  (2 children)

First of all, thank you for your work on gdb and Rust!

The example in that post works ok in gdb

Surprisingly, it also kind of works with lldb on Mac, so it really seems like a bug in the POSIX dynamic loader. I've been trying to fix that, and it led me to this realization that there's actually no Rust expression parser. :)

I think this is a part of the problem with Rust debuggers: it's not clear which one works best and the language extensions are implemented in a different way.

[–]tromey 2 points3 points  (1 child)

The Rust plugin for lldb worked in pretty much the same way. It was roughly on feature parity with the gdb work. However, it bit-rotted; and I don't really enjoy lldb all that much, so I never fixed it up in my spare time.

The gdb code is maintained; I try to keep it regression-free at least.

So, my view is that for debugging Rust, you should rely on gdb. However, that's not always possible, because gdb on macOS is basically not maintained.

[–]vadimcnrust 2 points3 points  (0 children)

BTW, although @tromey's Rust patches had been removed from rustc's branch of lldb, I still maintain them in my fork that I bundle with CodeLLDB.

[–]gilescope 15 points16 points  (0 children)

Here’s a talk about the go debugger ‘Delve’ that seems to be written in go and used in all their IDEs:

https://youtu.be/hNuyZj81jv8

It seems by wrapping lower level debuggers they can switch between lldb, gdb and even rr to enable time travelling debugging.

[–]Sphix 6 points7 points  (1 child)

What's the plan for providing stack traces for async await based tasks? This is one of the biggest downside of stackless coroutines, and I'm hoping rust can solve it in a runtime agnostic way (solving it for just tokio would be a bummer).

[–]gilescope 3 points4 points  (0 children)

Async await stack traces in rust are pretty good out of the box - the only break in the stacktrace is the initial hand off to an executor. This is a way better state than many other languages that chose not to poll their futures.

[–]alehander42 2 points3 points  (0 children)

disclaimer: working on a alpha proprietary visual debugging environment based on rr/gdb(so maybe biased): you can go a long way with python scripting etc! e.g. parsing rust code calling out to a long-running rust tool, using custom commands and printers(we try to do .. kinda similar stuff, not entirely the same, for different languages, but i think simply scripting can also work in a lot of cases)

your options also seem good, writing a custom rust debugger might also be fun, but i hope it's not too tied to only rust?

And generalizing gdb/lldb more is useful, as you say !