-
Notifications
You must be signed in to change notification settings - Fork 214
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
Add CFI information to __rust_probestack #305
Conversation
I've done some work to test this with a patched |
a7e6876
to
e67619c
Compare
In order for GDB to correctly backtrace a stack overflow, it needs CFI information in __rust_probestack. This turns the following backtrace, ``` >> bt #0 0x0000555555576f73 in __rust_probestack () at /cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.14/src/probestack.rs:55 Backtrace stopped: Cannot access memory at address 0x7fffff7fedf0 ``` To this: ``` >>> bt #0 0x0000555555574e47 in __rust_probestack () rust-lang#1 0x00005555555595ba in test::main () rust-lang#2 0x00005555555594f3 in std::rt::lang_start::{{closure}} () rust-lang#3 0x0000555555561ae3 in std::panicking::try::do_call () rust-lang#4 0x000055555556595a in __rust_maybe_catch_panic () rust-lang#5 0x000055555555af9b in std::rt::lang_start_internal () rust-lang#6 0x00005555555594d5 in std::rt::lang_start () rust-lang#7 0x000055555555977b in main () ```
movq %rsp, %rbp | ||
.cfi_def_cfa_register 6 | ||
mov %rax,%r11 | ||
// duplicate %rax as we're clobbering %r11 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this comment one line up. In is about the mov
above.
@@ -28,6 +28,22 @@ fn main() { | |||
println!("cargo:rustc-cfg=feature=\"mem\""); | |||
} | |||
|
|||
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); | |||
if target_os != "windows" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's probably fine to just check the target
local variable like the rest of this function
if target_os != "windows" { | ||
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); | ||
if target_arch == "x86_64" { | ||
let cfg = &mut cc::Build::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This compilation will want to be in the c
module as well, and if possible it'd be great to use the same compilation support that all the other C intrinsics use below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, it makes sense to refactor that way.
#[naked] | ||
#[no_mangle] | ||
#[cfg(all(target_arch = "x86_64", not(feature = "mangled-names")))] | ||
pub unsafe extern "C" fn __rust_probestack() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we'll want to delete these because a C compiler isn't always available and we'll still want definitions of these functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, we wouldn't really need C because we are compiling assembly files. Passing '.S' files to a C compiler is just wrapping around an assembler. Can we rely solely on our bundled-in LLVM for it somehow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah unfortunately we don't ship an assembler that uses LLVM, so we're left basically looking for cc
. You're right that we otherwise just need as
, but that's not actually that much easier to acquire than a C compiler most of the time.
.globl __rust_probestack | ||
.type __rust_probestack, @function | ||
__rust_probestack: | ||
.cfi_startproc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To confirm, are we certain that this can't be done with LLVM's inline assembly? For example does updating ebp/rbp work for gdb/backtraces? Does LLVM inline assembly not support the .cfi_*
directives?
(in general it'll just be easier if we can stick to inline assembly I think)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried adding the CFI directives both in the original inline assembly, also via global_asm!
, and both cases they did not result in a binary containing the directives, as observed via dwarfdump
. Only a separate compilation worked. I haven't tested yet whether gdb
picks on the ebp
/rbp
usage without the directives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gdb is very picky about what kind of prelude it accepts. Even placing a rex
prefix before the push
breaks it: https://github.com/bjorn3/rustc_codegen_cranelift/issues/146#issuecomment-449474527. Because of this, I wouldnt be suprised if using a different register as base pointer would confuse gdb.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can use the standard base register prelude here, and if that works I think we probably want to stick with that since we should be able to continue using inline assembly.
@da-x want to test on your end with the base pointer management added but still using inline assembly and seeing if it works?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works as expected. Please consider #306 and close this PR.
Indeed I'm gonna close this in favor of #306, thanks for investigating! |
☔ The latest upstream changes (presumably #306) made this pull request unmergeable. Please resolve the merge conflicts. |
In order for GDB and other stack unwinders to correctly backtrace a stack overflow, it needs CFI information in __rust_probestack.
This turns the following backtrace,
Into this:
Fixes #304.