1154047Sgrehan/* 2154047Sgrehan * Copyright 2006 Peter Grehan <grehan@freebsd.org> 3204977Simp * Copyright 2005 Orlando Bassotto <orlando@break.net> 4204977Simp * Copyright 1998 Sean Eric Fagan 5154047Sgrehan * 6154047Sgrehan * Redistribution and use in source and binary forms, with or without 7154047Sgrehan * modification, are permitted provided that the following conditions 8154047Sgrehan * are met: 9154047Sgrehan * 1. Redistributions of source code must retain the above copyright 10154047Sgrehan * notice, this list of conditions and the following disclaimer. 11154047Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 12154047Sgrehan * notice, this list of conditions and the following disclaimer in the 13154047Sgrehan * documentation and/or other materials provided with the distribution. 14154047Sgrehan * 15154047Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16154047Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17154047Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18154047Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19154047Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20154047Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21154047Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22154047Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23154047Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24154047Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25154047Sgrehan * SUCH DAMAGE. 26154047Sgrehan */ 27154047Sgrehan 28290052Sjhb#include <sys/cdefs.h> 29290052Sjhb__FBSDID("$FreeBSD$"); 30154047Sgrehan 31290052Sjhb/* FreeBSD/powerpc-specific system call handling. */ 32154047Sgrehan 33168569Sdelphij#include <sys/ptrace.h> 34154047Sgrehan#include <sys/syscall.h> 35154047Sgrehan 36154047Sgrehan#include <machine/reg.h> 37154047Sgrehan#include <machine/frame.h> 38154047Sgrehan 39154047Sgrehan#include <stdio.h> 40154047Sgrehan 41154047Sgrehan#include "truss.h" 42154047Sgrehan 43211935Snwhitehorn#ifdef __powerpc64__ /* 32-bit compatibility */ 44211935Snwhitehorn#include "freebsd32_syscalls.h" 45240005Szont#define syscallnames freebsd32_syscallnames 46211935Snwhitehorn#else /* native 32-bit */ 47154047Sgrehan#include "syscalls.h" 48211935Snwhitehorn#endif 49154047Sgrehan 50290052Sjhbstatic int 51290052Sjhbpowerpc_fetch_args(struct trussinfo *trussinfo, u_int narg) 52240562Szont{ 53240005Szont struct ptrace_io_desc iorequest; 54240005Szont struct reg regs; 55290052Sjhb struct current_syscall *cs; 56240562Szont lwpid_t tid; 57290052Sjhb u_int i, reg; 58154047Sgrehan 59240562Szont tid = trussinfo->curthread->tid; 60290052Sjhb cs = &trussinfo->curthread->cs; 61240562Szont if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { 62240005Szont fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 63290052Sjhb return (-1); 64240005Szont } 65154047Sgrehan 66240005Szont /* 67290052Sjhb * FreeBSD has two special kinds of system call redirections -- 68240005Szont * SYS_syscall, and SYS___syscall. The former is the old syscall() 69240005Szont * 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. 73240005Szont */ 74290052Sjhb reg = 0; 75290052Sjhb switch (regs.fixreg[0]) { 76290052Sjhb case SYS_syscall: 77290052Sjhb reg += 1; 78290052Sjhb break; 79290052Sjhb case SYS___syscall: 80290052Sjhb reg += 2; 81290052Sjhb break; 82240005Szont } 83154047Sgrehan 84290052Sjhb for (i = 0; i < narg && reg < NARGREG; i++, reg++) { 85290052Sjhb#ifdef __powerpc64__ 86290052Sjhb cs->args[i] = regs.fixreg[FIRSTARG + reg] & 0xffffffff; 87290052Sjhb#else 88290052Sjhb cs->args[i] = regs.fixreg[FIRSTARG + reg]; 89290052Sjhb#endif 90240005Szont } 91290052Sjhb if (narg > i) { 92290052Sjhb#ifdef __powerpc64__ 93290052Sjhb uint32_t args32[narg - i]; 94290052Sjhb u_int j; 95154047Sgrehan 96290052Sjhb#endif 97240005Szont iorequest.piod_op = PIOD_READ_D; 98240005Szont iorequest.piod_offs = (void *)(regs.fixreg[1] + 8); 99290052Sjhb#ifdef __powerpc64__ 100290052Sjhb iorequest.piod_addr = args32; 101290052Sjhb iorequest.piod_len = sizeof(args32); 102290052Sjhb#else 103290052Sjhb iorequest.piod_addr = &cs->args[i]; 104290052Sjhb iorequest.piod_len = (narg - i) * sizeof(cs->args[0]); 105290052Sjhb#endif 106240562Szont ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); 107240005Szont if (iorequest.piod_len == 0) 108290052Sjhb return (-1); 109290052Sjhb#ifdef __powerpc64__ 110290052Sjhb for (j = 0; j < narg - i; j++) 111290052Sjhb cs->args[i + j] = args32[j]; 112154047Sgrehan#endif 113240005Szont } 114154047Sgrehan 115290052Sjhb return (0); 116154047Sgrehan} 117154047Sgrehan 118290052Sjhbstatic int 119290052Sjhbpowerpc_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) 120154047Sgrehan{ 121240005Szont struct reg regs; 122240562Szont lwpid_t tid; 123154047Sgrehan 124240562Szont tid = trussinfo->curthread->tid; 125240562Szont if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { 126290052Sjhb fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 127240005Szont return (-1); 128240005Szont } 129154047Sgrehan 130290052Sjhb /* XXX: Does not have fixup for __syscall(). */ 131290052Sjhb#ifdef __powerpc64__ 132290052Sjhb retval[0] = regs.fixreg[3] & 0xffffffff; 133290052Sjhb retval[1] = regs.fixreg[4] & 0xffffffff; 134290052Sjhb#else 135290052Sjhb retval[0] = regs.fixreg[3]; 136290052Sjhb retval[1] = regs.fixreg[4]; 137290052Sjhb#endif 138290052Sjhb *errorp = !!(regs.cr & 0x10000000); 139290052Sjhb return (0); 140290052Sjhb} 141154047Sgrehan 142290052Sjhbstatic struct procabi powerpc_fbsd = { 143290052Sjhb "FreeBSD ELF32", 144290052Sjhb syscallnames, 145290052Sjhb nitems(syscallnames), 146290052Sjhb powerpc_fetch_args, 147290052Sjhb powerpc_fetch_retval 148290052Sjhb}; 149154047Sgrehan 150290052SjhbPROCABI(powerpc_fbsd); 151