[compiler-rt] r277874 - Fix two tests in Win64 ASan

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 8 12:51:43 PDT 2016


On Mon, Aug 8, 2016 at 10:37 AM, Reid Kleckner <rnk at google.com> wrote:

> On Fri, Aug 5, 2016 at 6:53 PM, David Majnemer <david.majnemer at gmail.com>
> wrote:
>
>> On Fri, Aug 5, 2016 at 2:47 PM, Reid Kleckner via llvm-commits <
>> llvm-commits at lists.llvm.org> wrote:
>>
>>> Author: rnk
>>> Date: Fri Aug  5 16:47:46 2016
>>> New Revision: 277874
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=277874&view=rev
>>> Log:
>>> Fix two tests in Win64 ASan
>>>
>>> Go back to intercepting kernel32!RaiseException, and only go for
>>> ntdll!RtlRaiseException if that fails. Fixes throw_and_catch.cc test.
>>>
>>> Work around an issue in LLVM's win64 epilogues. We end up with an
>>> epilogue that looks like this, and it drives the Win64 unwinder crazy
>>> until stack overflow:
>>>         call    ill_cc!__asan_handle_no_return
>>>         xor     eax,eax
>>>         add     rsp,40h // epilogue starts
>>
>>         pop     rbp     // CSR
>>>         ud2             // Trap here
>>>         ret             // Ret?
>>>         nop     word ptr [rax+rax]
>>>         sub     rsp,28h // Next function
>>>
>>
>>
>> Interesting.  So we started the epilogue but didn't finish it.  Happen to
>> have some IR or C lying around?  I'm curious exactly when we decided that a
>> ud2 between the pop and the ret was a smart move...
>>
>
> It's pretty easy to convince LLVM to put the ud2 there, but it's hard to
> build a test case that will cause the Win64 unwinder to fail in the same
> way that I observed in this test without the extra conditional control flow
> that I added.
>
> $ cat t.cpp
> void foo();
> int main() { foo(); __builtin_trap(); }
>
> $ clang -S --target=x86_64-windows t.cpp  -fno-omit-frame-pointer -o -
> ...
>         callq   "?foo@@YAXXZ"
>         xorl    %eax, %eax
>         addq    $32, %rsp
>         popq    %rbp
>         ud2
>         retq
> ...
>
> I think the issue is that the faulting PC does not appear to be within a
> standard epilogue, so the unwinder re-emulates the add 32 and pop rbp.
>

Hrm, the CoreCLR copy of the x64 unwinder *should* handle this case:
https://github.com/dotnet/coreclr/blob/master/src/unwinder/amd64/unwinder_amd64.cpp#L1304

Our retq is encoded as 0xc3 which is their RET_OP.

Using the same IR but forcing us out of FastISel leaves us with:
callq "?foo@@YAXXZ"
ud2
xorl %eax, %eax
addq $32, %rsp
popq %rbp
retq

The difference is caused by a different selection of terminator in
emitEpligoue (FastISel uses the TRAP while SDAG uses the RETQ).

>From reading the x64 ABI docs, I cannot find where we strongly violated a
constraint.  My only guess is that it doesn't like us partially unwinding a
frame function before performing the trap (something along the lines of the
unwinder _expecting_ to see an SP adjustment but seeing nothing but the
ret...).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160808/b9b8b229/attachment.html>


More information about the llvm-commits mailing list