| /* ********************************************************** |
| * Copyright (c) 2014-2016 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. |
| */ |
| |
| /* |
| * ARM-specific assembly and trampoline code, shared w/ non-core-DR-lib. |
| */ |
| |
| #include "../asm_defines.asm" |
| START_FILE |
| |
| #ifdef LINUX |
| #include "include/syscall.h" |
| #endif |
| |
| DECL_EXTERN(unexpected_return) |
| |
| /* we share dynamorio_syscall w/ preload */ |
| /* To avoid libc wrappers we roll our own syscall here. |
| * Hardcoded to use svc/swi for 32-bit -- FIXME: use something like do_syscall |
| * signature: dynamorio_syscall(sys_num, num_args, arg1, arg2, ...) |
| * For Linux, the argument max is 6. |
| */ |
| /* Linux system call on AArch32: |
| * - r7: syscall number |
| * - r0..r6: syscall arguments |
| * We need to not de-ref stack args that weren't passed so we can't ignore num_args. |
| */ |
| DECLARE_FUNC(dynamorio_syscall) |
| GLOBAL_LABEL(dynamorio_syscall:) |
| push {REG_R4-REG_R9} |
| /* Point r8 at the args on the stack */ |
| add REG_R8, sp, #(6*ARG_SZ) /* size for {r4-r9} */ |
| mov REG_R7, ARG1 /* sysnum */ |
| mov REG_R0, ARG3 /* syscall arg1 */ |
| mov REG_R9, ARG4 /* syscall arg2 */ |
| cmp ARG2, #2 |
| blt syscall_0_or_1arg |
| beq syscall_2args |
| cmp ARG2, #3 |
| beq syscall_3args |
| cmp ARG2, #4 |
| beq syscall_4args |
| cmp ARG2, #5 |
| beq syscall_5args |
| cmp ARG2, #6 |
| beq syscall_6args |
| syscall_7args: |
| ldr REG_R6, [REG_R8, #(4*ARG_SZ)] /* syscall arg7 */ |
| syscall_6args: |
| ldr REG_R5, [REG_R8, #(3*ARG_SZ)] /* syscall arg6 */ |
| syscall_5args: |
| ldr REG_R4, [REG_R8, #(2*ARG_SZ)] /* syscall arg5 */ |
| syscall_4args: |
| ldr REG_R3, [REG_R8, #(1*ARG_SZ)] /* syscall arg4 */ |
| syscall_3args: |
| ldr REG_R2, [REG_R8, #(0*ARG_SZ)] /* syscall arg3 */ |
| syscall_2args: |
| mov REG_R1, REG_R9 /* syscall arg2 */ |
| syscall_0_or_1arg: |
| /* arg1 is already in place */ |
| svc #0 |
| pop {REG_R4-REG_R9} |
| bx lr |
| |
| /* FIXME i#1551: just a shell to get things compiling. We need to fill |
| * in the real implementation. |
| */ |
| #define FUNCNAME dr_fpu_exception_init |
| DECLARE_FUNC(FUNCNAME) |
| GLOBAL_LABEL(FUNCNAME:) |
| bx lr |
| END_FUNC(FUNCNAME) |
| #undef FUNCNAME |
| |
| #ifdef LINUX |
| /* thread_id_t dynamorio_clone(uint flags, byte *newsp, void *ptid, void *tls, |
| * void *ctid, void (*func)(void)) |
| * TODO i#6514: Add support for passing NULL for newsp. |
| */ |
| DECLARE_FUNC(dynamorio_clone) |
| GLOBAL_LABEL(dynamorio_clone:) |
| /* Save callee-saved regs we clobber in the parent. */ |
| push {r4, r5, r7} |
| ldr r4, [sp, #12] /* ARG5 minus the pushes above */ |
| ldr r5, [sp, #16] /* ARG6 minus the pushes above */ |
| /* All args are now in syscall registers. */ |
| /* Push func on the new stack. */ |
| stmdb ARG2!, {r5} |
| mov r7, #SYS_clone |
| svc 0 |
| cmp r0, #0 |
| bne dynamorio_clone_parent |
| ldmia sp!, {r0} |
| blx r0 |
| bl GLOBAL_REF(unexpected_return) |
| dynamorio_clone_parent: |
| pop {r4, r5, r7} |
| bx lr |
| END_FUNC(dynamorio_clone) |
| #endif |
| |
| END_FILE |