// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // ==++== // // // ==--== #include "unixasmmacros.inc" #include "asmconstants.h" .syntax unified .thumb // // WARNING!! These functions immediately ruin thread unwindability. This is // WARNING!! OK as long as there is a mechanism for saving the thread context // WARNING!! prior to running these functions as well as a mechanism for // WARNING!! restoring the context prior to any stackwalk. This means that // WARNING!! we need to ensure that no GC can occur while the stack is // WARNING!! unwalkable. This further means that we cannot allow any exception // WARNING!! to occur when the stack is unwalkable // // GSCookie + alignment padding OFFSET_OF_FRAME=(4 + SIZEOF__GSCookie) .macro GenerateRedirectedStubWithFrame STUB, TARGET // // This is the primary function to which execution will be redirected to. // NESTED_ENTRY \STUB, _TEXT, NoHandler // // IN: lr: original IP before redirect // PROLOG_PUSH "{r4,r7,lr}" alloc_stack OFFSET_OF_FRAME + SIZEOF__FaultingExceptionFrame // At this point, the stack maybe misaligned if the thread abort was asynchronously // triggered in the prolog or epilog of the managed method. For such a case, we must // align the stack before calling into the VM. // // Runtime check for 8-byte alignment. PROLOG_STACK_SAVE r7 // We lose stack unwindability here by configuring fp(r7) incorrectely // here. and r0, r7, #4 sub sp, sp, r0 // Save pointer to FEF for GetFrameFromRedirectedStubStackFrame add r4, sp, #OFFSET_OF_FRAME // Prepare to initialize to NULL mov r1,#0 str r1, [r4] // Initialize vtbl (it is not strictly necessary) str r1, [r4, #FaultingExceptionFrame__m_fFilterExecuted] // Initialize BOOL for personality routine mov r0, r4 // move the ptr to FEF in R0 // stack must be 8 byte aligned CHECK_STACK_ALIGNMENT bl C_FUNC(\TARGET) // Target should not return. EMIT_BREAKPOINT NESTED_END \STUB, _TEXT .endm // ------------------------------------------------------------------ // This helper enables us to call into a funclet after applying the non-volatiles NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler PROLOG_PUSH "{r4-r11, lr}" PROLOG_STACK_SAVE_OFFSET r7, #12 alloc_stack 4 // On entry: // // R0 = throwable // R1 = PC to invoke // R2 = address of R4 register in CONTEXT record// used to restore the non-volatile registers of CrawlFrame // R3 = address of the location where the SP of funclet's caller (i.e. this helper) should be saved. // // Save the SP of this function str sp, [r3] // apply the non-volatiles corresponding to the CrawlFrame ldm r2!, {r4-r6} add r2, r2, #4 ldm r2!, {r8-r11} // Invoke the funclet blx r1 free_stack 4 EPILOG_POP "{r4-r11, pc}" NESTED_END CallEHFunclet, _TEXT // This helper enables us to call into a filter funclet by passing it the CallerSP to lookup the // frame pointer for accessing the locals in the parent method. NESTED_ENTRY CallEHFilterFunclet, _TEXT, NoHandler PROLOG_PUSH "{r7, lr}" PROLOG_STACK_SAVE r7 // On entry: // // R0 = throwable // R1 = SP of the caller of the method/funclet containing the filter // R2 = PC to invoke // R3 = address of the location where the SP of funclet's caller (i.e. this helper) should be saved. // // Save the SP of this function str sp, [r3] // Invoke the filter funclet blx r2 EPILOG_POP "{r7, pc}" NESTED_END CallEHFilterFunclet, _TEXT