[compiler-rt] r277874 - Fix two tests in Win64 ASan
David Majnemer via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 8 14:51:08 PDT 2016
On Mon, Aug 8, 2016 at 2:46 PM, David Majnemer <david.majnemer at gmail.com>
wrote:
>
>
> On Mon, Aug 8, 2016 at 12:51 PM, David Majnemer <david.majnemer at gmail.com>
> wrote:
>
>>
>>
>> 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...).
>>
>
>
> After talking with Gor, the problem has been made more clear. We are in a
> frame function but we, not the unwinder, restored the FP. This would be OK
> if we were in an epilogue sequence but we are not because the faulting
> instruction is a ud2 which makes the unwinder believe that we are in the
> body of the function.
>
> All of this started because we lowered the __builtin_trap to a TRAP which
> is marked isTerminator. emitEpilogue believes that this is our return
> opcode because it is the first terminator in the MBB. The easiest way of
> fixing this, IMO, is to insert a NOP after the TRAP. This will stop it
> from looking like a terminator in the epilogue code...
>
On second thought, it would be even better to introduce another trap
instruction which is not a terminator. This way we can preserve the
invariant that terminators are grouped at the end of MBBs.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160808/b9801f3f/attachment.html>
More information about the llvm-commits
mailing list