ia64-fbsd.c revision 122348
10SN/A/* 211001Smullan * Copryight 1997 Sean Eric Fagan 30SN/A * 40SN/A * Redistribution and use in source and binary forms, with or without 50SN/A * modification, are permitted provided that the following conditions 60SN/A * are met: 72362SN/A * 1. Redistributions of source code must retain the above copyright 80SN/A * notice, this list of conditions and the following disclaimer. 92362SN/A * 2. Redistributions in binary form must reproduce the above copyright 100SN/A * notice, this list of conditions and the following disclaimer in the 110SN/A * documentation and/or other materials provided with the distribution. 120SN/A * 3. All advertising materials mentioning features or use of this software 130SN/A * must display the following acknowledgement: 140SN/A * This product includes software developed by Sean Eric Fagan 150SN/A * 4. Neither the name of the author may be used to endorse or promote 160SN/A * products derived from this software without specific prior written 170SN/A * permission. 180SN/A * 190SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 200SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 212362SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 222362SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 232362SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 240SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 250SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 260SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 270SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 280SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 290SN/A * SUCH DAMAGE. 300SN/A */ 310SN/A 320SN/A#ifndef lint 330SN/Astatic const char rcsid[] = 340SN/A "$FreeBSD: head/usr.bin/truss/ia64-fbsd.c 122348 2003-11-09 03:48:13Z marcel $"; 350SN/A#endif /* not lint */ 360SN/A 370SN/A/* 380SN/A * FreeBSD/ia64-specific system call handling. This is probably the most 390SN/A * complex part of the entire truss program, although I've got lots of 400SN/A * it handled relatively cleanly now. The system call names are generated 410SN/A * automatically, thanks to /usr/src/sys/kern/syscalls.master. The 420SN/A * names used for the various structures are confusing, I sadly admit. 430SN/A */ 440SN/A 450SN/A#include <sys/types.h> 460SN/A#include <sys/ioctl.h> 470SN/A#include <sys/pioctl.h> 480SN/A#include <sys/syscall.h> 490SN/A 500SN/A#include <machine/reg.h> 510SN/A 520SN/A#include <errno.h> 530SN/A#include <fcntl.h> 540SN/A#include <signal.h> 550SN/A#include <stdio.h> 560SN/A#include <stdlib.h> 570SN/A#include <string.h> 580SN/A#include <time.h> 590SN/A#include <unistd.h> 600SN/A 610SN/A#include "truss.h" 620SN/A#include "syscall.h" 630SN/A#include "extern.h" 640SN/A 650SN/Astatic int fd = -1; 660SN/Astatic int cpid = -1; 670SN/Aextern int Procfd; 680SN/A 690SN/A#include "syscalls.h" 700SN/A 710SN/Astatic int nsyscalls = sizeof(syscallnames) / sizeof(syscallnames[0]); 720SN/A 730SN/A/* 740SN/A * This is what this particular file uses to keep track of a system call. 750SN/A * It is probably not quite sufficient -- I can probably use the same 760SN/A * structure for the various syscall personalities, and I also probably 770SN/A * need to nest system calls (for signal handlers). 780SN/A * 790SN/A * 'struct syscall' describes the system call; it may be NULL, however, 800SN/A * if we don't know about this particular system call yet. 810SN/A */ 820SN/Astatic struct freebsd_syscall { 830SN/A struct syscall *sc; 840SN/A const char *name; 850SN/A int number; 860SN/A unsigned long *args; 870SN/A int nargs; /* number of arguments -- *not* number of words! */ 880SN/A char **s_args; /* the printable arguments */ 890SN/A} fsc; 900SN/A 910SN/A/* Clear up and free parts of the fsc structure. */ 920SN/Astatic __inline void 930SN/Aclear_fsc(void) { 940SN/A if (fsc.args) { 950SN/A free(fsc.args); 960SN/A } 970SN/A if (fsc.s_args) { 980SN/A int i; 990SN/A for (i = 0; i < fsc.nargs; i++) 1000SN/A if (fsc.s_args[i]) 1010SN/A free(fsc.s_args[i]); 1020SN/A free(fsc.s_args); 1030SN/A } 1040SN/A memset(&fsc, 0, sizeof(fsc)); 1050SN/A} 1060SN/A 1070SN/A/* 1080SN/A * Called when a process has entered a system call. nargs is the 1090SN/A * number of words, not number of arguments (a necessary distinction 1100SN/A * in some cases). Note that if the STOPEVENT() code in ia64/ia64/trap.c 1110SN/A * is ever changed these functions need to keep up. 1120SN/A */ 1130SN/A 1140SN/Avoid 1150SN/Aia64_syscall_entry(struct trussinfo *trussinfo, int nargs) { 1160SN/A char buf[32]; 1170SN/A struct reg regs; 1180SN/A int syscall_num; 1190SN/A int i; 1200SN/A unsigned long *parm_offset; 1210SN/A struct syscall *sc; 1220SN/A 1230SN/A if (fd == -1 || trussinfo->pid != cpid) { 1240SN/A sprintf(buf, "/proc/%d/regs", trussinfo->pid); 1250SN/A fd = open(buf, O_RDWR); 1260SN/A if (fd == -1) { 1270SN/A fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); 1280SN/A return; 1290SN/A } 1300SN/A cpid = trussinfo->pid; 1310SN/A } 1320SN/A 1330SN/A clear_fsc(); 1340SN/A lseek(fd, 0L, 0); 1350SN/A if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { 1360SN/A fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 1370SN/A return; 1380SN/A } 13911001Smullan parm_offset = ®s.r_scratch.gr16; 1400SN/A 1410SN/A /* 1420SN/A * FreeBSD has two special kinds of system call redirctions -- 1430SN/A * SYS_syscall, and SYS___syscall. The former is the old syscall() 1440SN/A * routine, basicly; the latter is for quad-aligned arguments. 1450SN/A */ 1460SN/A syscall_num = regs.r_scratch.gr15; /* XXX double-check. */ 1470SN/A if (syscall_num == SYS_syscall || syscall_num == SYS___syscall) 1480SN/A syscall_num = (int)*parm_offset++; 1490SN/A 1500SN/A fsc.number = syscall_num; 1510SN/A fsc.name = (syscall_num < 0 || syscall_num > nsyscalls) 1520SN/A ? NULL : syscallnames[syscall_num]; 1530SN/A if (!fsc.name) { 1540SN/A fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n", syscall_num); 1550SN/A } 1560SN/A 1570SN/A if (fsc.name && (trussinfo->flags & FOLLOWFORKS) 1580SN/A && ((!strcmp(fsc.name, "fork") 1590SN/A || !strcmp(fsc.name, "rfork") 1600SN/A || !strcmp(fsc.name, "vfork")))) 1610SN/A { 1620SN/A trussinfo->in_fork = 1; 1630SN/A } 1640SN/A 1650SN/A if (nargs == 0) 1660SN/A return; 1670SN/A 1680SN/A fsc.args = malloc((1+nargs) * sizeof(unsigned long)); 1690SN/A memcpy(fsc.args, parm_offset, nargs * sizeof(long)); 1700SN/A 1710SN/A sc = get_syscall(fsc.name); 1720SN/A if (sc) { 1730SN/A fsc.nargs = sc->nargs; 1740SN/A } else { 1750SN/A#if DEBUG 1760SN/A fprintf(trussinfo->outfile, "unknown syscall %s -- setting args to %d\n", 1770SN/A fsc.name, nargs); 1780SN/A#endif 1790SN/A fsc.nargs = nargs; 1800SN/A } 1810SN/A 1820SN/A fsc.s_args = malloc((1+fsc.nargs) * sizeof(char*)); 1830SN/A memset(fsc.s_args, 0, fsc.nargs * sizeof(char*)); 1840SN/A fsc.sc = sc; 1850SN/A 1860SN/A /* 1870SN/A * At this point, we set up the system call arguments. 1880SN/A * We ignore any OUT ones, however -- those are arguments that 1890SN/A * are set by the system call, and so are probably meaningless 1900SN/A * now. This doesn't currently support arguments that are 1910SN/A * passed in *and* out, however. 1920SN/A */ 1930SN/A 1940SN/A if (fsc.name) { 1950SN/A 1960SN/A#if DEBUG 1970SN/A fprintf(stderr, "syscall %s(", fsc.name); 1980SN/A#endif 1990SN/A for (i = 0; i < fsc.nargs; i++) { 2000SN/A#if DEBUG 2010SN/A fprintf(stderr, "0x%x%s", 2020SN/A sc 2030SN/A ? fsc.args[sc->args[i].offset] 2040SN/A : fsc.args[i], 2050SN/A i < (fsc.nargs - 1) ? "," : ""); 2060SN/A#endif 2070SN/A if (sc && !(sc->args[i].type & OUT)) { 2080SN/A fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args); 2090SN/A } 2100SN/A } 2110SN/A#if DEBUG 2120SN/A fprintf(stderr, ")\n"); 2130SN/A#endif 2140SN/A } 2150SN/A 2160SN/A#if DEBUG 2170SN/A fprintf(trussinfo->outfile, "\n"); 2180SN/A#endif 2190SN/A 2200SN/A /* 2210SN/A * Some system calls should be printed out before they are done -- 2220SN/A * execve() and exit(), for example, never return. Possibly change 2230SN/A * this to work for any system call that doesn't have an OUT 2240SN/A * parameter? 2250SN/A */ 2260SN/A 2270SN/A if (!strcmp(fsc.name, "execve") || !strcmp(fsc.name, "exit")) { 2280SN/A 2290SN/A /* XXX 2300SN/A * This could be done in a more general 2310SN/A * manner but it still wouldn't be very pretty. 2320SN/A */ 2330SN/A if (!strcmp(fsc.name, "execve")) { 2340SN/A if ((trussinfo->flags & EXECVEARGS) == 0) 2350SN/A if (fsc.s_args[1]) { 2360SN/A free(fsc.s_args[1]); 2370SN/A fsc.s_args[1] = NULL; 2380SN/A } 2390SN/A if ((trussinfo->flags & EXECVEENVS) == 0) 2400SN/A if (fsc.s_args[2]) { 2410SN/A free(fsc.s_args[2]); 2420SN/A fsc.s_args[2] = NULL; 2430SN/A } 2440SN/A } 245 246 print_syscall(trussinfo, fsc.name, fsc.nargs, fsc.s_args); 247 fprintf(trussinfo->outfile, "\n"); 248 } 249 250 return; 251} 252 253/* 254 * And when the system call is done, we handle it here. 255 * Currently, no attempt is made to ensure that the system calls 256 * match -- this needs to be fixed (and is, in fact, why S_SCX includes 257 * the sytem call number instead of, say, an error status). 258 */ 259 260long 261ia64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) 262{ 263 char buf[32]; 264 struct reg regs; 265 long retval; 266 int i; 267 int errorp; 268 struct syscall *sc; 269 270 if (fd == -1 || trussinfo->pid != cpid) { 271 sprintf(buf, "/proc/%d/regs", trussinfo->pid); 272 fd = open(buf, O_RDONLY); 273 if (fd == -1) { 274 fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); 275 return (-1); 276 } 277 cpid = trussinfo->pid; 278 } 279 280 lseek(fd, 0L, 0); 281 if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { 282 fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); 283 return (-1); 284 } 285 retval = regs.r_scratch.gr8; 286 errorp = (regs.r_scratch.gr10 != 0) ? 1 : 0; 287 288 /* 289 * This code, while simpler than the initial versions I used, could 290 * stand some significant cleaning. 291 */ 292 293 sc = fsc.sc; 294 if (!sc) { 295 for (i = 0; i < fsc.nargs; i++) 296 asprintf(&fsc.s_args[i], "0x%lx", fsc.args[i]); 297 } else { 298 /* 299 * Here, we only look for arguments that have OUT masked in -- 300 * otherwise, they were handled in the syscall_entry function. 301 */ 302 for (i = 0; i < sc->nargs; i++) { 303 char *temp; 304 if (sc->args[i].type & OUT) { 305 /* 306 * If an error occurred, than don't bothe getting the data; 307 * it may not be valid. 308 */ 309 if (errorp) 310 asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); 311 else 312 temp = print_arg(Procfd, &sc->args[i], fsc.args); 313 fsc.s_args[i] = temp; 314 } 315 } 316 } 317 318 /* 319 * It would probably be a good idea to merge the error handling, 320 * but that complicates things considerably. 321 */ 322 323 print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, retval); 324 clear_fsc(); 325 326 return (retval); 327} 328