131567Ssef/* 2204977Simp * Copyright 1997 Sean Eric Fagan 331899Ssef * 431899Ssef * Redistribution and use in source and binary forms, with or without 531899Ssef * modification, are permitted provided that the following conditions 631899Ssef * are met: 731899Ssef * 1. Redistributions of source code must retain the above copyright 831899Ssef * notice, this list of conditions and the following disclaimer. 931899Ssef * 2. Redistributions in binary form must reproduce the above copyright 1031899Ssef * notice, this list of conditions and the following disclaimer in the 1131899Ssef * documentation and/or other materials provided with the distribution. 1231899Ssef * 3. All advertising materials mentioning features or use of this software 1331899Ssef * must display the following acknowledgement: 1431899Ssef * This product includes software developed by Sean Eric Fagan 1531899Ssef * 4. Neither the name of the author may be used to endorse or promote 1631899Ssef * products derived from this software without specific prior written 1731899Ssef * permission. 1831899Ssef * 1931899Ssef * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2031899Ssef * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2131899Ssef * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2231899Ssef * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2331899Ssef * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2431899Ssef * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2531899Ssef * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2631899Ssef * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2731899Ssef * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2831899Ssef * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2931899Ssef * SUCH DAMAGE. 3031899Ssef */ 3131899Ssef 32290052Sjhb#include <sys/cdefs.h> 33290052Sjhb__FBSDID("$FreeBSD$"); 3432275Scharnier 35290052Sjhb/* Linux/i386-specific system call handling. */ 3632275Scharnier 37168569Sdelphij#include <sys/ptrace.h> 3885301Sdes 3985301Sdes#include <machine/reg.h> 4085301Sdes#include <machine/psl.h> 4185301Sdes 4231567Ssef#include <stdio.h> 4331567Ssef 44101282Smdodd#include "truss.h" 4531567Ssef 4631567Ssef#include "linux_syscalls.h" 4731567Ssef 48290052Sjhbstatic int 49290052Sjhbi386_linux_fetch_args(struct trussinfo *trussinfo, u_int narg) 50240562Szont{ 51240005Szont struct reg regs; 52290052Sjhb struct current_syscall *cs; 53240562Szont lwpid_t tid; 5431567Ssef 55240562Szont tid = trussinfo->curthread->tid; 56290052Sjhb cs = &trussinfo->curthread->cs; 57240562Szont if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { 58240005Szont fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 59290052Sjhb return (-1); 60240005Szont } 6131567Ssef 62240005Szont /* 63240005Szont * Linux passes syscall arguments in registers, not 64240005Szont * on the stack. Fortunately, we've got access to the 65240005Szont * register set. Note that we don't bother checking the 66240005Szont * number of arguments. And what does linux do for syscalls 67240005Szont * that have more than five arguments? 68240005Szont */ 69290052Sjhb switch (narg) { 70290052Sjhb default: 71290052Sjhb cs->args[5] = regs.r_ebp; /* Unconfirmed */ 72290052Sjhb case 5: 73290052Sjhb cs->args[4] = regs.r_edi; 74290052Sjhb case 4: 75290052Sjhb cs->args[3] = regs.r_esi; 76290052Sjhb case 3: 77290052Sjhb cs->args[2] = regs.r_edx; 78290052Sjhb case 2: 79290052Sjhb cs->args[1] = regs.r_ecx; 80290052Sjhb case 1: 81290052Sjhb cs->args[0] = regs.r_ebx; 82240005Szont } 8331567Ssef 84290052Sjhb return (0); 8531567Ssef} 8631567Ssef 8731567Ssef/* 8831567Ssef * Linux syscalls return negative errno's, we do positive and map them 8931567Ssef */ 90228396Sedstatic const int bsd_to_linux_errno[] = { 91240005Szont -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, 92240005Szont -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, 93240005Szont -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, 94240005Szont -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, 95240005Szont -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, 9631567Ssef -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, 9731567Ssef -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, 9831567Ssef -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, 99240005Szont -6, 10031567Ssef}; 10131567Ssef 102290052Sjhbstatic int 103290052Sjhbi386_linux_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) 104122348Smarcel{ 105240005Szont struct reg regs; 106240562Szont lwpid_t tid; 107290052Sjhb size_t i; 10831567Ssef 109240562Szont tid = trussinfo->curthread->tid; 110240562Szont if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { 111240005Szont fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 112240005Szont return (-1); 113240005Szont } 11431567Ssef 115290052Sjhb retval[0] = regs.r_eax; 116290052Sjhb retval[1] = regs.r_edx; 117290052Sjhb *errorp = !!(regs.r_eflags & PSL_C); 118101374Smdodd 119290052Sjhb if (*errorp) { 120290052Sjhb for (i = 0; i < nitems(bsd_to_linux_errno); i++) { 121290052Sjhb if (retval[0] == bsd_to_linux_errno[i]) { 122290052Sjhb retval[0] = i; 123290052Sjhb return (0); 124240005Szont } 125240005Szont } 126171055Sdelphij 127290052Sjhb /* XXX: How to handle unknown errors? */ 128240005Szont } 129290052Sjhb return (0); 130290052Sjhb} 131171055Sdelphij 132290052Sjhbstatic struct procabi i386_linux = { 133296010Sjhb "Linux ELF", 134290052Sjhb linux_syscallnames, 135290052Sjhb nitems(linux_syscallnames), 136290052Sjhb i386_linux_fetch_args, 137290052Sjhb i386_linux_fetch_retval 138290052Sjhb}; 139101282Smdodd 140290052SjhbPROCABI(i386_linux); 141