/* **********************************************************
* Copyright (c) 2012-2020 Google, Inc. All rights reserved.
* ********************************************************** */
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Google, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
/***************************************************************************
* assembly utilities for which there are no intrinsics
*/
#include "cpp2asm_defines.h"
START_FILE
DECL_EXTERN(replace_native_xfer_stack_adjust)
DECL_EXTERN(replace_native_xfer_app_retaddr)
DECL_EXTERN(replace_native_xfer_target)
/* void replace_native_xfer(void)
*
* Replacement function returns here instead of to app.
* This routine is in assembly b/c it needs to jump to the client ibl
* xfer routine w/ the same stack value as when it entered.
*/
#define FUNCNAME replace_native_xfer
DECLARE_FUNC(FUNCNAME)
GLOBAL_LABEL(FUNCNAME:)
/* We must adjust the stack for stdcall (i#778), push the app retaddr,
* and finally jmp to client ibl xfer. However, we have to do all
* that w/o disturbing the return value from the replacement function.
* We thus only have xcx as a reg we can modify, and we have to preserve
* xax and xdx around every call. Our only simple OUT value is via
* the return address, so we make 3 separate calls.
* An alternative would be to look for our gencode bb and add meta
* instrs to do this, but we can't pass the retaddr there easily
* (ibl xfer clobbers scratch slots), and if we're going to put it
* on the stack here anyway, we may as well do the adjust here.
*
* XXX: what about xmm0 return reg?
*/
push 0 /* maintain 16-byte alignment for call */
push REG_XAX
push REG_XDX
CALLC0(GLOBAL_REF(replace_native_xfer_stack_adjust))
mov ecx, eax
pop REG_XDX
pop REG_XAX
lea REG_XSP, [ ARG_SZ + REG_XSP ]
/* DrMem i#1217: zero out these slots as they can contain retaddrs, which
* messes up high-performance callstack stack scans. This is beyond TOS,
* but these are writes so it's signal-safe.
*/
mov PTRSZ [-2 * ARG_SZ + REG_XSP], 0
mov PTRSZ [-1 * ARG_SZ + REG_XSP], 0
/* ok, now we have stack back to what it was. undo the stdcall stack adjust. */
sub REG_XSP, REG_XCX
/* make space for app retaddr */
push REG_XAX
push REG_XAX
push REG_XDX
/* We have to align the stack for our calls: o/w dyld lazy resolution
* crashes there. Current alignment could be anything so we save a ptr
* and mask off esp.
*/
push REG_XBX
mov REG_XBX, REG_XSP
and REG_XSP, -16 /* align to 16 */
/* put app retaddr into the slot we made above the 2 pushes */
CALLC0(GLOBAL_REF(replace_native_xfer_app_retaddr))
mov PTRSZ [3 * ARG_SZ + REG_XBX], REG_XAX
/* now get our target */
CALLC0(GLOBAL_REF(replace_native_xfer_target))
mov REG_XCX, REG_XAX
mov REG_XSP, REG_XBX
pop REG_XBX
pop REG_XDX
pop REG_XAX
/* DrMem i#1217: zero out these slots as they can contain retaddrs, which
* messes up high-performance callstack stack scans. This is beyond TOS,
* but these are writes so it's signal-safe.
*/
mov PTRSZ [-2 * ARG_SZ + REG_XSP], 0
mov PTRSZ [-1 * ARG_SZ + REG_XSP], 0
jmp REG_XCX
/* never reached */
ret
END_FUNC(FUNCNAME)
#undef FUNCNAME
/* i#778: We want the app code stream to have its stack operations all
* line up. The stdcall args + retaddr teardown executed natively (i#900),
* so we re-extend the stack in C code and then target a ret_imm instr
* from this series. We only support pointer-aligned. We do support
* for x64 although it's quite rare to need it there.
*/
DECLARE_GLOBAL(replace_native_ret_imms)
DECLARE_GLOBAL(replace_native_ret_imms_end)
#define FUNCNAME replace_native_rets
DECLARE_FUNC(FUNCNAME)
GLOBAL_LABEL(FUNCNAME:)
ret
ADDRTAKEN_LABEL(replace_native_ret_imms:)
ret 1 * ARG_SZ
ret 2 * ARG_SZ
ret 3 * ARG_SZ
ret 4 * ARG_SZ
ret 5 * ARG_SZ
ret 6 * ARG_SZ
ret 7 * ARG_SZ
ret 8 * ARG_SZ
ret 9 * ARG_SZ
ret 10 * ARG_SZ
ret 11 * ARG_SZ
ret 12 * ARG_SZ
ret 13 * ARG_SZ
ret 14 * ARG_SZ
ret 15 * ARG_SZ
ret 16 * ARG_SZ
ret 17 * ARG_SZ
ret 18 * ARG_SZ
ret 19 * ARG_SZ
ret 20 * ARG_SZ
ret 21 * ARG_SZ
ret 22 * ARG_SZ
ret 23 * ARG_SZ
ret 24 * ARG_SZ
ret 25 * ARG_SZ
ret 26 * ARG_SZ
ret 27 * ARG_SZ
ret 28 * ARG_SZ
ret 29 * ARG_SZ
ret 30 * ARG_SZ
ret 31 * ARG_SZ
ret 32 * ARG_SZ
ret 33 * ARG_SZ
ret 34 * ARG_SZ
ret 35 * ARG_SZ
ret 36 * ARG_SZ
ret 37 * ARG_SZ
ret 38 * ARG_SZ
ret 39 * ARG_SZ
ret 40 * ARG_SZ
ADDRTAKEN_LABEL(replace_native_ret_imms_end:)
nop
END_FUNC(FUNCNAME)
#undef FUNCNAME
/* We just need a sentinel block that does not cause DR to complain about
* non-executable code or illegal instrutions, for DRWRAP_REPLACE_RETADDR.
*/
#define FUNCNAME replace_retaddr_sentinel
DECLARE_FUNC(FUNCNAME)
GLOBAL_LABEL(FUNCNAME:)
ret
END_FUNC(FUNCNAME)
END_FILE