rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
94.91k stars 12.24k forks source link

Avoid volatile loads to preserve the gdb pretty printer section #44993

Open alexcrichton opened 6 years ago

alexcrichton commented 6 years ago

Right now when you compile a program with debuginfo on Linux we'll emit a volatile load of a gdb pretty printer section which is intended on ensuring that the linker forces a section in the executable.

Apparently, though, this has caused some problems for embedded work (cc @japaric) where the section doesn't always make it to the final image that's flashed to devices, meaning that this stray load near the beginning of the program can sometimes cause problems.

We should look into other solutions to force the linker to keep this symbol I think. Right now we're passing a version script on Linux to preserve symbols in cdylibs and I think the same would work for this? Worth trying out!

cc @michaelwoerister

alexcrichton commented 6 years ago

This comment has some more informaton on this. Apparently we should also make sure that this isn't an allocated section in the final executable, no need to have this actually be resident in memory!

michaelwoerister commented 6 years ago

Yes, I'd love to get rid of this hack.

japaric commented 6 years ago

This comment has some more informaton on this

This approach (read: hack) doesn't work with LLD 6.0, the LLD version that's shipped with the Rust toolchain. This means that if we want to default to LLD as the ARM Cortex-M linker (good because the user won't have to install arm-none-eabi-binutils, or worse arm-none-eabi-gcc, to link Rust programs) we'll have a regression in binary size (bad) because .debug_gdb_scripts will be allocated in the final binary.

@michaelwoerister @tromey is there any chance we could (eventually) get rid of .debug_gdb_scripts and rust-gdb altogether? GDB 7.12+ has official support for Rust and can pretty print Rust stuff so I'm not even sure what rust-gdb buys you at this point. The standard in Cortex-M land is to use vanilla arm-none-eabi-gdb so we'd rather not have to pay for / deal with this .gdb_debug_script hack which we don't even use!

tromey commented 6 years ago

GDB 7.12+ has official support for Rust and can pretty print Rust stuff so I'm not even sure what rust-gdb buys you at this point

It has printers for things from the standard library -- which is something gdb itself should not really know about; and it arranges for these printers to be installed (gdb by default won't load random python code, something has to set the "auto load safe path").

However, I don't think the hook code necessarily has to be in .debug_gdb_scripts. Another idea would be to have rust-gdb only handle the auto-load safe path, and have cargo create the needed scripts in the build tree. A nice property of this approach is that then other Rust crates could also supply their own gdb pretty-printers. A drawback would be that this would only work out-of-the-box when debugging in a build tree, not when debugging some installed executable.

alexcrichton commented 6 years ago

One option which may be the easiest to take in the meantime is to make generation of this section a boolean in custom target specs. That way presumably the embedded targets could all disable it (and it'd be left on for Linux and such).

Although if someone gets to @tromey's solution first then that'd obviate the need for this route of course!

japaric commented 6 years ago

It has printers for things from the standard library

That must be why I never noticed anything amiss -- ARM Cortex-M doesn't have access to the standard library. One always uses core and (very) ocassionally the alloc crate for stuff like Vec.

A nice property of this approach is that then other Rust crates could also supply their own gdb pretty-printers.

off-topic: I'd love to see GDB use the fmt::Debug implementations of the Rust code though I don't know what kind of black magic would be required for that. Having to write a pretty printer in Python for every one of my data structures doesn't sound scalable.

tromey commented 6 years ago

I'd love to see GDB use the fmt::Debug implementations of the Rust code though I don't know what kind of black magic would be required for that.

Normally I discourage this kind of thing, because pretty-printers are invoked by bt, and making inferior calls (which messi with the stack) while also unwinding can cause problems. Also, it doesn't work with core-file debugging (though not everybody does that).

One wacky option would be to translate the fmt::Debug implementations to Python. But that's also tricky.

michaelwoerister commented 6 years ago

One option which may be the easiest to take in the meantime is to make generation of this section a boolean in custom target specs.

That would be a quick short-term fix to avoid problems with certain targets.

whitequark commented 6 years ago

Normally I discourage this kind of thing, because pretty-printers are invoked by bt, and making inferior calls (which messi with the stack) while also unwinding can cause problems. Also, it doesn't work with core-file debugging (though not everybody does that).

One wacky option would be to translate the fmt::Debug implementations to Python. But that's also tricky.

Wild idea: can we make gdb somehow interpret the Rust code in fmt::Debug implementations without running it on the inferior but while providing it access to the inferior address space? Miri, anyone?

jonas-schievink commented 4 years ago

Wild idea: can we make gdb somehow interpret the Rust code in fmt::Debug implementations without running it on the inferior but while providing it access to the inferior address space? Miri, anyone?

Related: https://github.com/rust-lang/rust/issues/65564 (proposes running code on the inferior to obtain a debugger view)

wesleywiser commented 1 year ago

Visted during wg-debugging triage. At this time, a target option is available to completely disable the inclusion of gdb pretty printers in the executable. That seems to mitigate the original issue but it would still be good to solve this in a more elegant way. #[used] has a much more robust implementation now and marking the pretty printer with the equivalent LLVM attributes may be sufficient to avoid the load.