1247975Scognet/* 2247975Scognet * Copyright 1997 Sean Eric Fagan 3247975Scognet * 4247975Scognet * Redistribution and use in source and binary forms, with or without 5247975Scognet * modification, are permitted provided that the following conditions 6247975Scognet * are met: 7247975Scognet * 1. Redistributions of source code must retain the above copyright 8247975Scognet * notice, this list of conditions and the following disclaimer. 9247975Scognet * 2. Redistributions in binary form must reproduce the above copyright 10247975Scognet * notice, this list of conditions and the following disclaimer in the 11247975Scognet * documentation and/or other materials provided with the distribution. 12247975Scognet * 3. All advertising materials mentioning features or use of this software 13247975Scognet * must display the following acknowledgement: 14247975Scognet * This product includes software developed by Sean Eric Fagan 15247975Scognet * 4. Neither the name of the author may be used to endorse or promote 16247975Scognet * products derived from this software without specific prior written 17247975Scognet * permission. 18247975Scognet * 19247975Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20247975Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21247975Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22247975Scognet * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23247975Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24247975Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25247975Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26247975Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27247975Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28247975Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29247975Scognet * SUCH DAMAGE. 30247975Scognet */ 31247975Scognet 32247975Scognet#include <sys/cdefs.h> 33247975Scognet__FBSDID("$FreeBSD$"); 34290052Sjhb 35290052Sjhb/* FreeBSD/arm-specific system call handling. */ 36290052Sjhb 37247975Scognet#include <sys/ptrace.h> 38247975Scognet#include <sys/syscall.h> 39247975Scognet 40247975Scognet#include <machine/reg.h> 41247975Scognet#include <machine/armreg.h> 42247975Scognet#include <machine/ucontext.h> 43247975Scognet 44247975Scognet#include <stdio.h> 45247975Scognet 46247975Scognet#include "truss.h" 47247975Scognet 48247975Scognet#include "syscalls.h" 49247975Scognet 50290052Sjhbstatic int 51290052Sjhbarm_fetch_args(struct trussinfo *trussinfo, u_int narg) 52247975Scognet{ 53247975Scognet struct ptrace_io_desc iorequest; 54247975Scognet struct reg regs; 55290052Sjhb struct current_syscall *cs; 56247975Scognet lwpid_t tid; 57290052Sjhb u_int i, reg, syscall_num; 58247975Scognet 59247975Scognet tid = trussinfo->curthread->tid; 60290052Sjhb cs = &trussinfo->curthread->cs; 61247975Scognet if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { 62247975Scognet fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 63290052Sjhb return (-1); 64247975Scognet } 65247975Scognet 66247975Scognet /* 67290052Sjhb * FreeBSD has two special kinds of system call redirections -- 68247975Scognet * SYS_syscall, and SYS___syscall. The former is the old syscall() 69247975Scognet * routine, basically; the latter is for quad-aligned arguments. 70290052Sjhb * 71290052Sjhb * The system call argument count and code from ptrace() already 72290052Sjhb * account for these, but we need to skip over the first argument. 73247975Scognet */ 74247975Scognet#ifdef __ARM_EABI__ 75247975Scognet syscall_num = regs.r[7]; 76247975Scognet#else 77290052Sjhb if ((syscall_num = ptrace(PT_READ_I, tid, 78247975Scognet (caddr_t)(regs.r[_REG_PC] - INSN_SIZE), 0)) == -1) { 79247975Scognet fprintf(trussinfo->outfile, "-- CANNOT READ PC --\n"); 80290052Sjhb return (-1); 81247975Scognet } 82247975Scognet syscall_num = syscall_num & 0x000fffff; 83247975Scognet#endif 84290052Sjhb 85290052Sjhb reg = 0; 86247975Scognet switch (syscall_num) { 87247975Scognet case SYS_syscall: 88290052Sjhb reg = 1; 89247975Scognet break; 90247975Scognet case SYS___syscall: 91290052Sjhb reg = 2; 92247975Scognet break; 93247975Scognet } 94247975Scognet 95290052Sjhb for (i = 0; i < narg && reg < 4; i++, reg++) 96290052Sjhb cs->args[i] = regs.r[reg]; 97290052Sjhb if (narg > i) { 98247975Scognet iorequest.piod_op = PIOD_READ_D; 99290052Sjhb iorequest.piod_offs = (void *)(regs.r_sp + 100247975Scognet 4 * sizeof(uint32_t)); 101290052Sjhb iorequest.piod_addr = &cs->args[i]; 102290052Sjhb iorequest.piod_len = (narg - i) * sizeof(cs->args[0]); 103247975Scognet ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); 104247975Scognet if (iorequest.piod_len == 0) 105290052Sjhb return (-1); 106247975Scognet } 107247975Scognet 108290052Sjhb return (0); 109247975Scognet} 110247975Scognet 111290052Sjhbstatic int 112290052Sjhbarm_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) 113247975Scognet{ 114247975Scognet struct reg regs; 115247975Scognet lwpid_t tid; 116247975Scognet 117247975Scognet tid = trussinfo->curthread->tid; 118247975Scognet if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { 119247975Scognet fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 120247975Scognet return (-1); 121247975Scognet } 122247975Scognet 123290052Sjhb /* XXX: Does not have the __ARMEB__ handling for __syscall(). */ 124290052Sjhb retval[0] = regs.r[0]; 125290052Sjhb retval[1] = regs.r[1]; 126290052Sjhb *errorp = !!(regs.r_cpsr & PSR_C); 127290052Sjhb return (0); 128290052Sjhb} 129247975Scognet 130290052Sjhbstatic struct procabi arm_fbsd = { 131290052Sjhb "FreeBSD ELF32", 132290052Sjhb syscallnames, 133290052Sjhb nitems(syscallnames), 134290052Sjhb arm_fetch_args, 135290052Sjhb arm_fetch_retval 136290052Sjhb}; 137247975Scognet 138290052SjhbPROCABI(arm_fbsd); 139