<div dir="ltr">We can defensively warn in the frontend when we see __builtin_frame/return_address(n > 0) when we know frame pointers are absent, but in general, without knowledge of all the callers, these intrinsics can fault without warning. That's just a risk you have to be aware of when calling them, and I thought it was called out in documentation.</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 17, 2017 at 7:44 AM, Todd Mortimer via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello,<br>
<br>
The llvm.frameaddress and llvm.returnaddress intrinsics seem broken on<br>
64 bit X86 with -fomit-frame-pointer when given an argument greater than<br>
zero.<br>
<br>
We recently found on OpenBSD that code calling __builtin_return_address<br>
and __builtin_frame_address with arguments greater than zero can<br>
segfault if RBP has been allocated as a general purpose register<br>
somewhere up the stack. Specifically, we found that chromium calls<br>
backtrace(), and the library we were using to implement that function<br>
was just using __builtin_return_address and __builtin_frame_address to<br>
walk the stack backwards. The compiled code ended up something like<br>
this:<br>
<br>
     5bf:       48 8b 4d 00             mov    0x0(%rbp),%rcx<br>
     5c3:       48 8b 09                mov    (%rcx),%rcx<br>
     5c6:       48 8b 09                mov    (%rcx),%rcx<br>
     5c9:       48 8b 09                mov    (%rcx),%rcx<br>
     5cc:       48 83 39 00             cmpq   $0x0,(%rcx)<br>
<br>
This works fine when %rbp is always holding a frame pointer, but is<br>
unpredictable when it does not. In our case, C++ code in Chromium had<br>
used %rbp for data, so segfaulted when dereferencing.<br>
<br>
I see in the implementation of X86TargetLowering::<wbr>LowerFRAMEADDR that<br>
there is some special handling when MF.getTarget().getMCAsmInfo()-<wbr>>usesWindowsCFI()<br>
is true, and it is commented to the effect that depth > 0 makes no sense<br>
when unwind info is needed. Should the same logic be applied when given<br>
-fomit-frame-pointer, or just in general on 64 bit X86 where unwind<br>
tables are required anyway? I realize that the documentation for the<br>
llvm.frameaddress and llvm.returnaddress intrinsics are explicit that<br>
the return value may be wrong when the argument is > 0, but in cases<br>
where we know it will be unreliable / unstable, it might be useful to<br>
limit the output to something that doesn't possibly cause runtime<br>
failures?<br>
<br>
Todd<br>
<br>
<br>
______________________________<wbr>_________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-dev</a><br>
</blockquote></div><br></div>