amd64-linux32.c revision 100357
190075Sobrien/* 2132718Skan * Copryight 1997 Sean Eric Fagan 3169689Skan * 4169689Skan * Redistribution and use in source and binary forms, with or without 590075Sobrien * modification, are permitted provided that the following conditions 690075Sobrien * are met: 7132718Skan * 1. Redistributions of source code must retain the above copyright 890075Sobrien * notice, this list of conditions and the following disclaimer. 9132718Skan * 2. Redistributions in binary form must reproduce the above copyright 10132718Skan * notice, this list of conditions and the following disclaimer in the 11132718Skan * documentation and/or other materials provided with the distribution. 12132718Skan * 3. All advertising materials mentioning features or use of this software 1390075Sobrien * must display the following acknowledgement: 14132718Skan * This product includes software developed by Sean Eric Fagan 15132718Skan * 4. Neither the name of the author may be used to endorse or promote 16132718Skan * products derived from this software without specific prior written 17132718Skan * permission. 1890075Sobrien * 1990075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2390075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2490075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2590075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26132718Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27132718Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28132718Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29132718Skan * SUCH DAMAGE. 30132718Skan */ 31132718Skan 32132718Skan#ifndef lint 33132718Skanstatic const char rcsid[] = 34132718Skan "$FreeBSD: head/usr.bin/truss/amd64-linux32.c 100357 2002-07-19 13:49:37Z markm $"; 35132718Skan#endif /* not lint */ 36132718Skan 37132718Skan/* 38169689Skan * Linux/i386-specific system call handling. Given how much of this code 39169689Skan * is taken from the freebsd equivalent, I can probably put even more of 40169689Skan * it in support routines that can be used by any personality support. 41169689Skan */ 42132718Skan 43132718Skan#include <sys/types.h> 44132718Skan#include <sys/ioctl.h> 45132718Skan#include <sys/pioctl.h> 46132718Skan 47132718Skan#include <machine/reg.h> 48132718Skan#include <machine/psl.h> 49132718Skan 50132718Skan#include <errno.h> 51132718Skan#include <fcntl.h> 52132718Skan#include <signal.h> 53132718Skan#include <stdio.h> 54132718Skan#include <stdlib.h> 55132718Skan#include <string.h> 56132718Skan#include <unistd.h> 57132718Skan 58169689Skan#include "extern.h" 59169689Skan#include "syscall.h" 60169689Skan 61169689Skanstatic int fd = -1; 62169689Skanstatic int cpid = -1; 63169689Skanextern int Procfd; 64169689Skan 65169689Skanextern FILE *outfile; 66169689Skan#include "linux_syscalls.h" 67169689Skan 68169689Skanstatic int nsyscalls = 69169689Skan sizeof(linux_syscallnames) / sizeof(linux_syscallnames[0]); 70169689Skan 71169689Skan/* See the comment in i386-fbsd.c about this structure. */ 72169689Skanstatic struct linux_syscall { 73169689Skan struct syscall *sc; 74169689Skan char *name; 75132718Skan int number; 76132718Skan unsigned long args[5]; 77132718Skan int nargs; /* number of arguments -- *not* number of words! */ 78132718Skan char **s_args; /* the printable arguments */ 79132718Skan} lsc; 80132718Skan 81132718Skanstatic __inline void 82132718Skanclear_lsc() { 83169689Skan if (lsc.s_args) { 84169689Skan int i; 85132718Skan for (i = 0; i < lsc.nargs; i++) 86132718Skan if (lsc.s_args[i]) 8790075Sobrien free(lsc.s_args[i]); 8890075Sobrien free(lsc.s_args); 8990075Sobrien } 90169689Skan memset(&lsc, 0, sizeof(lsc)); 9190075Sobrien} 9290075Sobrien 9390075Sobrienvoid 94169689Skani386_linux_syscall_entry(int pid, int nargs) { 9590075Sobrien char buf[32]; 9690075Sobrien struct reg regs = { 0 }; 9790075Sobrien int syscall; 9890075Sobrien int i; 9990075Sobrien struct syscall *sc; 10090075Sobrien 10190075Sobrien if (fd == -1 || pid != cpid) { 10290075Sobrien sprintf(buf, "/proc/%d/regs", pid); 10390075Sobrien fd = open(buf, O_RDWR); 10490075Sobrien if (fd == -1) { 10590075Sobrien fprintf(outfile, "-- CANNOT READ REGISTERS --\n"); 10690075Sobrien return; 10790075Sobrien } 10890075Sobrien cpid = pid; 109132718Skan } 11090075Sobrien 11190075Sobrien clear_lsc(); 112132718Skan lseek(fd, 0L, 0); 11390075Sobrien i = read(fd, ®s, sizeof(regs)); 114132718Skan syscall = regs.r_eax; 115132718Skan 116132718Skan lsc.number = syscall; 117132718Skan lsc.name = 118132718Skan (syscall < 0 || syscall > nsyscalls) ? NULL : linux_syscallnames[syscall]; 119132718Skan if (!lsc.name) { 120132718Skan fprintf (outfile, "-- UNKNOWN SYSCALL %d\n", syscall); 121132718Skan } 122132718Skan 123132718Skan if (nargs == 0) 124132718Skan return; 125132718Skan 126132718Skan /* 12790075Sobrien * Linux passes syscall arguments in registers, not 128169689Skan * on the stack. Fortunately, we've got access to the 129169689Skan * register set. Note that we don't bother checking the 130169689Skan * number of arguments. And what does linux do for syscalls 131169689Skan * that have more than five arguments? 132169689Skan */ 13390075Sobrien 134169689Skan lsc.args[0] = regs.r_ebx; 135169689Skan lsc.args[1] = regs.r_ecx; 136169689Skan lsc.args[2] = regs.r_edx; 137169689Skan lsc.args[3] = regs.r_esi; 138169689Skan lsc.args[4] = regs.r_edi; 139169689Skan 140169689Skan sc = get_syscall(lsc.name); 141169689Skan if (sc) { 142169689Skan lsc.nargs = sc->nargs; 143169689Skan } else { 144169689Skan#ifdef DEBUG 145169689Skan fprintf(outfile, "unknown syscall %s -- setting args to %d\n", 146169689Skan lsc.name, nargs); 147169689Skan#endif 148169689Skan lsc.nargs = nargs; 149169689Skan } 150169689Skan 151169689Skan lsc.s_args = malloc((1+lsc.nargs) * sizeof(char*)); 152169689Skan memset(lsc.s_args, 0, lsc.nargs * sizeof(char*)); 153169689Skan lsc.sc = sc; 154169689Skan 155169689Skan if (lsc.name) { 156169689Skan 157169689Skan#ifdef DEBUG 158169689Skan fprintf(stderr, "syscall %s(", lsc.name); 159169689Skan#endif 160169689Skan for (i = 0; i < lsc.nargs ; i++) { 161169689Skan#ifdef DEBUG 162169689Skan fprintf(stderr, "0x%x%s", 163169689Skan sc ? 164169689Skan lsc.args[sc->args[i].offset] 165169689Skan : lsc.args[i], 166169689Skan i < (lsc.nargs - 1) ? "," : ""); 167169689Skan#endif 168169689Skan if (sc && !(sc->args[i].type & OUT)) { 169169689Skan lsc.s_args[i] = print_arg(Procfd, &sc->args[i], lsc.args); 17090075Sobrien } 17190075Sobrien } 17290075Sobrien#ifdef DEBUG 173169689Skan fprintf(stderr, ")\n"); 17490075Sobrien#endif 175169689Skan } 17690075Sobrien 17790075Sobrien if (!strcmp(lsc.name, "linux_execve") || !strcmp(lsc.name, "exit")) { 17890075Sobrien print_syscall(outfile, lsc.name, lsc.nargs, lsc.s_args); 179169689Skan } 18090075Sobrien 181169689Skan return; 18290075Sobrien} 18390075Sobrien 184169689Skan/* 185169689Skan * Linux syscalls return negative errno's, we do positive and map them 18690075Sobrien */ 18790075Sobrienconst int bsd_to_linux_errno[] = { 188169689Skan -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, 18990075Sobrien -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, 190169689Skan -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, 19190075Sobrien -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, 19290075Sobrien -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, 193132718Skan -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, 19490075Sobrien -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, 195169689Skan -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, 19690075Sobrien -6, 19790075Sobrien}; 19890075Sobrien 19990075Sobrienvoid 20090075Sobrieni386_linux_syscall_exit(int pid, int syscall) { 20190075Sobrien char buf[32]; 202169689Skan struct reg regs; 20390075Sobrien int retval; 20490075Sobrien int i; 20590075Sobrien int errorp; 20690075Sobrien struct syscall *sc; 20790075Sobrien 20890075Sobrien if (fd == -1 || pid != cpid) { 20990075Sobrien sprintf(buf, "/proc/%d/regs", pid); 21090075Sobrien fd = open(buf, O_RDONLY); 21190075Sobrien if (fd == -1) { 21290075Sobrien fprintf(outfile, "-- CANNOT READ REGISTERS --\n"); 213169689Skan return; 21490075Sobrien } 215169689Skan cpid = pid; 21690075Sobrien } 21790075Sobrien 21890075Sobrien lseek(fd, 0L, 0); 219132718Skan if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) 22090075Sobrien return; 221169689Skan 22290075Sobrien retval = regs.r_eax; 22390075Sobrien errorp = !!(regs.r_eflags & PSL_C); 22490075Sobrien 22590075Sobrien sc = lsc.sc; 22690075Sobrien if (!sc) { 22790075Sobrien for (i = 0; i < lsc.nargs; i++) { 228169689Skan lsc.s_args[i] = malloc(12); 22990075Sobrien sprintf(lsc.s_args[i], "0x%lx", lsc.args[i]); 23090075Sobrien } 23190075Sobrien } else { 23290075Sobrien for (i = 0; i < sc->nargs; i++) { 23390075Sobrien char *temp; 23490075Sobrien if (sc->args[i].type & OUT) { 23590075Sobrien if (errorp) { 23690075Sobrien temp = malloc(12); 23790075Sobrien sprintf(temp, "0x%lx", lsc.args[sc->args[i].offset]); 23890075Sobrien } else { 23990075Sobrien temp = print_arg(Procfd, &sc->args[i], lsc.args); 24090075Sobrien } 24190075Sobrien lsc.s_args[i] = temp; 24290075Sobrien } 24390075Sobrien } 24490075Sobrien } 24590075Sobrien if (errorp) { 24690075Sobrien for (i = 0; i < sizeof(bsd_to_linux_errno) / sizeof(int); i++) 24790075Sobrien if (retval == bsd_to_linux_errno[i]) 24890075Sobrien break; 24990075Sobrien } 25090075Sobrien print_syscall_ret(outfile, lsc.name, lsc.nargs, lsc.s_args, errorp, 251132718Skan errorp ? i : retval); 25290075Sobrien clear_lsc(); 25390075Sobrien return; 25490075Sobrien} 25590075Sobrien