[llvm-dev] X86 llvm.frameaddress/returnaddress
Todd Mortimer via llvm-dev
llvm-dev at lists.llvm.org
Fri Nov 17 07:44:33 PST 2017
Hello,
The llvm.frameaddress and llvm.returnaddress intrinsics seem broken on
64 bit X86 with -fomit-frame-pointer when given an argument greater than
zero.
We recently found on OpenBSD that code calling __builtin_return_address
and __builtin_frame_address with arguments greater than zero can
segfault if RBP has been allocated as a general purpose register
somewhere up the stack. Specifically, we found that chromium calls
backtrace(), and the library we were using to implement that function
was just using __builtin_return_address and __builtin_frame_address to
walk the stack backwards. The compiled code ended up something like
this:
5bf: 48 8b 4d 00 mov 0x0(%rbp),%rcx
5c3: 48 8b 09 mov (%rcx),%rcx
5c6: 48 8b 09 mov (%rcx),%rcx
5c9: 48 8b 09 mov (%rcx),%rcx
5cc: 48 83 39 00 cmpq $0x0,(%rcx)
This works fine when %rbp is always holding a frame pointer, but is
unpredictable when it does not. In our case, C++ code in Chromium had
used %rbp for data, so segfaulted when dereferencing.
I see in the implementation of X86TargetLowering::LowerFRAMEADDR that
there is some special handling when MF.getTarget().getMCAsmInfo()->usesWindowsCFI()
is true, and it is commented to the effect that depth > 0 makes no sense
when unwind info is needed. Should the same logic be applied when given
-fomit-frame-pointer, or just in general on 64 bit X86 where unwind
tables are required anyway? I realize that the documentation for the
llvm.frameaddress and llvm.returnaddress intrinsics are explicit that
the return value may be wrong when the argument is > 0, but in cases
where we know it will be unreliable / unstable, it might be useful to
limit the output to something that doesn't possibly cause runtime
failures?
Todd
More information about the llvm-dev
mailing list