198944Sobrien/* Machine independent support for SVR4 /proc (process file system) for GDB. 2130803Smarcel 3130803Smarcel Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc. 4130803Smarcel 598944Sobrien Written by Michael Snyder at Cygnus Solutions. 698944Sobrien Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others. 798944Sobrien 898944SobrienThis file is part of GDB. 998944Sobrien 1098944SobrienThis program is free software; you can redistribute it and/or modify 1198944Sobrienit under the terms of the GNU General Public License as published by 1298944Sobrienthe Free Software Foundation; either version 2 of the License, or 1398944Sobrien(at your option) any later version. 1498944Sobrien 1598944SobrienThis program is distributed in the hope that it will be useful, 1698944Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1798944SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1898944SobrienGNU General Public License for more details. 1998944Sobrien 2098944SobrienYou should have received a copy of the GNU General Public License 2198944Sobrienalong with this program; if not, write to the Free Software Foundation, 2298944SobrienInc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2398944Sobrien 2498944Sobrien/* 2598944Sobrien * Pretty-print trace of api calls to the /proc api 2698944Sobrien * (ioctl or read/write calls). 2798944Sobrien * 2898944Sobrien */ 2998944Sobrien 3098944Sobrien#include "defs.h" 3198944Sobrien#include "gdbcmd.h" 3298944Sobrien#include "completer.h" 3398944Sobrien 3498944Sobrien#if defined (NEW_PROC_API) 3598944Sobrien#define _STRUCTURED_PROC 1 3698944Sobrien#endif 3798944Sobrien 3898944Sobrien#include <stdio.h> 3998944Sobrien#include <sys/types.h> 4098944Sobrien#include <sys/procfs.h> 41130803Smarcel#ifdef HAVE_SYS_PROC_H 4298944Sobrien#include <sys/proc.h> /* for struct proc */ 43130803Smarcel#endif 4498944Sobrien#ifdef HAVE_SYS_USER_H 4598944Sobrien#include <sys/user.h> /* for struct user */ 4698944Sobrien#endif 4798944Sobrien#include <fcntl.h> /* for O_RDWR etc. */ 48130803Smarcel#include "gdb_wait.h" 4998944Sobrien 5098944Sobrien#include "proc-utils.h" 5198944Sobrien 5298944Sobrien/* Much of the information used in the /proc interface, particularly for 5398944Sobrien printing status information, is kept as tables of structures of the 5498944Sobrien following form. These tables can be used to map numeric values to 5598944Sobrien their symbolic names and to a string that describes their specific use. */ 5698944Sobrien 5798944Sobrienstruct trans { 5898944Sobrien long value; /* The numeric value */ 5998944Sobrien char *name; /* The equivalent symbolic value */ 6098944Sobrien char *desc; /* Short description of value */ 6198944Sobrien}; 6298944Sobrien 6398944Sobrienstatic int procfs_trace = 0; 6498944Sobrienstatic FILE *procfs_file = NULL; 6598944Sobrienstatic char *procfs_filename = "procfs_trace"; 6698944Sobrien 6798944Sobrienstatic void 6898944Sobrienprepare_to_trace (void) 6998944Sobrien{ 7098944Sobrien if (procfs_trace) /* if procfs tracing turned on */ 7198944Sobrien if (procfs_file == NULL) /* if output file not yet open */ 7298944Sobrien if (procfs_filename != NULL) /* if output filename known */ 7398944Sobrien procfs_file = fopen (procfs_filename, "a"); /* open output file */ 7498944Sobrien} 7598944Sobrien 7698944Sobrienstatic void 7798944Sobrienset_procfs_trace_cmd (char *args, int from_tty, struct cmd_list_element *c) 7898944Sobrien{ 7998944Sobrien#if 0 /* not sure what I might actually need to do here, if anything */ 8098944Sobrien if (procfs_file) 8198944Sobrien fflush (procfs_file); 8298944Sobrien#endif 8398944Sobrien} 8498944Sobrien 8598944Sobrienstatic void 8698944Sobrienset_procfs_file_cmd (char *args, int from_tty, struct cmd_list_element *c) 8798944Sobrien{ 8898944Sobrien /* Just changed the filename for procfs tracing. 8998944Sobrien If a file was already open, close it. */ 9098944Sobrien if (procfs_file) 9198944Sobrien fclose (procfs_file); 9298944Sobrien procfs_file = NULL; 9398944Sobrien} 9498944Sobrien 9598944Sobrien 9698944Sobrien#ifndef NEW_PROC_API 9798944Sobrien 9898944Sobrienstatic struct trans ioctl_table[] = { 9998944Sobrien#ifdef PIOCACINFO /* irix */ 10098944Sobrien { PIOCACINFO, "PIOCACINFO", "get process account info" }, 10198944Sobrien#endif 10298944Sobrien { PIOCACTION, "PIOCACTION", "get signal action structs" }, 10398944Sobrien#ifdef PIOCARGUMENTS /* osf */ 10498944Sobrien { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" }, 10598944Sobrien#endif 10698944Sobrien#ifdef PIOCAUXV /* solaris aux vectors */ 10798944Sobrien { PIOCAUXV, "PIOCAUXV", "get aux vector" }, 10898944Sobrien { PIOCNAUXV, "PIOCNAUXV", "get number of aux vector entries" }, 10998944Sobrien#endif /* AUXV */ 11098944Sobrien { PIOCCFAULT, "PIOCCFAULT", "clear current fault" }, 11198944Sobrien { PIOCCRED, "PIOCCRED", "get process credentials" }, 11298944Sobrien#ifdef PIOCENEVCTRS /* irix event counters */ 11398944Sobrien { PIOCENEVCTRS, "PIOCENEVCTRS", "acquire and start event counters" }, 11498944Sobrien { PIOCGETEVCTRL, "PIOCGETEVCTRL", "get control info of event counters" }, 11598944Sobrien { PIOCGETEVCTRS, "PIOCGETEVCTRS", "dump event counters" }, 11698944Sobrien { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" }, 11798944Sobrien { PIOCRELEVCTRS, "PIOCRELEVCTRS", "release/stop event counters" }, 11898944Sobrien { PIOCSETEVCTRL, "PIOCSETEVCTRL", "set control info of event counters" }, 11998944Sobrien { PIOCGETPTIMER, "PIOCGETPTIMER", "get process timers" }, 12098944Sobrien#endif /* irix event counters */ 12198944Sobrien { PIOCGENTRY, "PIOCGENTRY", "get traced syscall entry set" }, 12298944Sobrien#if defined (PIOCGETPR) 12398944Sobrien { PIOCGETPR, "PIOCGETPR", "read struct proc" }, 12498944Sobrien#endif 12598944Sobrien#if defined (PIOCGETU) 12698944Sobrien { PIOCGETU, "PIOCGETU", "read user area" }, 12798944Sobrien#endif 12898944Sobrien#if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */ 12998944Sobrien { PIOCGETUTK, "PIOCGETUTK", "get the utask struct" }, 13098944Sobrien#endif 13198944Sobrien { PIOCGEXIT, "PIOCGEXIT", "get traced syscall exit set" }, 13298944Sobrien { PIOCGFAULT, "PIOCGFAULT", "get traced fault set" }, 13398944Sobrien#ifdef PIOCGFPCR /* osf */ 13498944Sobrien { PIOCGFPCR, "PIOCGFPCR", "get FP control register" }, 13598944Sobrien { PIOCSFPCR, "PIOCSFPCR", "set FP conrtol register" }, 13698944Sobrien#endif 13798944Sobrien { PIOCGFPREG, "PIOCGFPREG", "get floating point registers" }, 13898944Sobrien { PIOCGHOLD, "PIOCGHOLD", "get held signal set" }, 13998944Sobrien { PIOCGREG, "PIOCGREG", "get general registers" }, 14098944Sobrien { PIOCGROUPS, "PIOCGROUPS", "get supplementary groups" }, 14198944Sobrien#ifdef PIOCGSPCACT /* osf */ 14298944Sobrien { PIOCGSPCACT, "PIOCGSPCACT", "get special action" }, 14398944Sobrien { PIOCSSPCACT, "PIOCSSPCACT", "set special action" }, 14498944Sobrien#endif 14598944Sobrien { PIOCGTRACE, "PIOCGTRACE", "get traced signal set" }, 14698944Sobrien#ifdef PIOCGWATCH /* irix watchpoints */ 14798944Sobrien { PIOCGWATCH, "PIOCGWATCH", "get watchpoint" }, 14898944Sobrien { PIOCSWATCH, "PIOCSWATCH", "set watchpoint" }, 14998944Sobrien { PIOCNWATCH, "PIOCNWATCH", "get number of watchpoints" }, 15098944Sobrien#endif /* irix watchpoints */ 15198944Sobrien#ifdef PIOCGWIN /* solaris sparc */ 15298944Sobrien { PIOCGWIN, "PIOCGWIN", "get gwindows_t" }, 15398944Sobrien#endif 15498944Sobrien#ifdef PIOCGXREG /* solaris sparc extra regs */ 15598944Sobrien { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" }, 15698944Sobrien { PIOCGXREG, "PIOCGXREG", "get extra register state" }, 15798944Sobrien { PIOCSXREG, "PIOCSXREG", "set extra register state" }, 15898944Sobrien#endif /* XREG */ 15998944Sobrien { PIOCKILL, "PIOCKILL", "send signal" }, 16098944Sobrien#ifdef PIOCLDT /* solaris i386 */ 16198944Sobrien { PIOCLDT, "PIOCLDT", "get LDT" }, 16298944Sobrien { PIOCNLDT, "PIOCNLDT", "get number of LDT entries" }, 16398944Sobrien#endif 16498944Sobrien#ifdef PIOCLSTATUS /* solaris and unixware */ 16598944Sobrien { PIOCLSTATUS, "PIOCLSTATUS", "get status of all lwps" }, 16698944Sobrien { PIOCLUSAGE, "PIOCLUSAGE", "get resource usage of all lwps" }, 16798944Sobrien { PIOCOPENLWP, "PIOCOPENLWP", "get lwp file descriptor" }, 16898944Sobrien { PIOCLWPIDS, "PIOCLWPIDS", "get lwp identifiers" }, 16998944Sobrien#endif /* LWP */ 17098944Sobrien { PIOCMAP, "PIOCMAP", "get memory map information" }, 17198944Sobrien { PIOCMAXSIG, "PIOCMAXSIG", "get max signal number" }, 17298944Sobrien { PIOCNICE, "PIOCNICE", "set nice priority" }, 17398944Sobrien { PIOCNMAP, "PIOCNMAP", "get number of memory mappings" }, 17498944Sobrien { PIOCOPENM, "PIOCOPENM", "open mapped object for reading" }, 17598944Sobrien#ifdef PIOCOPENMOBS /* osf */ 17698944Sobrien { PIOCOPENMOBS, "PIOCOPENMOBS", "open mapped object" }, 17798944Sobrien#endif 17898944Sobrien#ifdef PIOCOPENPD /* solaris */ 17998944Sobrien { PIOCOPENPD, "PIOCOPENPD", "get page data file descriptor" }, 18098944Sobrien#endif 18198944Sobrien { PIOCPSINFO, "PIOCPSINFO", "get ps(1) information" }, 18298944Sobrien { PIOCRESET, "PIOCRESET", "reset process flags" }, 18398944Sobrien { PIOCRFORK, "PIOCRFORK", "reset inherit-on-fork flag" }, 18498944Sobrien { PIOCRRLC, "PIOCRRLC", "reset run-on-last-close flag" }, 18598944Sobrien { PIOCRUN, "PIOCRUN", "make process runnable" }, 18698944Sobrien#ifdef PIOCSAVECCNTRS /* irix */ 18798944Sobrien { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" }, 18898944Sobrien#endif 18998944Sobrien { PIOCSENTRY, "PIOCSENTRY", "set traced syscall entry set" }, 19098944Sobrien { PIOCSET, "PIOCSET", "set process flags" }, 19198944Sobrien { PIOCSEXIT, "PIOCSEXIT", "set traced syscall exit set" }, 19298944Sobrien { PIOCSFAULT, "PIOCSFAULT", "set traced fault set" }, 19398944Sobrien { PIOCSFORK, "PIOCSFORK", "set inherit-on-fork flag" }, 19498944Sobrien { PIOCSFPREG, "PIOCSFPREG", "set floating point registers" }, 19598944Sobrien { PIOCSHOLD, "PIOCSHOLD", "set held signal set" }, 19698944Sobrien { PIOCSREG, "PIOCSREG", "set general registers" }, 19798944Sobrien { PIOCSRLC, "PIOCSRLC", "set run-on-last-close flag" }, 19898944Sobrien { PIOCSSIG, "PIOCSSIG", "set current signal" }, 19998944Sobrien { PIOCSTATUS, "PIOCSTATUS", "get process status" }, 20098944Sobrien { PIOCSTOP, "PIOCSTOP", "post stop request" }, 20198944Sobrien { PIOCSTRACE, "PIOCSTRACE", "set traced signal set" }, 20298944Sobrien { PIOCUNKILL, "PIOCUNKILL", "delete a signal" }, 20398944Sobrien#ifdef PIOCUSAGE /* solaris */ 20498944Sobrien { PIOCUSAGE, "PIOCUSAGE", "get resource usage" }, 20598944Sobrien#endif 20698944Sobrien { PIOCWSTOP, "PIOCWSTOP", "wait for process to stop" }, 20798944Sobrien 20898944Sobrien#ifdef PIOCNTHR /* osf threads */ 20998944Sobrien { PIOCNTHR, "PIOCNTHR", "get thread count" }, 21098944Sobrien { PIOCRTINH, "PIOCRTINH", "reset inherit-on-thread-creation" }, 21198944Sobrien { PIOCSTINH, "PIOCSTINH", "set inherit-on-thread-creation" }, 21298944Sobrien { PIOCTLIST, "PIOCTLIST", "get thread ids" }, 21398944Sobrien { PIOCXPTH, "PIOCXPTH", "translate port to thread handle" }, 21498944Sobrien { PIOCTRUN, "PIOCTRUN", "make thread runnable" }, 21598944Sobrien { PIOCTSTATUS, "PIOCTSTATUS", "get thread status" }, 21698944Sobrien { PIOCTSTOP, "PIOCTSTOP", "stop a thread" }, 21798944Sobrien /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT 21898944Sobrien TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY 21998944Sobrien TGEXIT TSEXIT TSHOLD ... thread functions */ 22098944Sobrien#endif /* osf threads */ 22198944Sobrien { -1, NULL, NULL } 22298944Sobrien}; 22398944Sobrien 22498944Sobrienint 22598944Sobrienioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line) 22698944Sobrien{ 22798944Sobrien int i = 0; 22898944Sobrien int ret; 22998944Sobrien int arg1; 23098944Sobrien 23198944Sobrien prepare_to_trace (); 23298944Sobrien 23398944Sobrien if (procfs_trace) 23498944Sobrien { 23598944Sobrien for (i = 0; ioctl_table[i].name != NULL; i++) 23698944Sobrien if (ioctl_table[i].value == opcode) 23798944Sobrien break; 23898944Sobrien 23998944Sobrien if (info_verbose) 24098944Sobrien fprintf (procfs_file ? procfs_file : stdout, 24198944Sobrien "%s:%d -- ", file, line); 24298944Sobrien switch (opcode) { 24398944Sobrien case PIOCSET: 24498944Sobrien arg1 = ptr ? *(long *) ptr : 0; 24598944Sobrien fprintf (procfs_file ? procfs_file : stdout, 24698944Sobrien "ioctl (PIOCSET, %s) %s\n", 24798944Sobrien arg1 == PR_FORK ? "PR_FORK" : 24898944Sobrien arg1 == PR_RLC ? "PR_RLC" : 24998944Sobrien#ifdef PR_ASYNC 25098944Sobrien arg1 == PR_ASYNC ? "PR_ASYNC" : 25198944Sobrien#endif 25298944Sobrien "<unknown flag>", 25398944Sobrien info_verbose ? ioctl_table[i].desc : ""); 25498944Sobrien break; 25598944Sobrien case PIOCRESET: 25698944Sobrien arg1 = ptr ? *(long *) ptr : 0; 25798944Sobrien fprintf (procfs_file ? procfs_file : stdout, 25898944Sobrien "ioctl (PIOCRESET, %s) %s\n", 25998944Sobrien arg1 == PR_FORK ? "PR_FORK" : 26098944Sobrien arg1 == PR_RLC ? "PR_RLC" : 26198944Sobrien#ifdef PR_ASYNC 26298944Sobrien arg1 == PR_ASYNC ? "PR_ASYNC" : 26398944Sobrien#endif 26498944Sobrien "<unknown flag>", 26598944Sobrien info_verbose ? ioctl_table[i].desc : ""); 26698944Sobrien break; 26798944Sobrien case PIOCSTRACE: 26898944Sobrien fprintf (procfs_file ? procfs_file : stdout, 26998944Sobrien "ioctl (PIOCSTRACE) "); 27098944Sobrien proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 27198944Sobrien (sigset_t *) ptr, 0); 27298944Sobrien break; 27398944Sobrien case PIOCSFAULT: 27498944Sobrien fprintf (procfs_file ? procfs_file : stdout, 27598944Sobrien "ioctl (%s) ", 27698944Sobrien opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT"); 27798944Sobrien proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout, 27898944Sobrien (fltset_t *) ptr, 0); 27998944Sobrien break; 28098944Sobrien case PIOCSENTRY: 28198944Sobrien fprintf (procfs_file ? procfs_file : stdout, 28298944Sobrien "ioctl (%s) ", 28398944Sobrien opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY"); 28498944Sobrien proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 28598944Sobrien (sysset_t *) ptr, 0); 28698944Sobrien break; 28798944Sobrien case PIOCSEXIT: 28898944Sobrien fprintf (procfs_file ? procfs_file : stdout, 28998944Sobrien "ioctl (%s) ", 29098944Sobrien opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT"); 29198944Sobrien proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 29298944Sobrien (sysset_t *) ptr, 0); 29398944Sobrien break; 29498944Sobrien case PIOCSHOLD: 29598944Sobrien fprintf (procfs_file ? procfs_file : stdout, 29698944Sobrien "ioctl (%s) ", 29798944Sobrien opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD"); 29898944Sobrien proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 29998944Sobrien (sigset_t *) ptr, 0); 30098944Sobrien break; 30198944Sobrien case PIOCSSIG: 30298944Sobrien fprintf (procfs_file ? procfs_file : stdout, 30398944Sobrien "ioctl (PIOCSSIG) "); 30498944Sobrien proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 30598944Sobrien ptr ? ((siginfo_t *) ptr)->si_signo : 0, 30698944Sobrien 0); 30798944Sobrien fprintf (procfs_file ? procfs_file : stdout, "\n"); 30898944Sobrien break; 30998944Sobrien case PIOCRUN: 31098944Sobrien fprintf (procfs_file ? procfs_file : stdout, 31198944Sobrien "ioctl (PIOCRUN) "); 31298944Sobrien 31398944Sobrien arg1 = ptr ? *(long *) ptr : 0; 31498944Sobrien if (arg1 & PRCSIG) 31598944Sobrien fprintf (procfs_file ? procfs_file : stdout, "clearSig "); 31698944Sobrien if (arg1 & PRCFAULT) 31798944Sobrien fprintf (procfs_file ? procfs_file : stdout, "clearFlt "); 31898944Sobrien if (arg1 & PRSTRACE) 31998944Sobrien fprintf (procfs_file ? procfs_file : stdout, "setTrace "); 32098944Sobrien if (arg1 & PRSHOLD) 32198944Sobrien fprintf (procfs_file ? procfs_file : stdout, "setHold "); 32298944Sobrien if (arg1 & PRSFAULT) 32398944Sobrien fprintf (procfs_file ? procfs_file : stdout, "setFlt "); 32498944Sobrien if (arg1 & PRSVADDR) 32598944Sobrien fprintf (procfs_file ? procfs_file : stdout, "setVaddr "); 32698944Sobrien if (arg1 & PRSTEP) 32798944Sobrien fprintf (procfs_file ? procfs_file : stdout, "step "); 32898944Sobrien if (arg1 & PRSABORT) 32998944Sobrien fprintf (procfs_file ? procfs_file : stdout, "syscallAbort "); 33098944Sobrien if (arg1 & PRSTOP) 33198944Sobrien fprintf (procfs_file ? procfs_file : stdout, "stopReq "); 33298944Sobrien 33398944Sobrien fprintf (procfs_file ? procfs_file : stdout, "\n"); 33498944Sobrien break; 33598944Sobrien case PIOCKILL: 33698944Sobrien fprintf (procfs_file ? procfs_file : stdout, 33798944Sobrien "ioctl (PIOCKILL) "); 33898944Sobrien proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 33998944Sobrien ptr ? *(long *) ptr : 0, 0); 34098944Sobrien fprintf (procfs_file ? procfs_file : stdout, "\n"); 34198944Sobrien break; 34298944Sobrien#ifdef PIOCSSPCACT 34398944Sobrien case PIOCSSPCACT: 34498944Sobrien fprintf (procfs_file ? procfs_file : stdout, 34598944Sobrien "ioctl (PIOCSSPCACT) "); 34698944Sobrien arg1 = ptr ? *(long *) ptr : 0; 34798944Sobrien if (arg1 & PRFS_STOPFORK) 34898944Sobrien fprintf (procfs_file ? procfs_file : stdout, "stopFork "); 34998944Sobrien if (arg1 & PRFS_STOPEXEC) 35098944Sobrien fprintf (procfs_file ? procfs_file : stdout, "stopExec "); 35198944Sobrien if (arg1 & PRFS_STOPTERM) 35298944Sobrien fprintf (procfs_file ? procfs_file : stdout, "stopTerm "); 35398944Sobrien if (arg1 & PRFS_STOPTCR) 35498944Sobrien fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate "); 35598944Sobrien if (arg1 & PRFS_STOPTTERM) 35698944Sobrien fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm "); 35798944Sobrien if (arg1 & PRFS_KOLC) 35898944Sobrien fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose "); 35998944Sobrien fprintf (procfs_file ? procfs_file : stdout, "\n"); 36098944Sobrien break; 36198944Sobrien#endif /* PIOCSSPCACT */ 36298944Sobrien default: 36398944Sobrien if (ioctl_table[i].name) 36498944Sobrien fprintf (procfs_file ? procfs_file : stdout, 36598944Sobrien "ioctl (%s) %s\n", 36698944Sobrien ioctl_table[i].name, 36798944Sobrien info_verbose ? ioctl_table[i].desc : ""); 36898944Sobrien else 36998944Sobrien fprintf (procfs_file ? procfs_file : stdout, 37098944Sobrien "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode); 37198944Sobrien break; 37298944Sobrien } 37398944Sobrien if (procfs_file) 37498944Sobrien fflush (procfs_file); 37598944Sobrien } 37698944Sobrien errno = 0; 37798944Sobrien ret = ioctl (fd, opcode, ptr); 37898944Sobrien if (procfs_trace && ret < 0) 37998944Sobrien { 38098944Sobrien fprintf (procfs_file ? procfs_file : stdout, 38198944Sobrien "[ioctl (%s) FAILED! (%s)]\n", 38298944Sobrien ioctl_table[i].name != NULL ? 38398944Sobrien ioctl_table[i].name : "<unknown>", 38498944Sobrien safe_strerror (errno)); 38598944Sobrien if (procfs_file) 38698944Sobrien fflush (procfs_file); 38798944Sobrien } 38898944Sobrien 38998944Sobrien return ret; 39098944Sobrien} 39198944Sobrien 39298944Sobrien#else /* NEW_PROC_API */ 39398944Sobrien 39498944Sobrienstatic struct trans rw_table[] = { 39598944Sobrien#ifdef PCAGENT /* solaris */ 39698944Sobrien { PCAGENT, "PCAGENT", "create agent lwp with regs from argument" }, 39798944Sobrien#endif 39898944Sobrien { PCCFAULT, "PCCFAULT", "clear current fault" }, 39998944Sobrien#ifdef PCCSIG /* solaris */ 40098944Sobrien { PCCSIG, "PCCSIG", "clear current signal" }, 40198944Sobrien#endif 402130803Smarcel#ifdef PCDSTOP /* solaris */ 40398944Sobrien { PCDSTOP, "PCDSTOP", "post stop request" }, 404130803Smarcel#endif 40598944Sobrien { PCKILL, "PCKILL", "post a signal" }, 406130803Smarcel#ifdef PCNICE /* solaris */ 40798944Sobrien { PCNICE, "PCNICE", "set nice priority" }, 408130803Smarcel#endif 40998944Sobrien#ifdef PCREAD /* solaris */ 41098944Sobrien { PCREAD, "PCREAD", "read from the address space" }, 41198944Sobrien { PCWRITE, "PCWRITE", "write to the address space" }, 41298944Sobrien#endif 41398944Sobrien#ifdef PCRESET /* unixware */ 41498944Sobrien { PCRESET, "PCRESET", "unset modes" }, 41598944Sobrien#endif 41698944Sobrien { PCRUN, "PCRUN", "make process/lwp runnable" }, 41798944Sobrien#ifdef PCSASRS /* solaris 2.7 only */ 41898944Sobrien { PCSASRS, "PCSASRS", "set ancillary state registers" }, 41998944Sobrien#endif 42098944Sobrien#ifdef PCSCRED /* solaris */ 42198944Sobrien { PCSCRED, "PCSCRED", "set process credentials" }, 42298944Sobrien#endif 42398944Sobrien { PCSENTRY, "PCSENTRY", "set traced syscall entry set" }, 42498944Sobrien { PCSET, "PCSET", "set modes" }, 42598944Sobrien { PCSEXIT, "PCSEXIT", "set traced syscall exit set" }, 42698944Sobrien { PCSFAULT, "PCSFAULT", "set traced fault set" }, 42798944Sobrien { PCSFPREG, "PCSFPREG", "set floating point registers" }, 428130803Smarcel#ifdef PCSHOLD /* solaris */ 42998944Sobrien { PCSHOLD, "PCSHOLD", "set signal mask" }, 430130803Smarcel#endif 43198944Sobrien { PCSREG, "PCSREG", "set general registers" }, 43298944Sobrien { PCSSIG, "PCSSIG", "set current signal" }, 43398944Sobrien { PCSTOP, "PCSTOP", "post stop request and wait" }, 43498944Sobrien { PCSTRACE, "PCSTRACE", "set traced signal set" }, 43598944Sobrien#ifdef PCSVADDR /* solaris */ 43698944Sobrien { PCSVADDR, "PCSVADDR", "set pc virtual address" }, 43798944Sobrien#endif 43898944Sobrien#ifdef PCSXREG /* solaris sparc only */ 43998944Sobrien { PCSXREG, "PCSXREG", "set extra registers" }, 44098944Sobrien#endif 44198944Sobrien#ifdef PCTWSTOP /* solaris */ 44298944Sobrien { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" }, 44398944Sobrien#endif 444130803Smarcel#ifdef PCUNKILL /* solaris */ 44598944Sobrien { PCUNKILL, "PCUNKILL", "delete a pending signal" }, 446130803Smarcel#endif 44798944Sobrien#ifdef PCUNSET /* solaris */ 44898944Sobrien { PCUNSET, "PCUNSET", "unset modes" }, 44998944Sobrien#endif 45098944Sobrien#ifdef PCWATCH /* solaris */ 45198944Sobrien { PCWATCH, "PCWATCH", "set/unset watched memory area" }, 45298944Sobrien#endif 45398944Sobrien { PCWSTOP, "PCWSTOP", "wait for process/lwp to stop, no timeout" }, 45498944Sobrien { 0, NULL, NULL } 45598944Sobrien}; 45698944Sobrien 45798944Sobrienstatic off_t lseek_offset; 45898944Sobrien 45998944Sobrienint 46098944Sobrienwrite_with_trace (int fd, void *varg, size_t len, char *file, int line) 46198944Sobrien{ 462130803Smarcel int i = ARRAY_SIZE (rw_table) - 1; 46398944Sobrien int ret; 46498944Sobrien procfs_ctl_t *arg = (procfs_ctl_t *) varg; 46598944Sobrien 46698944Sobrien prepare_to_trace (); 46798944Sobrien if (procfs_trace) 46898944Sobrien { 46998944Sobrien procfs_ctl_t opcode = arg[0]; 47098944Sobrien for (i = 0; rw_table[i].name != NULL; i++) 47198944Sobrien if (rw_table[i].value == opcode) 47298944Sobrien break; 47398944Sobrien 47498944Sobrien if (info_verbose) 47598944Sobrien fprintf (procfs_file ? procfs_file : stdout, 47698944Sobrien "%s:%d -- ", file, line); 47798944Sobrien switch (opcode) { 47898944Sobrien case PCSET: 47998944Sobrien fprintf (procfs_file ? procfs_file : stdout, 48098944Sobrien "write (PCSET, %s) %s\n", 48198944Sobrien arg[1] == PR_FORK ? "PR_FORK" : 48298944Sobrien arg[1] == PR_RLC ? "PR_RLC" : 48398944Sobrien#ifdef PR_ASYNC 48498944Sobrien arg[1] == PR_ASYNC ? "PR_ASYNC" : 48598944Sobrien#endif 48698944Sobrien "<unknown flag>", 48798944Sobrien info_verbose ? rw_table[i].desc : ""); 48898944Sobrien break; 48998944Sobrien#ifdef PCUNSET 49098944Sobrien case PCUNSET: 49198944Sobrien#endif 49298944Sobrien#ifdef PCRESET 49398944Sobrien#if PCRESET != PCUNSET 49498944Sobrien case PCRESET: 49598944Sobrien#endif 49698944Sobrien#endif 49798944Sobrien fprintf (procfs_file ? procfs_file : stdout, 49898944Sobrien "write (PCRESET, %s) %s\n", 49998944Sobrien arg[1] == PR_FORK ? "PR_FORK" : 50098944Sobrien arg[1] == PR_RLC ? "PR_RLC" : 50198944Sobrien#ifdef PR_ASYNC 50298944Sobrien arg[1] == PR_ASYNC ? "PR_ASYNC" : 50398944Sobrien#endif 50498944Sobrien "<unknown flag>", 50598944Sobrien info_verbose ? rw_table[i].desc : ""); 50698944Sobrien break; 50798944Sobrien case PCSTRACE: 50898944Sobrien fprintf (procfs_file ? procfs_file : stdout, 50998944Sobrien "write (PCSTRACE) "); 51098944Sobrien proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 51198944Sobrien (sigset_t *) &arg[1], 0); 51298944Sobrien break; 51398944Sobrien case PCSFAULT: 51498944Sobrien fprintf (procfs_file ? procfs_file : stdout, 51598944Sobrien "write (PCSFAULT) "); 51698944Sobrien proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout, 51798944Sobrien (fltset_t *) &arg[1], 0); 51898944Sobrien break; 51998944Sobrien case PCSENTRY: 52098944Sobrien fprintf (procfs_file ? procfs_file : stdout, 52198944Sobrien "write (PCSENTRY) "); 52298944Sobrien proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 52398944Sobrien (sysset_t *) &arg[1], 0); 52498944Sobrien break; 52598944Sobrien case PCSEXIT: 52698944Sobrien fprintf (procfs_file ? procfs_file : stdout, 52798944Sobrien "write (PCSEXIT) "); 52898944Sobrien proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 52998944Sobrien (sysset_t *) &arg[1], 0); 53098944Sobrien break; 531130803Smarcel#ifdef PCSHOLD 53298944Sobrien case PCSHOLD: 53398944Sobrien fprintf (procfs_file ? procfs_file : stdout, 53498944Sobrien "write (PCSHOLD) "); 53598944Sobrien proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 53698944Sobrien (sigset_t *) &arg[1], 0); 53798944Sobrien break; 538130803Smarcel#endif 53998944Sobrien case PCSSIG: 54098944Sobrien fprintf (procfs_file ? procfs_file : stdout, 54198944Sobrien "write (PCSSIG) "); 54298944Sobrien proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 54398944Sobrien arg[1] ? ((siginfo_t *) &arg[1])->si_signo 54498944Sobrien : 0, 54598944Sobrien 0); 54698944Sobrien fprintf (procfs_file ? procfs_file : stdout, "\n"); 54798944Sobrien break; 54898944Sobrien case PCRUN: 54998944Sobrien fprintf (procfs_file ? procfs_file : stdout, 55098944Sobrien "write (PCRUN) "); 55198944Sobrien if (arg[1] & PRCSIG) 55298944Sobrien fprintf (procfs_file ? procfs_file : stdout, "clearSig "); 55398944Sobrien if (arg[1] & PRCFAULT) 55498944Sobrien fprintf (procfs_file ? procfs_file : stdout, "clearFlt "); 55598944Sobrien if (arg[1] & PRSTEP) 55698944Sobrien fprintf (procfs_file ? procfs_file : stdout, "step "); 557130803Smarcel#ifdef PRSABORT 55898944Sobrien if (arg[1] & PRSABORT) 55998944Sobrien fprintf (procfs_file ? procfs_file : stdout, "syscallAbort "); 560130803Smarcel#endif 561130803Smarcel#ifdef PRSTOP 56298944Sobrien if (arg[1] & PRSTOP) 56398944Sobrien fprintf (procfs_file ? procfs_file : stdout, "stopReq "); 564130803Smarcel#endif 56598944Sobrien 56698944Sobrien fprintf (procfs_file ? procfs_file : stdout, "\n"); 56798944Sobrien break; 56898944Sobrien case PCKILL: 56998944Sobrien fprintf (procfs_file ? procfs_file : stdout, 57098944Sobrien "write (PCKILL) "); 57198944Sobrien proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 57298944Sobrien arg[1], 0); 57398944Sobrien fprintf (procfs_file ? procfs_file : stdout, "\n"); 57498944Sobrien break; 57598944Sobrien default: 57698944Sobrien { 57798944Sobrien if (rw_table[i].name) 57898944Sobrien fprintf (procfs_file ? procfs_file : stdout, 57998944Sobrien "write (%s) %s\n", 58098944Sobrien rw_table[i].name, 58198944Sobrien info_verbose ? rw_table[i].desc : ""); 58298944Sobrien else 58398944Sobrien { 58498944Sobrien if (lseek_offset != -1) 58598944Sobrien fprintf (procfs_file ? procfs_file : stdout, 58698944Sobrien "write (<unknown>, %lud bytes at 0x%08lx) \n", 58798944Sobrien (unsigned long) len, (unsigned long) lseek_offset); 58898944Sobrien else 58998944Sobrien fprintf (procfs_file ? procfs_file : stdout, 59098944Sobrien "write (<unknown>, %lud bytes) \n", 59198944Sobrien (unsigned long) len); 59298944Sobrien } 59398944Sobrien break; 59498944Sobrien } 59598944Sobrien } 59698944Sobrien if (procfs_file) 59798944Sobrien fflush (procfs_file); 59898944Sobrien } 59998944Sobrien errno = 0; 60098944Sobrien ret = write (fd, (void *) arg, len); 60198944Sobrien if (procfs_trace && ret != len) 60298944Sobrien { 60398944Sobrien fprintf (procfs_file ? procfs_file : stdout, 60498944Sobrien "[write (%s) FAILED! (%s)]\n", 60598944Sobrien rw_table[i].name != NULL ? 60698944Sobrien rw_table[i].name : "<unknown>", 60798944Sobrien safe_strerror (errno)); 60898944Sobrien if (procfs_file) 60998944Sobrien fflush (procfs_file); 61098944Sobrien } 61198944Sobrien 61298944Sobrien lseek_offset = -1; 61398944Sobrien return ret; 61498944Sobrien} 61598944Sobrien 61698944Sobrienoff_t 61798944Sobrienlseek_with_trace (int fd, off_t offset, int whence, char *file, int line) 61898944Sobrien{ 61998944Sobrien off_t ret; 62098944Sobrien 62198944Sobrien prepare_to_trace (); 62298944Sobrien errno = 0; 62398944Sobrien ret = lseek (fd, offset, whence); 62498944Sobrien lseek_offset = ret; 62598944Sobrien if (procfs_trace && (ret == -1 || errno != 0)) 62698944Sobrien { 62798944Sobrien fprintf (procfs_file ? procfs_file : stdout, 62898944Sobrien "[lseek (0x%08lx) FAILED! (%s)]\n", 62998944Sobrien (unsigned long) offset, safe_strerror (errno)); 63098944Sobrien if (procfs_file) 63198944Sobrien fflush (procfs_file); 63298944Sobrien } 63398944Sobrien 63498944Sobrien return ret; 63598944Sobrien} 63698944Sobrien 63798944Sobrien#endif /* NEW_PROC_API */ 63898944Sobrien 63998944Sobrienint 64098944Sobrienopen_with_trace (char *filename, int mode, char *file, int line) 64198944Sobrien{ 64298944Sobrien int ret; 64398944Sobrien 64498944Sobrien prepare_to_trace (); 64598944Sobrien errno = 0; 64698944Sobrien ret = open (filename, mode); 64798944Sobrien if (procfs_trace) 64898944Sobrien { 64998944Sobrien if (info_verbose) 65098944Sobrien fprintf (procfs_file ? procfs_file : stdout, 65198944Sobrien "%s:%d -- ", file, line); 65298944Sobrien 65398944Sobrien if (errno) 65498944Sobrien { 65598944Sobrien fprintf (procfs_file ? procfs_file : stdout, 65698944Sobrien "[open FAILED! (%s) line %d]\\n", 65798944Sobrien safe_strerror (errno), line); 65898944Sobrien } 65998944Sobrien else 66098944Sobrien { 66198944Sobrien fprintf (procfs_file ? procfs_file : stdout, 66298944Sobrien "%d = open (%s, ", ret, filename); 66398944Sobrien if (mode == O_RDONLY) 66498944Sobrien fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n", 66598944Sobrien line); 66698944Sobrien else if (mode == O_WRONLY) 66798944Sobrien fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n", 66898944Sobrien line); 66998944Sobrien else if (mode == O_RDWR) 67098944Sobrien fprintf (procfs_file ? procfs_file : stdout, "O_RDWR) %d\n", 67198944Sobrien line); 67298944Sobrien } 67398944Sobrien if (procfs_file) 67498944Sobrien fflush (procfs_file); 67598944Sobrien } 67698944Sobrien 67798944Sobrien return ret; 67898944Sobrien} 67998944Sobrien 68098944Sobrienint 68198944Sobrienclose_with_trace (int fd, char *file, int line) 68298944Sobrien{ 68398944Sobrien int ret; 68498944Sobrien 68598944Sobrien prepare_to_trace (); 68698944Sobrien errno = 0; 68798944Sobrien ret = close (fd); 68898944Sobrien if (procfs_trace) 68998944Sobrien { 69098944Sobrien if (info_verbose) 69198944Sobrien fprintf (procfs_file ? procfs_file : stdout, 69298944Sobrien "%s:%d -- ", file, line); 69398944Sobrien if (errno) 69498944Sobrien fprintf (procfs_file ? procfs_file : stdout, 69598944Sobrien "[close FAILED! (%s)]\n", safe_strerror (errno)); 69698944Sobrien else 69798944Sobrien fprintf (procfs_file ? procfs_file : stdout, 69898944Sobrien "%d = close (%d)\n", ret, fd); 69998944Sobrien if (procfs_file) 70098944Sobrien fflush (procfs_file); 70198944Sobrien } 70298944Sobrien 70398944Sobrien return ret; 70498944Sobrien} 70598944Sobrien 70698944Sobrienpid_t 70798944Sobrienwait_with_trace (int *wstat, char *file, int line) 70898944Sobrien{ 70998944Sobrien int ret, lstat = 0; 71098944Sobrien 71198944Sobrien prepare_to_trace (); 71298944Sobrien if (procfs_trace) 71398944Sobrien { 71498944Sobrien if (info_verbose) 71598944Sobrien fprintf (procfs_file ? procfs_file : stdout, 71698944Sobrien "%s:%d -- ", file, line); 71798944Sobrien fprintf (procfs_file ? procfs_file : stdout, 71898944Sobrien "wait (line %d) ", line); 71998944Sobrien if (procfs_file) 72098944Sobrien fflush (procfs_file); 72198944Sobrien } 72298944Sobrien errno = 0; 72398944Sobrien ret = wait (&lstat); 72498944Sobrien if (procfs_trace) 72598944Sobrien { 72698944Sobrien if (errno) 72798944Sobrien fprintf (procfs_file ? procfs_file : stdout, 72898944Sobrien "[wait FAILED! (%s)]\n", safe_strerror (errno)); 72998944Sobrien else 73098944Sobrien fprintf (procfs_file ? procfs_file : stdout, 73198944Sobrien "returned pid %d, status 0x%x\n", ret, lstat); 73298944Sobrien if (procfs_file) 73398944Sobrien fflush (procfs_file); 73498944Sobrien } 73598944Sobrien if (wstat) 73698944Sobrien *wstat = lstat; 73798944Sobrien 73898944Sobrien return ret; 73998944Sobrien} 74098944Sobrien 74198944Sobrienvoid 74298944Sobrienprocfs_note (char *msg, char *file, int line) 74398944Sobrien{ 74498944Sobrien prepare_to_trace (); 74598944Sobrien if (procfs_trace) 74698944Sobrien { 74798944Sobrien if (info_verbose) 74898944Sobrien fprintf (procfs_file ? procfs_file : stdout, 74998944Sobrien "%s:%d -- ", file, line); 750130803Smarcel fprintf (procfs_file ? procfs_file : stdout, "%s", msg); 75198944Sobrien if (procfs_file) 75298944Sobrien fflush (procfs_file); 75398944Sobrien } 75498944Sobrien} 75598944Sobrien 75698944Sobrienvoid 75798944Sobrienproc_prettyfprint_status (long flags, int why, int what, int thread) 75898944Sobrien{ 75998944Sobrien prepare_to_trace (); 76098944Sobrien if (procfs_trace) 76198944Sobrien { 76298944Sobrien if (thread) 76398944Sobrien fprintf (procfs_file ? procfs_file : stdout, 76498944Sobrien "Thread %d: ", thread); 76598944Sobrien 76698944Sobrien proc_prettyfprint_flags (procfs_file ? procfs_file : stdout, 76798944Sobrien flags, 0); 76898944Sobrien 76998944Sobrien if (flags & (PR_STOPPED | PR_ISTOP)) 77098944Sobrien proc_prettyfprint_why (procfs_file ? procfs_file : stdout, 77198944Sobrien why, what, 0); 77298944Sobrien if (procfs_file) 77398944Sobrien fflush (procfs_file); 77498944Sobrien } 77598944Sobrien} 77698944Sobrien 77798944Sobrien 77898944Sobrienvoid 77998944Sobrien_initialize_proc_api (void) 78098944Sobrien{ 78198944Sobrien struct cmd_list_element *c; 78298944Sobrien 78398944Sobrien c = add_set_cmd ("procfs-trace", no_class, 78498944Sobrien var_boolean, (char *) &procfs_trace, 78598944Sobrien "Set tracing for /proc api calls.\n", &setlist); 78698944Sobrien 78798944Sobrien add_show_from_set (c, &showlist); 78898944Sobrien set_cmd_sfunc (c, set_procfs_trace_cmd); 789130803Smarcel set_cmd_completer (c, filename_completer); 79098944Sobrien 79198944Sobrien c = add_set_cmd ("procfs-file", no_class, var_filename, 79298944Sobrien (char *) &procfs_filename, 79398944Sobrien "Set filename for /proc tracefile.\n", &setlist); 79498944Sobrien 79598944Sobrien add_show_from_set (c, &showlist); 79698944Sobrien set_cmd_sfunc (c, set_procfs_file_cmd); 79798944Sobrien} 798