GDB (API)
|
00001 /* Machine independent support for SVR4 /proc (process file system) for GDB. 00002 00003 Copyright (C) 1999-2013 Free Software Foundation, Inc. 00004 00005 Written by Michael Snyder at Cygnus Solutions. 00006 Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others. 00007 00008 This file is part of GDB. 00009 00010 This program is free software; you can redistribute it and/or modify 00011 it under the terms of the GNU General Public License as published by 00012 the Free Software Foundation; either version 3 of the License, or 00013 (at your option) any later version. 00014 00015 This program is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00022 00023 /* 00024 * Pretty-print trace of api calls to the /proc api 00025 * (ioctl or read/write calls). 00026 * 00027 */ 00028 00029 #include "defs.h" 00030 #include "gdbcmd.h" 00031 #include "completer.h" 00032 00033 #if defined (NEW_PROC_API) 00034 #define _STRUCTURED_PROC 1 00035 #endif 00036 00037 #include <stdio.h> 00038 #include <sys/types.h> 00039 #include <sys/procfs.h> 00040 #ifdef HAVE_SYS_PROC_H 00041 #include <sys/proc.h> /* for struct proc */ 00042 #endif 00043 #ifdef HAVE_SYS_USER_H 00044 #include <sys/user.h> /* for struct user */ 00045 #endif 00046 #include <fcntl.h> /* for O_RDWR etc. */ 00047 #include "gdb_wait.h" 00048 00049 #include "proc-utils.h" 00050 00051 /* Much of the information used in the /proc interface, particularly for 00052 printing status information, is kept as tables of structures of the 00053 following form. These tables can be used to map numeric values to 00054 their symbolic names and to a string that describes their specific use. */ 00055 00056 struct trans { 00057 long value; /* The numeric value */ 00058 char *name; /* The equivalent symbolic value */ 00059 char *desc; /* Short description of value */ 00060 }; 00061 00062 static int procfs_trace = 0; 00063 static FILE *procfs_file = NULL; 00064 static char *procfs_filename = "procfs_trace"; 00065 00066 static void 00067 prepare_to_trace (void) 00068 { 00069 if (procfs_trace) /* if procfs tracing turned on */ 00070 if (procfs_file == NULL) /* if output file not yet open */ 00071 if (procfs_filename != NULL) /* if output filename known */ 00072 procfs_file = fopen (procfs_filename, "a"); /* open output file */ 00073 } 00074 00075 static void 00076 set_procfs_trace_cmd (char *args, int from_tty, struct cmd_list_element *c) 00077 { 00078 #if 0 /* not sure what I might actually need to do here, if anything */ 00079 if (procfs_file) 00080 fflush (procfs_file); 00081 #endif 00082 } 00083 00084 static void 00085 set_procfs_file_cmd (char *args, int from_tty, struct cmd_list_element *c) 00086 { 00087 /* Just changed the filename for procfs tracing. 00088 If a file was already open, close it. */ 00089 if (procfs_file) 00090 fclose (procfs_file); 00091 procfs_file = NULL; 00092 } 00093 00094 00095 #ifndef NEW_PROC_API 00096 00097 static struct trans ioctl_table[] = { 00098 #ifdef PIOCACINFO /* irix */ 00099 { PIOCACINFO, "PIOCACINFO", "get process account info" }, 00100 #endif 00101 { PIOCACTION, "PIOCACTION", "get signal action structs" }, 00102 #ifdef PIOCARGUMENTS /* osf */ 00103 { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" }, 00104 #endif 00105 #ifdef PIOCAUXV /* solaris aux vectors */ 00106 { PIOCAUXV, "PIOCAUXV", "get aux vector" }, 00107 { PIOCNAUXV, "PIOCNAUXV", "get number of aux vector entries" }, 00108 #endif /* AUXV */ 00109 { PIOCCFAULT, "PIOCCFAULT", "clear current fault" }, 00110 { PIOCCRED, "PIOCCRED", "get process credentials" }, 00111 #ifdef PIOCENEVCTRS /* irix event counters */ 00112 { PIOCENEVCTRS, "PIOCENEVCTRS", "acquire and start event counters" }, 00113 { PIOCGETEVCTRL, "PIOCGETEVCTRL", "get control info of event counters" }, 00114 { PIOCGETEVCTRS, "PIOCGETEVCTRS", "dump event counters" }, 00115 { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" }, 00116 { PIOCRELEVCTRS, "PIOCRELEVCTRS", "release/stop event counters" }, 00117 { PIOCSETEVCTRL, "PIOCSETEVCTRL", "set control info of event counters" }, 00118 { PIOCGETPTIMER, "PIOCGETPTIMER", "get process timers" }, 00119 #endif /* irix event counters */ 00120 { PIOCGENTRY, "PIOCGENTRY", "get traced syscall entry set" }, 00121 #if defined (PIOCGETPR) 00122 { PIOCGETPR, "PIOCGETPR", "read struct proc" }, 00123 #endif 00124 #if defined (PIOCGETU) 00125 { PIOCGETU, "PIOCGETU", "read user area" }, 00126 #endif 00127 #if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */ 00128 { PIOCGETUTK, "PIOCGETUTK", "get the utask struct" }, 00129 #endif 00130 { PIOCGEXIT, "PIOCGEXIT", "get traced syscall exit set" }, 00131 { PIOCGFAULT, "PIOCGFAULT", "get traced fault set" }, 00132 #ifdef PIOCGFPCR /* osf */ 00133 { PIOCGFPCR, "PIOCGFPCR", "get FP control register" }, 00134 { PIOCSFPCR, "PIOCSFPCR", "set FP conrtol register" }, 00135 #endif 00136 { PIOCGFPREG, "PIOCGFPREG", "get floating point registers" }, 00137 { PIOCGHOLD, "PIOCGHOLD", "get held signal set" }, 00138 { PIOCGREG, "PIOCGREG", "get general registers" }, 00139 { PIOCGROUPS, "PIOCGROUPS", "get supplementary groups" }, 00140 #ifdef PIOCGSPCACT /* osf */ 00141 { PIOCGSPCACT, "PIOCGSPCACT", "get special action" }, 00142 { PIOCSSPCACT, "PIOCSSPCACT", "set special action" }, 00143 #endif 00144 { PIOCGTRACE, "PIOCGTRACE", "get traced signal set" }, 00145 #ifdef PIOCGWATCH /* irix watchpoints */ 00146 { PIOCGWATCH, "PIOCGWATCH", "get watchpoint" }, 00147 { PIOCSWATCH, "PIOCSWATCH", "set watchpoint" }, 00148 { PIOCNWATCH, "PIOCNWATCH", "get number of watchpoints" }, 00149 #endif /* irix watchpoints */ 00150 #ifdef PIOCGWIN /* solaris sparc */ 00151 { PIOCGWIN, "PIOCGWIN", "get gwindows_t" }, 00152 #endif 00153 #ifdef PIOCGXREG /* solaris sparc extra regs */ 00154 { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" }, 00155 { PIOCGXREG, "PIOCGXREG", "get extra register state" }, 00156 { PIOCSXREG, "PIOCSXREG", "set extra register state" }, 00157 #endif /* XREG */ 00158 { PIOCKILL, "PIOCKILL", "send signal" }, 00159 #ifdef PIOCLDT /* solaris i386 */ 00160 { PIOCLDT, "PIOCLDT", "get LDT" }, 00161 { PIOCNLDT, "PIOCNLDT", "get number of LDT entries" }, 00162 #endif 00163 #ifdef PIOCLSTATUS /* solaris */ 00164 { PIOCLSTATUS, "PIOCLSTATUS", "get status of all lwps" }, 00165 { PIOCLUSAGE, "PIOCLUSAGE", "get resource usage of all lwps" }, 00166 { PIOCOPENLWP, "PIOCOPENLWP", "get lwp file descriptor" }, 00167 { PIOCLWPIDS, "PIOCLWPIDS", "get lwp identifiers" }, 00168 #endif /* LWP */ 00169 { PIOCMAP, "PIOCMAP", "get memory map information" }, 00170 { PIOCMAXSIG, "PIOCMAXSIG", "get max signal number" }, 00171 { PIOCNICE, "PIOCNICE", "set nice priority" }, 00172 { PIOCNMAP, "PIOCNMAP", "get number of memory mappings" }, 00173 { PIOCOPENM, "PIOCOPENM", "open mapped object for reading" }, 00174 #ifdef PIOCOPENMOBS /* osf */ 00175 { PIOCOPENMOBS, "PIOCOPENMOBS", "open mapped object" }, 00176 #endif 00177 #ifdef PIOCOPENPD /* solaris */ 00178 { PIOCOPENPD, "PIOCOPENPD", "get page data file descriptor" }, 00179 #endif 00180 { PIOCPSINFO, "PIOCPSINFO", "get ps(1) information" }, 00181 { PIOCRESET, "PIOCRESET", "reset process flags" }, 00182 { PIOCRFORK, "PIOCRFORK", "reset inherit-on-fork flag" }, 00183 { PIOCRRLC, "PIOCRRLC", "reset run-on-last-close flag" }, 00184 { PIOCRUN, "PIOCRUN", "make process runnable" }, 00185 #ifdef PIOCSAVECCNTRS /* irix */ 00186 { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" }, 00187 #endif 00188 { PIOCSENTRY, "PIOCSENTRY", "set traced syscall entry set" }, 00189 { PIOCSET, "PIOCSET", "set process flags" }, 00190 { PIOCSEXIT, "PIOCSEXIT", "set traced syscall exit set" }, 00191 { PIOCSFAULT, "PIOCSFAULT", "set traced fault set" }, 00192 { PIOCSFORK, "PIOCSFORK", "set inherit-on-fork flag" }, 00193 { PIOCSFPREG, "PIOCSFPREG", "set floating point registers" }, 00194 { PIOCSHOLD, "PIOCSHOLD", "set held signal set" }, 00195 { PIOCSREG, "PIOCSREG", "set general registers" }, 00196 { PIOCSRLC, "PIOCSRLC", "set run-on-last-close flag" }, 00197 { PIOCSSIG, "PIOCSSIG", "set current signal" }, 00198 { PIOCSTATUS, "PIOCSTATUS", "get process status" }, 00199 { PIOCSTOP, "PIOCSTOP", "post stop request" }, 00200 { PIOCSTRACE, "PIOCSTRACE", "set traced signal set" }, 00201 { PIOCUNKILL, "PIOCUNKILL", "delete a signal" }, 00202 #ifdef PIOCUSAGE /* solaris */ 00203 { PIOCUSAGE, "PIOCUSAGE", "get resource usage" }, 00204 #endif 00205 { PIOCWSTOP, "PIOCWSTOP", "wait for process to stop" }, 00206 00207 #ifdef PIOCNTHR /* osf threads */ 00208 { PIOCNTHR, "PIOCNTHR", "get thread count" }, 00209 { PIOCRTINH, "PIOCRTINH", "reset inherit-on-thread-creation" }, 00210 { PIOCSTINH, "PIOCSTINH", "set inherit-on-thread-creation" }, 00211 { PIOCTLIST, "PIOCTLIST", "get thread ids" }, 00212 { PIOCXPTH, "PIOCXPTH", "translate port to thread handle" }, 00213 { PIOCTRUN, "PIOCTRUN", "make thread runnable" }, 00214 { PIOCTSTATUS, "PIOCTSTATUS", "get thread status" }, 00215 { PIOCTSTOP, "PIOCTSTOP", "stop a thread" }, 00216 /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT 00217 TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY 00218 TGEXIT TSEXIT TSHOLD ... thread functions */ 00219 #endif /* osf threads */ 00220 { -1, NULL, NULL } 00221 }; 00222 00223 int 00224 ioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line) 00225 { 00226 int i = 0; 00227 int ret; 00228 int arg1; 00229 00230 prepare_to_trace (); 00231 00232 if (procfs_trace) 00233 { 00234 for (i = 0; ioctl_table[i].name != NULL; i++) 00235 if (ioctl_table[i].value == opcode) 00236 break; 00237 00238 if (info_verbose) 00239 fprintf (procfs_file ? procfs_file : stdout, 00240 "%s:%d -- ", file, line); 00241 switch (opcode) { 00242 case PIOCSET: 00243 arg1 = ptr ? *(long *) ptr : 0; 00244 fprintf (procfs_file ? procfs_file : stdout, 00245 "ioctl (PIOCSET, %s) %s\n", 00246 arg1 == PR_FORK ? "PR_FORK" : 00247 arg1 == PR_RLC ? "PR_RLC" : 00248 #ifdef PR_ASYNC 00249 arg1 == PR_ASYNC ? "PR_ASYNC" : 00250 #endif 00251 "<unknown flag>", 00252 info_verbose ? ioctl_table[i].desc : ""); 00253 break; 00254 case PIOCRESET: 00255 arg1 = ptr ? *(long *) ptr : 0; 00256 fprintf (procfs_file ? procfs_file : stdout, 00257 "ioctl (PIOCRESET, %s) %s\n", 00258 arg1 == PR_FORK ? "PR_FORK" : 00259 arg1 == PR_RLC ? "PR_RLC" : 00260 #ifdef PR_ASYNC 00261 arg1 == PR_ASYNC ? "PR_ASYNC" : 00262 #endif 00263 "<unknown flag>", 00264 info_verbose ? ioctl_table[i].desc : ""); 00265 break; 00266 case PIOCSTRACE: 00267 fprintf (procfs_file ? procfs_file : stdout, 00268 "ioctl (PIOCSTRACE) "); 00269 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 00270 (sigset_t *) ptr, 0); 00271 break; 00272 case PIOCSFAULT: 00273 fprintf (procfs_file ? procfs_file : stdout, 00274 "ioctl (%s) ", 00275 opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT"); 00276 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout, 00277 (fltset_t *) ptr, 0); 00278 break; 00279 case PIOCSENTRY: 00280 fprintf (procfs_file ? procfs_file : stdout, 00281 "ioctl (%s) ", 00282 opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY"); 00283 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 00284 (sysset_t *) ptr, 0); 00285 break; 00286 case PIOCSEXIT: 00287 fprintf (procfs_file ? procfs_file : stdout, 00288 "ioctl (%s) ", 00289 opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT"); 00290 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 00291 (sysset_t *) ptr, 0); 00292 break; 00293 case PIOCSHOLD: 00294 fprintf (procfs_file ? procfs_file : stdout, 00295 "ioctl (%s) ", 00296 opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD"); 00297 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 00298 (sigset_t *) ptr, 0); 00299 break; 00300 case PIOCSSIG: 00301 fprintf (procfs_file ? procfs_file : stdout, 00302 "ioctl (PIOCSSIG) "); 00303 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 00304 ptr ? ((siginfo_t *) ptr)->si_signo : 0, 00305 0); 00306 fprintf (procfs_file ? procfs_file : stdout, "\n"); 00307 break; 00308 case PIOCRUN: 00309 fprintf (procfs_file ? procfs_file : stdout, 00310 "ioctl (PIOCRUN) "); 00311 00312 arg1 = ptr ? *(long *) ptr : 0; 00313 if (arg1 & PRCSIG) 00314 fprintf (procfs_file ? procfs_file : stdout, "clearSig "); 00315 if (arg1 & PRCFAULT) 00316 fprintf (procfs_file ? procfs_file : stdout, "clearFlt "); 00317 if (arg1 & PRSTRACE) 00318 fprintf (procfs_file ? procfs_file : stdout, "setTrace "); 00319 if (arg1 & PRSHOLD) 00320 fprintf (procfs_file ? procfs_file : stdout, "setHold "); 00321 if (arg1 & PRSFAULT) 00322 fprintf (procfs_file ? procfs_file : stdout, "setFlt "); 00323 if (arg1 & PRSVADDR) 00324 fprintf (procfs_file ? procfs_file : stdout, "setVaddr "); 00325 if (arg1 & PRSTEP) 00326 fprintf (procfs_file ? procfs_file : stdout, "step "); 00327 if (arg1 & PRSABORT) 00328 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort "); 00329 if (arg1 & PRSTOP) 00330 fprintf (procfs_file ? procfs_file : stdout, "stopReq "); 00331 00332 fprintf (procfs_file ? procfs_file : stdout, "\n"); 00333 break; 00334 case PIOCKILL: 00335 fprintf (procfs_file ? procfs_file : stdout, 00336 "ioctl (PIOCKILL) "); 00337 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 00338 ptr ? *(long *) ptr : 0, 0); 00339 fprintf (procfs_file ? procfs_file : stdout, "\n"); 00340 break; 00341 #ifdef PIOCSSPCACT 00342 case PIOCSSPCACT: 00343 fprintf (procfs_file ? procfs_file : stdout, 00344 "ioctl (PIOCSSPCACT) "); 00345 arg1 = ptr ? *(long *) ptr : 0; 00346 if (arg1 & PRFS_STOPFORK) 00347 fprintf (procfs_file ? procfs_file : stdout, "stopFork "); 00348 if (arg1 & PRFS_STOPEXEC) 00349 fprintf (procfs_file ? procfs_file : stdout, "stopExec "); 00350 if (arg1 & PRFS_STOPTERM) 00351 fprintf (procfs_file ? procfs_file : stdout, "stopTerm "); 00352 if (arg1 & PRFS_STOPTCR) 00353 fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate "); 00354 if (arg1 & PRFS_STOPTTERM) 00355 fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm "); 00356 if (arg1 & PRFS_KOLC) 00357 fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose "); 00358 fprintf (procfs_file ? procfs_file : stdout, "\n"); 00359 break; 00360 #endif /* PIOCSSPCACT */ 00361 default: 00362 if (ioctl_table[i].name) 00363 fprintf (procfs_file ? procfs_file : stdout, 00364 "ioctl (%s) %s\n", 00365 ioctl_table[i].name, 00366 info_verbose ? ioctl_table[i].desc : ""); 00367 else 00368 fprintf (procfs_file ? procfs_file : stdout, 00369 "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode); 00370 break; 00371 } 00372 if (procfs_file) 00373 fflush (procfs_file); 00374 } 00375 errno = 0; 00376 ret = ioctl (fd, opcode, ptr); 00377 if (procfs_trace && ret < 0) 00378 { 00379 fprintf (procfs_file ? procfs_file : stdout, 00380 "[ioctl (%s) FAILED! (%s)]\n", 00381 ioctl_table[i].name != NULL ? 00382 ioctl_table[i].name : "<unknown>", 00383 safe_strerror (errno)); 00384 if (procfs_file) 00385 fflush (procfs_file); 00386 } 00387 00388 return ret; 00389 } 00390 00391 #else /* NEW_PROC_API */ 00392 00393 static struct trans rw_table[] = { 00394 #ifdef PCAGENT /* solaris */ 00395 { PCAGENT, "PCAGENT", "create agent lwp with regs from argument" }, 00396 #endif 00397 { PCCFAULT, "PCCFAULT", "clear current fault" }, 00398 #ifdef PCCSIG /* solaris */ 00399 { PCCSIG, "PCCSIG", "clear current signal" }, 00400 #endif 00401 #ifdef PCDSTOP /* solaris */ 00402 { PCDSTOP, "PCDSTOP", "post stop request" }, 00403 #endif 00404 { PCKILL, "PCKILL", "post a signal" }, 00405 #ifdef PCNICE /* solaris */ 00406 { PCNICE, "PCNICE", "set nice priority" }, 00407 #endif 00408 #ifdef PCREAD /* solaris */ 00409 { PCREAD, "PCREAD", "read from the address space" }, 00410 { PCWRITE, "PCWRITE", "write to the address space" }, 00411 #endif 00412 { PCRUN, "PCRUN", "make process/lwp runnable" }, 00413 #ifdef PCSASRS /* solaris 2.7 only */ 00414 { PCSASRS, "PCSASRS", "set ancillary state registers" }, 00415 #endif 00416 #ifdef PCSCRED /* solaris */ 00417 { PCSCRED, "PCSCRED", "set process credentials" }, 00418 #endif 00419 { PCSENTRY, "PCSENTRY", "set traced syscall entry set" }, 00420 { PCSET, "PCSET", "set modes" }, 00421 { PCSEXIT, "PCSEXIT", "set traced syscall exit set" }, 00422 { PCSFAULT, "PCSFAULT", "set traced fault set" }, 00423 { PCSFPREG, "PCSFPREG", "set floating point registers" }, 00424 #ifdef PCSHOLD /* solaris */ 00425 { PCSHOLD, "PCSHOLD", "set signal mask" }, 00426 #endif 00427 { PCSREG, "PCSREG", "set general registers" }, 00428 { PCSSIG, "PCSSIG", "set current signal" }, 00429 { PCSTOP, "PCSTOP", "post stop request and wait" }, 00430 { PCSTRACE, "PCSTRACE", "set traced signal set" }, 00431 #ifdef PCSVADDR /* solaris */ 00432 { PCSVADDR, "PCSVADDR", "set pc virtual address" }, 00433 #endif 00434 #ifdef PCSXREG /* solaris sparc only */ 00435 { PCSXREG, "PCSXREG", "set extra registers" }, 00436 #endif 00437 #ifdef PCTWSTOP /* solaris */ 00438 { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" }, 00439 #endif 00440 #ifdef PCUNKILL /* solaris */ 00441 { PCUNKILL, "PCUNKILL", "delete a pending signal" }, 00442 #endif 00443 #ifdef PCUNSET /* solaris */ 00444 { PCUNSET, "PCUNSET", "unset modes" }, 00445 #endif 00446 #ifdef PCWATCH /* solaris */ 00447 { PCWATCH, "PCWATCH", "set/unset watched memory area" }, 00448 #endif 00449 { PCWSTOP, "PCWSTOP", "wait for process/lwp to stop, no timeout" }, 00450 { 0, NULL, NULL } 00451 }; 00452 00453 static off_t lseek_offset; 00454 00455 int 00456 write_with_trace (int fd, void *varg, size_t len, char *file, int line) 00457 { 00458 int i = ARRAY_SIZE (rw_table) - 1; 00459 int ret; 00460 procfs_ctl_t *arg = (procfs_ctl_t *) varg; 00461 00462 prepare_to_trace (); 00463 if (procfs_trace) 00464 { 00465 procfs_ctl_t opcode = arg[0]; 00466 for (i = 0; rw_table[i].name != NULL; i++) 00467 if (rw_table[i].value == opcode) 00468 break; 00469 00470 if (info_verbose) 00471 fprintf (procfs_file ? procfs_file : stdout, 00472 "%s:%d -- ", file, line); 00473 switch (opcode) { 00474 case PCSET: 00475 fprintf (procfs_file ? procfs_file : stdout, 00476 "write (PCSET, %s) %s\n", 00477 arg[1] == PR_FORK ? "PR_FORK" : 00478 arg[1] == PR_RLC ? "PR_RLC" : 00479 #ifdef PR_ASYNC 00480 arg[1] == PR_ASYNC ? "PR_ASYNC" : 00481 #endif 00482 "<unknown flag>", 00483 info_verbose ? rw_table[i].desc : ""); 00484 break; 00485 #ifdef PCUNSET 00486 case PCUNSET: 00487 #endif 00488 #ifdef PCRESET 00489 #if PCRESET != PCUNSET 00490 case PCRESET: 00491 #endif 00492 #endif 00493 fprintf (procfs_file ? procfs_file : stdout, 00494 "write (PCRESET, %s) %s\n", 00495 arg[1] == PR_FORK ? "PR_FORK" : 00496 arg[1] == PR_RLC ? "PR_RLC" : 00497 #ifdef PR_ASYNC 00498 arg[1] == PR_ASYNC ? "PR_ASYNC" : 00499 #endif 00500 "<unknown flag>", 00501 info_verbose ? rw_table[i].desc : ""); 00502 break; 00503 case PCSTRACE: 00504 fprintf (procfs_file ? procfs_file : stdout, 00505 "write (PCSTRACE) "); 00506 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 00507 (sigset_t *) &arg[1], 0); 00508 break; 00509 case PCSFAULT: 00510 fprintf (procfs_file ? procfs_file : stdout, 00511 "write (PCSFAULT) "); 00512 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout, 00513 (fltset_t *) &arg[1], 0); 00514 break; 00515 case PCSENTRY: 00516 fprintf (procfs_file ? procfs_file : stdout, 00517 "write (PCSENTRY) "); 00518 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 00519 (sysset_t *) &arg[1], 0); 00520 break; 00521 case PCSEXIT: 00522 fprintf (procfs_file ? procfs_file : stdout, 00523 "write (PCSEXIT) "); 00524 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 00525 (sysset_t *) &arg[1], 0); 00526 break; 00527 #ifdef PCSHOLD 00528 case PCSHOLD: 00529 fprintf (procfs_file ? procfs_file : stdout, 00530 "write (PCSHOLD) "); 00531 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 00532 (sigset_t *) &arg[1], 0); 00533 break; 00534 #endif 00535 case PCSSIG: 00536 fprintf (procfs_file ? procfs_file : stdout, 00537 "write (PCSSIG) "); 00538 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 00539 arg[1] ? ((siginfo_t *) &arg[1])->si_signo 00540 : 0, 00541 0); 00542 fprintf (procfs_file ? procfs_file : stdout, "\n"); 00543 break; 00544 case PCRUN: 00545 fprintf (procfs_file ? procfs_file : stdout, 00546 "write (PCRUN) "); 00547 if (arg[1] & PRCSIG) 00548 fprintf (procfs_file ? procfs_file : stdout, "clearSig "); 00549 if (arg[1] & PRCFAULT) 00550 fprintf (procfs_file ? procfs_file : stdout, "clearFlt "); 00551 if (arg[1] & PRSTEP) 00552 fprintf (procfs_file ? procfs_file : stdout, "step "); 00553 #ifdef PRSABORT 00554 if (arg[1] & PRSABORT) 00555 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort "); 00556 #endif 00557 #ifdef PRSTOP 00558 if (arg[1] & PRSTOP) 00559 fprintf (procfs_file ? procfs_file : stdout, "stopReq "); 00560 #endif 00561 00562 fprintf (procfs_file ? procfs_file : stdout, "\n"); 00563 break; 00564 case PCKILL: 00565 fprintf (procfs_file ? procfs_file : stdout, 00566 "write (PCKILL) "); 00567 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 00568 arg[1], 0); 00569 fprintf (procfs_file ? procfs_file : stdout, "\n"); 00570 break; 00571 default: 00572 { 00573 if (rw_table[i].name) 00574 fprintf (procfs_file ? procfs_file : stdout, 00575 "write (%s) %s\n", 00576 rw_table[i].name, 00577 info_verbose ? rw_table[i].desc : ""); 00578 else 00579 { 00580 if (lseek_offset != -1) 00581 fprintf (procfs_file ? procfs_file : stdout, 00582 "write (<unknown>, %lud bytes at 0x%08lx) \n", 00583 (unsigned long) len, (unsigned long) lseek_offset); 00584 else 00585 fprintf (procfs_file ? procfs_file : stdout, 00586 "write (<unknown>, %lud bytes) \n", 00587 (unsigned long) len); 00588 } 00589 break; 00590 } 00591 } 00592 if (procfs_file) 00593 fflush (procfs_file); 00594 } 00595 errno = 0; 00596 ret = write (fd, (void *) arg, len); 00597 if (procfs_trace && ret != len) 00598 { 00599 fprintf (procfs_file ? procfs_file : stdout, 00600 "[write (%s) FAILED! (%s)]\n", 00601 rw_table[i].name != NULL ? 00602 rw_table[i].name : "<unknown>", 00603 safe_strerror (errno)); 00604 if (procfs_file) 00605 fflush (procfs_file); 00606 } 00607 00608 lseek_offset = -1; 00609 return ret; 00610 } 00611 00612 off_t 00613 lseek_with_trace (int fd, off_t offset, int whence, char *file, int line) 00614 { 00615 off_t ret; 00616 00617 prepare_to_trace (); 00618 errno = 0; 00619 ret = lseek (fd, offset, whence); 00620 lseek_offset = ret; 00621 if (procfs_trace && (ret == -1 || errno != 0)) 00622 { 00623 fprintf (procfs_file ? procfs_file : stdout, 00624 "[lseek (0x%08lx) FAILED! (%s)]\n", 00625 (unsigned long) offset, safe_strerror (errno)); 00626 if (procfs_file) 00627 fflush (procfs_file); 00628 } 00629 00630 return ret; 00631 } 00632 00633 #endif /* NEW_PROC_API */ 00634 00635 int 00636 open_with_trace (char *filename, int mode, char *file, int line) 00637 { 00638 int ret; 00639 00640 prepare_to_trace (); 00641 errno = 0; 00642 ret = open (filename, mode); 00643 if (procfs_trace) 00644 { 00645 if (info_verbose) 00646 fprintf (procfs_file ? procfs_file : stdout, 00647 "%s:%d -- ", file, line); 00648 00649 if (errno) 00650 { 00651 fprintf (procfs_file ? procfs_file : stdout, 00652 "[open FAILED! (%s) line %d]\\n", 00653 safe_strerror (errno), line); 00654 } 00655 else 00656 { 00657 fprintf (procfs_file ? procfs_file : stdout, 00658 "%d = open (%s, ", ret, filename); 00659 if (mode == O_RDONLY) 00660 fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n", 00661 line); 00662 else if (mode == O_WRONLY) 00663 fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n", 00664 line); 00665 else if (mode == O_RDWR) 00666 fprintf (procfs_file ? procfs_file : stdout, "O_RDWR) %d\n", 00667 line); 00668 } 00669 if (procfs_file) 00670 fflush (procfs_file); 00671 } 00672 00673 return ret; 00674 } 00675 00676 int 00677 close_with_trace (int fd, char *file, int line) 00678 { 00679 int ret; 00680 00681 prepare_to_trace (); 00682 errno = 0; 00683 ret = close (fd); 00684 if (procfs_trace) 00685 { 00686 if (info_verbose) 00687 fprintf (procfs_file ? procfs_file : stdout, 00688 "%s:%d -- ", file, line); 00689 if (errno) 00690 fprintf (procfs_file ? procfs_file : stdout, 00691 "[close FAILED! (%s)]\n", safe_strerror (errno)); 00692 else 00693 fprintf (procfs_file ? procfs_file : stdout, 00694 "%d = close (%d)\n", ret, fd); 00695 if (procfs_file) 00696 fflush (procfs_file); 00697 } 00698 00699 return ret; 00700 } 00701 00702 pid_t 00703 wait_with_trace (int *wstat, char *file, int line) 00704 { 00705 int ret, lstat = 0; 00706 00707 prepare_to_trace (); 00708 if (procfs_trace) 00709 { 00710 if (info_verbose) 00711 fprintf (procfs_file ? procfs_file : stdout, 00712 "%s:%d -- ", file, line); 00713 fprintf (procfs_file ? procfs_file : stdout, 00714 "wait (line %d) ", line); 00715 if (procfs_file) 00716 fflush (procfs_file); 00717 } 00718 errno = 0; 00719 ret = wait (&lstat); 00720 if (procfs_trace) 00721 { 00722 if (errno) 00723 fprintf (procfs_file ? procfs_file : stdout, 00724 "[wait FAILED! (%s)]\n", safe_strerror (errno)); 00725 else 00726 fprintf (procfs_file ? procfs_file : stdout, 00727 "returned pid %d, status 0x%x\n", ret, lstat); 00728 if (procfs_file) 00729 fflush (procfs_file); 00730 } 00731 if (wstat) 00732 *wstat = lstat; 00733 00734 return ret; 00735 } 00736 00737 void 00738 procfs_note (char *msg, char *file, int line) 00739 { 00740 prepare_to_trace (); 00741 if (procfs_trace) 00742 { 00743 if (info_verbose) 00744 fprintf (procfs_file ? procfs_file : stdout, 00745 "%s:%d -- ", file, line); 00746 fprintf (procfs_file ? procfs_file : stdout, "%s", msg); 00747 if (procfs_file) 00748 fflush (procfs_file); 00749 } 00750 } 00751 00752 void 00753 proc_prettyfprint_status (long flags, int why, int what, int thread) 00754 { 00755 prepare_to_trace (); 00756 if (procfs_trace) 00757 { 00758 if (thread) 00759 fprintf (procfs_file ? procfs_file : stdout, 00760 "Thread %d: ", thread); 00761 00762 proc_prettyfprint_flags (procfs_file ? procfs_file : stdout, 00763 flags, 0); 00764 00765 if (flags & (PR_STOPPED | PR_ISTOP)) 00766 proc_prettyfprint_why (procfs_file ? procfs_file : stdout, 00767 why, what, 0); 00768 if (procfs_file) 00769 fflush (procfs_file); 00770 } 00771 } 00772 00773 00774 /* Provide a prototype to silence -Wmissing-prototypes. */ 00775 extern void _initialize_proc_api (void); 00776 00777 void 00778 _initialize_proc_api (void) 00779 { 00780 struct cmd_list_element *c; 00781 00782 add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\ 00783 Set tracing for /proc api calls."), _("\ 00784 Show tracing for /proc api calls."), NULL, 00785 set_procfs_trace_cmd, 00786 NULL, /* FIXME: i18n: */ 00787 &setlist, &showlist); 00788 00789 add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\ 00790 Set filename for /proc tracefile."), _("\ 00791 Show filename for /proc tracefile."), NULL, 00792 set_procfs_file_cmd, 00793 NULL, /* FIXME: i18n: */ 00794 &setlist, &showlist); 00795 }