Headcrab, a Rust debugger library

That definitely wasn't the intention! :slight_smile: It's a tongue-in-cheek word play on the Rust's crab mascot (which is the opposite of gross, as I believe) & the critter from the Half-Life universe, which uhh... attaches itself to a host - and that's something we do with debuggers, too. You can find an attempt at our own mascot on the website.

Indeed, there are at least a couple of them: goblin and gimli. We use the latter.


My 10 cents: I think it's cool, and the mascot is cute.
And I really need a debugger.


Rust's crab mascot is fine. It's all about context and juxtaposition.

I'm old school, I have no idea what "half life" unless it's about radio active decay. "headcrab" just conjures up head lice and crabs in my mind. Grossness I'd rather be reminded of.

What you describe about the Half-Life critters makes them sound like Toxoplasma gondii https://www.discovermagazine.com/planet-earth/meet-the-parasites-that-control-human-brains. Even more gross!

Half Life is a game series, first game was released way back in 1998, that's pretty old school by now.

1 Like

I have heard of it.

The first and last computer game I bought was Starglider for my Atari ST 520. In 1987. https://en.wikipedia.org/wiki/Starglider

After many hours of tenaciously playing Starglider I hit it's maximum score of 100,000. At that point the game ended and it gave me a ranking of "Cheat".

I lost interest in games after that.


I see Headcrab is still making the buzz.

That name is genius!

I was wondering if you would have a syntax checker for imports in the toml file? I made a spelling error there and the compiler, very helpfully pointed me to faulty imports, but I did not understand that it was originated in the toml file.

Awesome project. The premise sounds really ambitious. Looking forward to where this project will go.
Love the name and the symbolism behind the name too :grinning:


Please file gdb bug reports for problems you find. There's a "rust" component there that you can use. Thanks.

The problem was that gdb was not codesigned. Could be solved by following those instructions until point 9, and then those instructions from 1.3 (since the drag to systems keychain did not produce a cert file on Desktop)

I am pretty sure many people reported that already, but if you want I can file a report :crayon: :email:

1 Like


Thanks for working this. The debugging experience in Rust could definitely be better.

You mention async in your blogpost. It's indeed really hard to debug deadlocks in tokio, for example, with GDB. Hope this will improve in the future :slight_smile:


Hi everyone,

This month has flown by already, and we have another project update!

To highlight just a few changes, here's what's been improved this month:

  • Source disassembly.
  • Stack unwinding.
  • Memory writing and reading functions.
  • Reading local variables.
  • Watchpoints on Linux.

You can find a full list of changes in the newsletter on our website, along with a demo for the command line example.


It is fantastic to hear your progress. I am waiting for your release. I love rust but I am not able to propose it as an alternative lang due to its debugger support. I use VSCode in windows and I have tried vscode-lldb and vsdbg. Out of these two, I felt the latter is better but not the best. Some points I hate with current debuggers,

  • Not able to visualise NDarray (shows just pointers)
  • Not able to set conditional breakpoint on Arc (because struct.read().field1 == 1 is not supported)
  • Not able to visualise slices
  • Most of the time, it is not detecting the breakpoint
  • Slowerdebug runtime (not compile time); When I run my code in debug mode it is excruciatingly slow by taking 5mins and the same on release build takes less than 1s. If I change the optimisation settings, variables are optimised out. Anyway, I don't think you will be able to do anything on this :frowning:
  • It is sad to see Rust community is happy with the current debugger and I don't see a roadmap. Maybe I am spoiled by C# debugger
1 Like

The problem here is that serious optimization involves significant code transformation, including assigning values to registers, potentially in a computationally-altered form, and moving loop-invariant subexpression computations out of loops and control-flow-invariant subexpressions out of if/then/else and match structures. Such optimizations do not leave artifacts that the debugger/programmer can directly relate to source program variables and expressions.

You are right @TomP. However, why is it so slow compared to other lang (C#, pascal etc)? For proving the capability of Rust, I tried porting a pascal code. I am definitely getting 25% improvement in release which is great. However, I am having slow debug which is almost x5 times slower than the pascal. From other sources, I could see praise for pascal in its debug performance but x5 times slower is really unacceptable in my case. Now I am having hard time in convincing my team :frowning:.

Just to clarify, is it slow both when you run the code in debug mode normally (i.e. cargo run from the command line) and under the debugger, or only under the debugger?

Rust uses lots of abstractions which only become zero-cost after optimisation. The debug mode contains next to no optimisations (deliberately, it's hard to debug optimised code) and is well known for generating slow code.

It's not uncommon that newbies come to this forum saying "my rust code is slower than this Python equivalent" because they've just done cargo run, then are blown away when they are told to use cargo run --release and the code is 1000x faster.

If this slow down only happens under the debugger, then I'd make an issue upstream.


This doesn't just happen to newbies and is actually a very valid concern. I think it is wrong to make dev mode the default for cargo build and cargo run; not just is the debuggability of Rust programs very limited in general but dev also has a number of serious issues such as:

  • it applies globally (whereas in other languages you can control the optimisation on a per file level and it is quite common to only enable debugging for the code you're actually interested to debug)
  • dev mode enables debug assertions unconditionally
  • there really is no "optimize lightly" or "optimize for best debugging experience" option like in other languages, the options are only off, normal, crazy, for size and crazy but keep size in mind
  • off is often not an option, e.g. in embedded it is quite typical that a program without optiomisations will not even fit into the flash of a MCU, if you have a tiny MCU even a LED blinky will not even link due to size problems. Also things which are "guaranteed" to be zero-cost like a compiler_fence() will suddenly turn into real code including a panicking branch: https://github.com/rust-lang/rust/issues/68208. Also trivial things will suddenly be so inefficient and slow that using some peripherals (e.g. USB) will simply not work in that setting.

Other languages do a whole better here and people are not only used to that ability but it can actually be a show-stopper for Rust usage.

Personally, I couldn't care less about classical debuggers, but there's a whole lot more attached to the ability to generate debuggable code and Rust really is very sub-par here.

1 Like

I'm curious to know what you feel is missing here.

Reaching for a "classical debugger" has been my last resort in all kind of languages, including assembler, for decades having often found that when a bug is hard proving hard to find then building for and using a debugger hides the bug, make stings worse or cannot even be used. As you point out for embedded systems.

Luckily the need to reach for such a debugger is greatly reduced in Rust as it eliminates all those insidious memory and type errors.

In a nutshell what I wrote above wrt to light optimisations. But Rust has additional challenges due to the lack of language support within the usual debuggers which is hopefully what headcrab is going to rectify. In the last few months the embedded folks have massively stepped up their game with respect to tooling, e.g. via https://probe.rs.

Now all we need is a usable debugger. :wink:

I fully agree, people around me appreciate that because they know when I reach for a debugger, the shit has just hit the fan and things are about get ugly in my vicinity... :sweat_smile:

1 Like

My personal experience with debuggers so far has been the following:

  • In Rust code println! is easier than a debugger. Pretty much only when a program hangs do I use a debugger to get a backtrace.
  • While debugging miscompilation caused by cg_clif, a debugger is pretty useful. Especially with rr to be able to follow an invalid value back to the original miscompilation.
  • In C++ code a debugger is very useful for me, as there is no #[derive(Debug)] equivalent and many of my bugs are caused by memory corruption.