Closed
Description
The compiler flag -C force-frame-pointers=yes
isn't always honored, clobbering the %rbp
register and resulting in the unrecoverable stackframe for perf --call-graph fp
.
It seems that if I compile rustc
under -C force-frame-pointers=yes
, it works as shown below:
setup
$ cargo new clobbered-frame-pointer && cd clobbered-frame-pointer
pre-built stock binary rustc
$ rm -rf target/ && RUSTFLAGS="-C force-frame-pointers=yes" cargo build --release && objdump -C -d target/release/clobbered-frame-pointer | grep -A50 'std::sys::unix::futex::futex_wait>:'
Compiling clobbered-frame-pointer v0.1.0 (/home/sol/clobbered-frame-pointer)
Finished release [optimized] target(s) in 0.33s
000000000001fe60 <std::sys::unix::futex::futex_wait>:
1fe60: 55 push %rbp
1fe61: 41 57 push %r15
1fe63: 41 56 push %r14
1fe65: 41 55 push %r13
1fe67: 41 54 push %r12
1fe69: 53 push %rbx
1fe6a: 48 83 ec 28 sub $0x28,%rsp
1fe6e: 41 89 f6 mov %esi,%r14d
1fe71: 48 89 fb mov %rdi,%rbx
1fe74: 48 83 3a 00 cmpq $0x0,(%rdx)
1fe78: 74 4d je 1fec7 <std::sys::unix::futex::futex_wait+0x67>
1fe7a: 48 8b 6a 08 mov 0x8(%rdx),%rbp
1fe7e: 44 8b 7a 10 mov 0x10(%rdx),%r15d
1fe82: 48 8d 74 24 10 lea 0x10(%rsp),%rsi
1fe87: bf 01 00 00 00 mov $0x1,%edi
1fe8c: ff 15 a6 cb 02 00 callq *0x2cba6(%rip) # 4ca38 <clock_gettime@GLIBC_2.17>
1fe92: 83 f8 ff cmp $0xffffffff,%eax
1fe95: 0f 84 c1 00 00 00 je 1ff5c <std::sys::unix::futex::futex_wait+0xfc>
1fe9b: 48 8b 44 24 10 mov 0x10(%rsp),%rax
1fea0: 48 01 e8 add %rbp,%rax
1fea3: 0f 90 c2 seto %dl
1fea6: 31 c9 xor %ecx,%ecx
1fea8: 48 85 ed test %rbp,%rbp
1feab: 78 37 js 1fee4 <std::sys::unix::futex::futex_wait+0x84>
1fead: 84 d2 test %dl,%dl
1feaf: 75 33 jne 1fee4 <std::sys::unix::futex::futex_wait+0x84>
1feb1: 48 8b 4c 24 18 mov 0x18(%rsp),%rcx
1feb6: 41 01 cf add %ecx,%r15d
1feb9: 41 81 ff 00 ca 9a 3b cmp $0x3b9aca00,%r15d
1fec0: 72 10 jb 1fed2 <std::sys::unix::futex::futex_wait+0x72>
1fec2: 48 ff c0 inc %rax
1fec5: 71 04 jno 1fecb <std::sys::unix::futex::futex_wait+0x6b>
1fec7: 31 c9 xor %ecx,%ecx
1fec9: eb 19 jmp 1fee4 <std::sys::unix::futex::futex_wait+0x84>
1fecb: 41 81 c7 00 36 65 c4 add $0xc4653600,%r15d
1fed2: 44 89 f9 mov %r15d,%ecx
1fed5: 48 89 44 24 18 mov %rax,0x18(%rsp)
1feda: 48 89 4c 24 20 mov %rcx,0x20(%rsp)
1fedf: b9 01 00 00 00 mov $0x1,%ecx
1fee4: 48 89 4c 24 10 mov %rcx,0x10(%rsp)
1fee9: 4c 8d 7c 24 18 lea 0x18(%rsp),%r15
1feee: 4c 8b 25 a3 cd 02 00 mov 0x2cda3(%rip),%r12 # 4cc98 <syscall@GLIBC_2.2.5>
1fef5: 4c 8b 2d ac ca 02 00 mov 0x2caac(%rip),%r13 # 4c9a8 <__errno_location@GLIBC_2.2.5>
1fefc: 0f 1f 40 00 nopl 0x0(%rax)
1ff00: 8b 03 mov (%rbx),%eax
1ff02: 40 b5 01 mov $0x1,%bpl # !!!! %RBP IS CLOBBERED
1ff05: 44 39 f0 cmp %r14d,%eax
1ff08: 75 41 jne 1ff4b <std::sys::unix::futex::futex_wait+0xeb>
1ff0a: 4c 8b 44 24 10 mov 0x10(%rsp),%r8
1ff0f: 4d 85 c0 test %r8,%r8
re-built rustc
under -C force-frame-pointer=rustc
rm -rf target/ && RUSTFLAGS="-C force-frame-pointers=yes" cargo +kustom-for-frame-pointer build --release && objdump -C -d target/release/clobbered-frame-pointer | grep -A50 'std::sys::unix::futex::futex_wait>:'
Compiling clobbered-frame-pointer v0.1.0 (/home/sol/clobbered-frame-pointer)
Finished release [optimized] target(s) in 0.16s
000000000001e480 <std::sys::unix::futex::futex_wait>:
1e480: 55 push %rbp
1e481: 48 89 e5 mov %rsp,%rbp
1e484: 41 57 push %r15
1e486: 41 56 push %r14
1e488: 41 55 push %r13
1e48a: 41 54 push %r12
1e48c: 53 push %rbx
1e48d: 48 83 ec 28 sub $0x28,%rsp
1e491: 48 83 3a 00 cmpq $0x0,(%rdx)
1e495: 41 89 f6 mov %esi,%r14d
1e498: 49 89 ff mov %rdi,%r15
1e49b: 74 48 je 1e4e5 <std::sys::unix::futex::futex_wait+0x65>
1e49d: 44 8b 62 10 mov 0x10(%rdx),%r12d
1e4a1: 48 8b 5a 08 mov 0x8(%rdx),%rbx
1e4a5: 48 8d 75 c0 lea -0x40(%rbp),%rsi
1e4a9: bf 01 00 00 00 mov $0x1,%edi
1e4ae: ff 15 b4 25 03 00 callq *0x325b4(%rip) # 50a68 <clock_gettime@GLIBC_2.17>
1e4b4: 83 f8 ff cmp $0xffffffff,%eax
1e4b7: 0f 84 c2 00 00 00 je 1e57f <std::sys::unix::futex::futex_wait+0xff>
1e4bd: 48 8b 45 c0 mov -0x40(%rbp),%rax
1e4c1: 48 01 d8 add %rbx,%rax
1e4c4: 0f 90 c1 seto %cl
1e4c7: 48 85 db test %rbx,%rbx
1e4ca: 78 19 js 1e4e5 <std::sys::unix::futex::futex_wait+0x65>
1e4cc: 84 c9 test %cl,%cl
1e4ce: 75 15 jne 1e4e5 <std::sys::unix::futex::futex_wait+0x65>
1e4d0: 48 8b 4d c8 mov -0x38(%rbp),%rcx
1e4d4: 41 01 cc add %ecx,%r12d
1e4d7: 41 81 fc 00 ca 9a 3b cmp $0x3b9aca00,%r12d
1e4de: 72 16 jb 1e4f6 <std::sys::unix::futex::futex_wait+0x76>
1e4e0: 48 ff c0 inc %rax
1e4e3: 71 0a jno 1e4ef <std::sys::unix::futex::futex_wait+0x6f>
1e4e5: 48 c7 45 c0 00 00 00 movq $0x0,-0x40(%rbp)
1e4ec: 00
1e4ed: eb 1a jmp 1e509 <std::sys::unix::futex::futex_wait+0x89>
1e4ef: 41 81 c4 00 36 65 c4 add $0xc4653600,%r12d
1e4f6: 44 89 e1 mov %r12d,%ecx
1e4f9: 48 89 45 c8 mov %rax,-0x38(%rbp)
1e4fd: 48 89 4d d0 mov %rcx,-0x30(%rbp)
1e501: 48 c7 45 c0 01 00 00 movq $0x1,-0x40(%rbp)
1e508: 00
1e509: 4c 8b 2d 70 27 03 00 mov 0x32770(%rip),%r13 # 50c80 <syscall@GLIBC_2.2.5>
1e510: 4c 8b 25 e9 28 03 00 mov 0x328e9(%rip),%r12 # 50e00 <__errno_location@GLIBC_2.2.5>
1e517: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
1e51e: 00 00
1e520: 41 8b 07 mov (%r15),%eax
1e523: b3 01 mov $0x1,%bl # OKAY!
1e525: 44 39 f0 cmp %r14d,%eax
1e528: 75 44 jne 1e56e <std::sys::unix::futex::futex_wait+0xee>
1e52a: 4c 8b 45 c0 mov -0x40(%rbp),%r8
I picked std::sys::unix::futex::futex_wait
for the above example. But it seems that there's many:
$ rm -rf target/ && RUSTFLAGS="-C force-frame-pointers=yes" cargo build --release && objdump -C -d target/release/clobbered-frame-pointer | grep -E '>:$|\$0x1,%bpl' | grep -B1 bpl | head -n 50
Compiling clobbered-frame-pointer v0.1.0 (/home/sol/clobbered-frame-pointer)
Finished release [optimized] target(s) in 0.33s
000000000000f7a0 <addr2line::ResUnit<R>::parse_lines>:
11d14: 40 b5 01 mov $0x1,%bpl
11d47: 40 b5 01 mov $0x1,%bpl
11d5c: 40 b5 01 mov $0x1,%bpl
11d6c: 40 b5 01 mov $0x1,%bpl
11d7e: 40 b5 01 mov $0x1,%bpl
--
00000000000121e0 <addr2line::ResDwarf<R>::parse>:
1469d: 40 b5 01 mov $0x1,%bpl
16e6b: 40 b5 01 mov $0x1,%bpl
16e7d: 40 b5 01 mov $0x1,%bpl
--
000000000001dcc0 <std::panicking::default_hook>:
1dfc6: 40 80 f5 01 xor $0x1,%bpl
1e064: 40 b5 01 mov $0x1,%bpl
1e076: 40 b5 01 mov $0x1,%bpl
1e0a6: 40 b5 01 mov $0x1,%bpl
--
000000000001fe60 <std::sys::unix::futex::futex_wait>:
1ff02: 40 b5 01 mov $0x1,%bpl
--
0000000000020e30 <std::backtrace_rs::symbolize::gimli::Context::new>:
218a4: 40 b5 01 mov $0x1,%bpl
219a7: 40 b5 01 mov $0x1,%bpl
21d71: 40 b5 01 mov $0x1,%bpl
--
0000000000022020 <std::backtrace_rs::symbolize::gimli::resolve::{{closure}}>:
22d20: 40 80 fd 01 cmp $0x1,%bpl
240b1: 40 80 fd 01 cmp $0x1,%bpl
253bf: 40 b5 01 mov $0x1,%bpl
257fc: 40 f6 c5 01 test $0x1,%bpl
266ed: 40 b5 01 mov $0x1,%bpl
267d2: 40 b5 01 mov $0x1,%bpl
--
0000000000029a50 <gimli::read::abbrev::Abbreviations::insert>:
29b1b: 40 80 fd 01 cmp $0x1,%bpl
--
000000000002ce30 <<rustc_demangle::v0::Ident as core::fmt::Display>::fmt>:
2d243: 40 b5 01 mov $0x1,%bpl
2d2f3: 40 b5 01 mov $0x1,%bpl
--
000000000002da20 <rustc_demangle::v0::Printer::print_backref>:
2da99: 40 b5 01 mov $0x1,%bpl
000000000002dbe0 <rustc_demangle::v0::Printer::print_backref>:
2dc59: 40 b5 01 mov $0x1,%bpl
000000000002dda0 <rustc_demangle::v0::Printer::print_backref>:
2de19: 40 b5 01 mov $0x1,%bpl
--
000000000002f9d0 <rustc_demangle::v0::Printer::print_type::{{closure}}>:
2facd: 40 b5 01 mov $0x1,%bpl
I suspect this is caused by pre-built fn machine code is statically linked into the binary, skipping compilation and not considering RUSTFLAGS
.
$ rustc --version --verbose
rustc 1.64.0 (a55dd71d5 2022-09-19)
binary: rustc
commit-hash: a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52
commit-date: 2022-09-19
host: x86_64-unknown-linux-gnu
release: 1.64.0
LLVM version: 14.0.6