code icon indicating copy to clipboard operation
code copied to clipboard

ch12-sjlj Why the program not execute the line `println!("early return!");`, set_jmp and long_jmp didn`t work.

Open TQLeung opened this issue 2 years ago • 3 comments

TQLeung avatar Sep 19 '22 01:09 TQLeung

To provide a bit more context, at least as of 2023-01-14, Rust Nightly produces code that just crashes (Segementation Fault), instead of succeeding with the setjmp() / longjmp() trickery, in the ch12/ch12-sjlj example.

I'm not that surprised. Even in C setjmp() / longjmp() are wildly unsafe C library calls, that it's recomended never to use unless you have absolutely no other choice. And preferably you wouldn't be longjmp()ing from a signal handler back to other (non-signal handler) code, as is implemented here. FWIW, the idea of trying to setjmp()/longjmp() via a foreign function interface (ie, Rust to C) struck me as very unlikely to succeed; I guess there was maybe a rust compiler Nightly version/LLDB version where what was implemented happened to work, but it seems extremely fragile.

From a bit of debugging it is unsurprisingly crashing in the longjmp() call. And the fact that trying to read the franken_pointer value reports it couldn't read from address 0x18 strongly implies that's an offset from a NULL pointer. Presumably only the liberal use of unsafe here is preventing the compiler from saying "What? No, just no" to this :-)

(FTR, it looks like RETURN_HERE -- the jump buffer -- does have a valid address, and might even have plausible contents -- although there's a lot of 0 bytes in it.)

Ewen

ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ rustc +nightly --version
rustc 1.68.0-nightly (0b90256ad 2023-01-13)
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ cargo +nightly --version
cargo 1.68.0-nightly (d992ab4e9 2023-01-10)
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ cargo +nightly clean
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ cargo +nightly run
   Compiling libc v0.2.84
   Compiling ch10-sjlj v0.1.0 (/home/ewen/misc/src/rust/rust-in-action/ch12/ch12-sjlj)
    Finished dev [unoptimized + debuginfo] target(s) in 1.04s
     Running `target/debug/ch10-sjlj`

#
##
###
Segmentation fault (core dumped)
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ 
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ nl -ba src/main.rs | awk '$1 > 32 && $1 < 36 {print;}'
    33	  let franken_pointer = ptr_to_jmp_buf();
    34	  unsafe { longjmp(franken_pointer) };         // <5>
    35	}
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ 
Example core dump back trace
ewen@rustdev:~/misc/src/rust/rust-in-action/ch12/ch12-sjlj$ rust-lldb target/debug/ch10-sjlj -c $(ls -t /var/lib/apport/coredump/core.* | head -1)
(lldb) command script import "/home/ewen/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/etc/lldb_lookup.py"
(lldb) command source -s 0 '/home/ewen/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/etc/lldb_commands'
Executing commands in '/home/ewen/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/etc/lldb_commands'.
(lldb) type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?str$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup  -e -x -h "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
(lldb) type category enable Rust
(lldb) target create "target/debug/ch10-sjlj" --core "/var/lib/apport/coredump/core._home_ewen_misc_src_rust_rust-in-action_ch12_ch12-sjlj_target_debug_ch10-sjlj.1000.815c6d8a-8ee6-45a1-b111-d05f4b76a7db.30059.26038095"
Core file '/var/lib/apport/coredump/core._home_ewen_misc_src_rust_rust-in-action_ch12_ch12-sjlj_target_debug_ch10-sjlj.1000.815c6d8a-8ee6-45a1-b111-d05f4b76a7db.30059.26038095' (x86_64) was loaded.
(lldb) bt
* thread #1, name = 'ch10-sjlj', stop reason = signal SIGSEGV
  * frame #0: 0x00005582c7a92a81 ch10-sjlj`ch10_sjlj::return_early::h9f631bb2eb221bac at main.rs:34:12
(lldb) p franken_pointer
error: Couldn't materialize: couldn't get the value of variable franken_pointer: read memory from 0x18 failed (0 of 8 bytes read)
error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression
(lldb) print &RETURN_HERE
(char (*)[64]) $2 = 0x00005582c7ada032
(lldb) print sizeof(RETURN_HERE)
(unsigned long) $3 = 64
(lldb) print RETURN_HERE
(char[64]) $4 = "\0\0\0\0\0\0\0\0\x84-\xa9ǂU\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
(lldb) 

ewenmcneill avatar Jan 14 '23 02:01 ewenmcneill

Just remove attributes {#[link_name...]) of setjmp and longjmp signatures.

swkim01 avatar Apr 18 '23 07:04 swkim01