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 46179051Sjhb#include "linux32_syscalls.h" 4731567Ssef 48290052Sjhbstatic int 49290052Sjhbamd64_linux32_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_rbp; /* Unconfirmed */ 72290052Sjhb case 5: 73290052Sjhb cs->args[4] = regs.r_rdi; 74290052Sjhb case 4: 75290052Sjhb cs->args[3] = regs.r_rsi; 76290052Sjhb case 3: 77290052Sjhb cs->args[2] = regs.r_rdx; 78290052Sjhb case 2: 79290052Sjhb cs->args[1] = regs.r_rcx; 80290052Sjhb case 1: 81290052Sjhb cs->args[0] = regs.r_rbx; 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 103290052Sjhbamd64_linux32_fetch_retval(struct trussinfo *trussinfo, long *retval, 104290052Sjhb int *errorp) 105122348Smarcel{ 106240005Szont struct reg regs; 107240562Szont lwpid_t tid; 108290052Sjhb size_t i; 10931567Ssef 110240562Szont tid = trussinfo->curthread->tid; 111240562Szont if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { 112240005Szont fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 113240005Szont return (-1); 114240005Szont } 11531567Ssef 116290052Sjhb retval[0] = regs.r_rax & 0xffffffff; 117290052Sjhb retval[1] = regs.r_rdx & 0xffffffff; 118290052Sjhb *errorp = !!(regs.r_rflags & PSL_C); 119296010Sjhb if (*errorp) 120296010Sjhb retval[0] = (int)retval[0]; 121101374Smdodd 122290052Sjhb if (*errorp) { 123290052Sjhb for (i = 0; i < nitems(bsd_to_linux_errno); i++) { 124290052Sjhb if (retval[0] == bsd_to_linux_errno[i]) { 125290052Sjhb retval[0] = i; 126290052Sjhb return (0); 127240005Szont } 128240005Szont } 129171055Sdelphij 130290052Sjhb /* XXX: How to handle unknown errors? */ 131240005Szont } 132290052Sjhb return (0); 133290052Sjhb} 134171055Sdelphij 135290052Sjhbstatic struct procabi amd64_linux32 = { 136290052Sjhb "Linux ELF32", 137290052Sjhb linux32_syscallnames, 138290052Sjhb nitems(linux32_syscallnames), 139290052Sjhb amd64_linux32_fetch_args, 140290052Sjhb amd64_linux32_fetch_retval 141290052Sjhb}; 142101282Smdodd 143290052SjhbPROCABI(amd64_linux32); 144