[HN Gopher] Show HN: Unbug - Rust macros for programmatically in...
___________________________________________________________________
Show HN: Unbug - Rust macros for programmatically invoking
breakpoints
This project is inspired by some of the asserts in Unreal engine.
Due to reliance on core_intrinsics it is necessary to develop using
nightly Rust, but there are stubs in place so a production build
will not require nightly. I recently released version 0.2 which
includes no_std support and adds optional log message arguments to
the ensure macro.
Author : BrainBacon
Score : 79 points
Date : 2024-11-20 13:33 UTC (9 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| revskill wrote:
| What does nightly mean ? I hate that you could not know a
| specific version of a nightly.
| nindalf wrote:
| The master branch of the Rust repo is built every night and
| distributed. That's a nightly build. Most people are on the
| stable release, which is updated every six weeks.
|
| A minority use the nightly build for various reasons: a feature
| that hasn't reached stable yet, or because they want to help
| test the nightly releases and prevent bugs from reaching
| stable.
| jtrueb wrote:
| Is it a minority? Are there stats posted for this?
|
| Only recently have I had some projects switching to stable
| after their required features stabilized.
| JoshTriplett wrote:
| https://raw.githubusercontent.com/rust-
| lang/surveys/main/sur...
|
| 89.4% of users surveyed use stable. 31.1% use nightly, but
| there's overlap there (e.g. I use nightly to try out new
| things but don't build things that _depend_ on nightly).
| Only 11.5% of people say they use a crate that requires it.
| littlestymaar wrote:
| > Only recently have I had some projects switching to
| stable after their required features stabilized.
|
| While this used to be very common back then (in 2016-18
| many things where progressively stabilized and you had
| cornerstone libraries switching to stable at almost every
| release) it hasn't been so for the past 5 years.
|
| Rust gets way less "exciting" new features nowadays, as the
| language has settled a lot (there are still moving parts,
| but they are the minority not the norm).
| dvtkrlbs wrote:
| You can pin versions with the rust-toolchain.toml file you need
| to be using Rustup afaik. Nightly is just the daily builds.
| johnisgood wrote:
| I assume any "nightly" version would work in this context,
| meaning it would not refer to a version from a year ago, as
| it would have already been made stable by that point, right?
| traxys wrote:
| "nightly" versions also allow to use unstable features, and
| unstable features may remain so for a very long time
| (potentially forever) without breaking, so an old nightly
| could maybe work
| johnisgood wrote:
| Right, not everything gets merged to stable. In that
| case: letting us know the specifics beyond "nightly" is
| advisable, IMO.
| do_not_redeem wrote:
| The readme does mention the specifics, immediately after
| mentioning nightly.
|
| > BREAKPOINTS REQUIRE ENABLING THE EXPERIMENTAL
| core_intrinsics FEATURE
| johnisgood wrote:
| How do I know which versions of nightly support that
| feature, and that specific version of the feature though?
|
| I like your username.
| GolDDranks wrote:
| Just use a recent nightly and you should be fine. Rust
| project doesn't offically provide support even for old
| stable versions, so "using nightly" with no specifics
| generally means using any nightly build, around or newer
| than, the current stable release.
| monocasa wrote:
| A lot of people pin a specific nightly since the feature
| they're depending on could change (or ostensibly it would
| be in stable), so they can keep working without
| continuously having to track nightly changes or deal with
| it breaking on a different system with a different nightly
| version.
|
| That obviously only works for non-library uses of nightly.
| kookamamie wrote:
| I thought nightly is for nightly builds. I'll get my coat.
| landr0id wrote:
| It's a bit unfortunate wording but it basically requires any
| nightly toolchain version. It uses
| `std::intrinsics::breakpoint()` which is a compiler intrinstic.
| This has been available for a long time, but afaik will never
| be exposed on a stable toolchain.
|
| Per https://dev-doc.rust-lang.org/nightly/unstable-
| book/library-...
|
| >This feature is internal to the Rust compiler and is not
| intended for general use.
| JoshTriplett wrote:
| You could potentially build on stable Rust by emitting the
| breakpoint instructions yourself, at least on popular platforms.
| For instance, `core::arch::asm!("int3")` on x86, or
| `core::arch::asm!("brk #1")` on ARM.
|
| Also, this is providing motivation to want to stabilize a
| breakpoint mechanism, perhaps `core::arch::breakpoint()`. I'm
| going to propose an API Change Proposal (ACP) to the libs-api
| team to see if we can provide that in stable Rust.
| BrainBacon wrote:
| Thanks, yeah I considered using the instructions directly, but
| I was hoping for a more cross-platform option. For my purposes,
| developing in the Bevy engine, nightly isn't a huge blocker.
| Yeah, it would be really great to just have breakpoint support
| in stable Rust, thanks for doing the proposal! I'll consider
| stable support in the meantime.
| amluto wrote:
| Hah, the README says:
|
| > Additonally, debugging may not land on the macro statements
| themselves.
|
| See my comment above, and give int3;nop a try.
| BrainBacon wrote:
| Interesting. Unfortunately, I'm not well versed in
| assembly, is there a similar trick or requirement in arm
| and would that include Apple silicon, or is this something
| specific to `int3` on x86? That may explain why it was
| inconsistent during my development process, I didn't think
| to check if the inconsistency was platform dependent.
| amluto wrote:
| Plain int3 is a footgun: the CPU does not keep track of the
| address of the int3 (at least not until FRED), and it reports
| the address _after_ int3. It's impossible to reliably undo that
| in software, and most debuggers don't even try, and the result
| is a failure to identify the location of the breakpoint. It's
| problematic if the int3 is the last instruction in a basic
| block, and even worse if the optimizer thinks that whatever is
| after the int3 is unreachable.
|
| If Rust's standard library does this, please consider using
| int3;nop instead.
| JoshTriplett wrote:
| Good to know! I've seen the pattern of "int3; nop" before,
| but I've never seen the explanation for why. I'd always
| assumed it involved the desire to be able to live-patch a
| different instruction over it.
|
| In Rust, we're using the `llvm.debugtrap` intrinsic. Does
| that DTRT?
| rep_lodsb wrote:
| The "canonical" INT 3 is a single byte opcode (CCh), so the
| debugger can just subtract 1 from the address pushed on the
| stack to get the breakpoint location.
|
| There is another encoding (CD 03), but no assembler should
| emit it. It used to be possible for adversarial code to
| confuse debug interrupt handlers with this, but this should
| be fixed now.
| amluto wrote:
| This would involve the debugger actually being structured
| in a way that makes this make sense. A debugger like GCC
| has a gnarly data structure that represents the machine
| state, and it contains things like EIP/RIP. There is a
| command 'backtrace' that takes the machine state and
| attempts to generate a backtrace. And there's a command
| 'continue' that resumes execution.
|
| int3 is a "trap". continue will resume execution at the
| instruction after int3, as intended. But backtrace should,
| by some ill-defined magic, generate the backtrace as though
| RIP was (saved RIP - 1). And the condition for doing this
| isn't something that is (AFAIK) representable at all in
| GCC's worldview. Sure, GCC knows, or at least ought to know
| [0], that it gained control because of vector 3, and the
| Intel and AMD manuals say that vector 3 is a trap. But
| there isn't a bit in memory or anything you would see in
| 'info regs' that will say "hey, this is a 'trap', and
| backtraces and such should be done as though RIP was
| actually RIP-1".
|
| Maybe the right solution would be to split the program
| counter, from the perspective of the debugger, into two
| fields: program counter for backtracing, and program
| counter for resumption.
|
| And yes, I know that GCC gets this wrong. Been there, seen
| the failures. I have not checked, but I expect that LLDB
| works exactly like GCC in this regard.
|
| [0] ptrace on Linux exposes the vector number, somewhat
| awkwardly. Or you can infer it from the fact that the
| signal was SIGTRAP.
| estebank wrote:
| Having a feature like this will significantly increase the
| demand of better incremental compilation, potentially with the
| need for patching specific items on existing binaries for
| speed. At that point you could get very close to an IDE
| debugging experience/speed with only rustc, a text editor and a
| debugger. (Inserting a bunch of NOPs on every function and
| supporting patching of JMPs in their place would likely go a
| long way for this.)
| thramp wrote:
| Oh, that's super clever integration with tracing. Feel free to
| send us a PR; we'll link to this as a related project in the
| docs!
| BrainBacon wrote:
| Thanks! I'll get a PR up shortly!
| BrainBacon wrote:
| PR opened: https://github.com/tokio-rs/tracing/pull/3147
| xobs wrote:
| I find myself using debug_here
| (https://github.com/ethanpailes/debug-here) which does similar
| things but for desktop-class debugging. It hasn't been updated in
| a while, but it still works for me on Windows at least.
| dboreham wrote:
| We used to divide by zero but then someone decided that was ok.
| merksoftworks wrote:
| Rusts current pretty printers in lldb and gdb are just not good
| enough for a fluid step debugging experience. I've had luck with
| intellij IDE's but it's very sad that the best we can do in a
| language with such good devex tooling is print debugging.
|
| Theoretically you could generate debug scripts with a macro and
| embed them with
| #![debugger_visualizer(gdb_script_file = "../foo.py")]
|
| but I haven't seen anyone go through the trouble.
| landr0id wrote:
| The pretty printers seem to break from time to time as well
| with compiler updates:
| https://www.reddit.com/r/rust/comments/1f28akn/invalid_value...
| ewuhic wrote:
| Is there a good newby tutorial on how to use debugger with Rust
| (and debugger in general?) No videos please.
| nathanwh wrote:
| Neat project! Maybe this decision is copied over from unreal
| engine, but instead of `ensure` and `ensure_always`, having names
| like `ensure_once` and `ensure` would have been more clear to me.
___________________________________________________________________
(page generated 2024-11-20 23:00 UTC)