1 /* Machine independent support for SVR4 /proc (process file system) for GDB. 2 3 Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc. 4 5 Written by Michael Snyder at Cygnus Solutions. 6 Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others. 7 8 This file is part of GDB. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software Foundation, 22 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 23 24 /* 25 * Pretty-print trace of api calls to the /proc api 26 * (ioctl or read/write calls). 27 * 28 */ 29 30 #include "defs.h" 31 #include "gdbcmd.h" 32 #include "completer.h" 33 34 #if defined (NEW_PROC_API) 35 #define _STRUCTURED_PROC 1 36 #endif 37 38 #include <stdio.h> 39 #include <sys/types.h> 40 #include <sys/procfs.h> 41 #ifdef HAVE_SYS_PROC_H 42 #include <sys/proc.h> /* for struct proc */ 43 #endif 44 #ifdef HAVE_SYS_USER_H 45 #include <sys/user.h> /* for struct user */ 46 #endif 47 #include <fcntl.h> /* for O_RDWR etc. */ 48 #include "gdb_wait.h" 49 50 #include "proc-utils.h" 51 52 /* Much of the information used in the /proc interface, particularly for 53 printing status information, is kept as tables of structures of the 54 following form. These tables can be used to map numeric values to 55 their symbolic names and to a string that describes their specific use. */ 56 57 struct trans { 58 long value; /* The numeric value */ 59 char *name; /* The equivalent symbolic value */ 60 char *desc; /* Short description of value */ 61 }; 62 63 static int procfs_trace = 0; 64 static FILE *procfs_file = NULL; 65 static char *procfs_filename = "procfs_trace"; 66 67 static void 68 prepare_to_trace (void) 69 { 70 if (procfs_trace) /* if procfs tracing turned on */ 71 if (procfs_file == NULL) /* if output file not yet open */ 72 if (procfs_filename != NULL) /* if output filename known */ 73 procfs_file = fopen (procfs_filename, "a"); /* open output file */ 74 } 75 76 static void 77 set_procfs_trace_cmd (char *args, int from_tty, struct cmd_list_element *c) 78 { 79 #if 0 /* not sure what I might actually need to do here, if anything */ 80 if (procfs_file) 81 fflush (procfs_file); 82 #endif 83 } 84 85 static void 86 set_procfs_file_cmd (char *args, int from_tty, struct cmd_list_element *c) 87 { 88 /* Just changed the filename for procfs tracing. 89 If a file was already open, close it. */ 90 if (procfs_file) 91 fclose (procfs_file); 92 procfs_file = NULL; 93 } 94 95 96 #ifndef NEW_PROC_API 97 98 static struct trans ioctl_table[] = { 99 #ifdef PIOCACINFO /* irix */ 100 { PIOCACINFO, "PIOCACINFO", "get process account info" }, 101 #endif 102 { PIOCACTION, "PIOCACTION", "get signal action structs" }, 103 #ifdef PIOCARGUMENTS /* osf */ 104 { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" }, 105 #endif 106 #ifdef PIOCAUXV /* solaris aux vectors */ 107 { PIOCAUXV, "PIOCAUXV", "get aux vector" }, 108 { PIOCNAUXV, "PIOCNAUXV", "get number of aux vector entries" }, 109 #endif /* AUXV */ 110 { PIOCCFAULT, "PIOCCFAULT", "clear current fault" }, 111 { PIOCCRED, "PIOCCRED", "get process credentials" }, 112 #ifdef PIOCENEVCTRS /* irix event counters */ 113 { PIOCENEVCTRS, "PIOCENEVCTRS", "acquire and start event counters" }, 114 { PIOCGETEVCTRL, "PIOCGETEVCTRL", "get control info of event counters" }, 115 { PIOCGETEVCTRS, "PIOCGETEVCTRS", "dump event counters" }, 116 { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" }, 117 { PIOCRELEVCTRS, "PIOCRELEVCTRS", "release/stop event counters" }, 118 { PIOCSETEVCTRL, "PIOCSETEVCTRL", "set control info of event counters" }, 119 { PIOCGETPTIMER, "PIOCGETPTIMER", "get process timers" }, 120 #endif /* irix event counters */ 121 { PIOCGENTRY, "PIOCGENTRY", "get traced syscall entry set" }, 122 #if defined (PIOCGETPR) 123 { PIOCGETPR, "PIOCGETPR", "read struct proc" }, 124 #endif 125 #if defined (PIOCGETU) 126 { PIOCGETU, "PIOCGETU", "read user area" }, 127 #endif 128 #if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */ 129 { PIOCGETUTK, "PIOCGETUTK", "get the utask struct" }, 130 #endif 131 { PIOCGEXIT, "PIOCGEXIT", "get traced syscall exit set" }, 132 { PIOCGFAULT, "PIOCGFAULT", "get traced fault set" }, 133 #ifdef PIOCGFPCR /* osf */ 134 { PIOCGFPCR, "PIOCGFPCR", "get FP control register" }, 135 { PIOCSFPCR, "PIOCSFPCR", "set FP conrtol register" }, 136 #endif 137 { PIOCGFPREG, "PIOCGFPREG", "get floating point registers" }, 138 { PIOCGHOLD, "PIOCGHOLD", "get held signal set" }, 139 { PIOCGREG, "PIOCGREG", "get general registers" }, 140 { PIOCGROUPS, "PIOCGROUPS", "get supplementary groups" }, 141 #ifdef PIOCGSPCACT /* osf */ 142 { PIOCGSPCACT, "PIOCGSPCACT", "get special action" }, 143 { PIOCSSPCACT, "PIOCSSPCACT", "set special action" }, 144 #endif 145 { PIOCGTRACE, "PIOCGTRACE", "get traced signal set" }, 146 #ifdef PIOCGWATCH /* irix watchpoints */ 147 { PIOCGWATCH, "PIOCGWATCH", "get watchpoint" }, 148 { PIOCSWATCH, "PIOCSWATCH", "set watchpoint" }, 149 { PIOCNWATCH, "PIOCNWATCH", "get number of watchpoints" }, 150 #endif /* irix watchpoints */ 151 #ifdef PIOCGWIN /* solaris sparc */ 152 { PIOCGWIN, "PIOCGWIN", "get gwindows_t" }, 153 #endif 154 #ifdef PIOCGXREG /* solaris sparc extra regs */ 155 { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" }, 156 { PIOCGXREG, "PIOCGXREG", "get extra register state" }, 157 { PIOCSXREG, "PIOCSXREG", "set extra register state" }, 158 #endif /* XREG */ 159 { PIOCKILL, "PIOCKILL", "send signal" }, 160 #ifdef PIOCLDT /* solaris i386 */ 161 { PIOCLDT, "PIOCLDT", "get LDT" }, 162 { PIOCNLDT, "PIOCNLDT", "get number of LDT entries" }, 163 #endif 164 #ifdef PIOCLSTATUS /* solaris and unixware */ 165 { PIOCLSTATUS, "PIOCLSTATUS", "get status of all lwps" }, 166 { PIOCLUSAGE, "PIOCLUSAGE", "get resource usage of all lwps" }, 167 { PIOCOPENLWP, "PIOCOPENLWP", "get lwp file descriptor" }, 168 { PIOCLWPIDS, "PIOCLWPIDS", "get lwp identifiers" }, 169 #endif /* LWP */ 170 { PIOCMAP, "PIOCMAP", "get memory map information" }, 171 { PIOCMAXSIG, "PIOCMAXSIG", "get max signal number" }, 172 { PIOCNICE, "PIOCNICE", "set nice priority" }, 173 { PIOCNMAP, "PIOCNMAP", "get number of memory mappings" }, 174 { PIOCOPENM, "PIOCOPENM", "open mapped object for reading" }, 175 #ifdef PIOCOPENMOBS /* osf */ 176 { PIOCOPENMOBS, "PIOCOPENMOBS", "open mapped object" }, 177 #endif 178 #ifdef PIOCOPENPD /* solaris */ 179 { PIOCOPENPD, "PIOCOPENPD", "get page data file descriptor" }, 180 #endif 181 { PIOCPSINFO, "PIOCPSINFO", "get ps(1) information" }, 182 { PIOCRESET, "PIOCRESET", "reset process flags" }, 183 { PIOCRFORK, "PIOCRFORK", "reset inherit-on-fork flag" }, 184 { PIOCRRLC, "PIOCRRLC", "reset run-on-last-close flag" }, 185 { PIOCRUN, "PIOCRUN", "make process runnable" }, 186 #ifdef PIOCSAVECCNTRS /* irix */ 187 { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" }, 188 #endif 189 { PIOCSENTRY, "PIOCSENTRY", "set traced syscall entry set" }, 190 { PIOCSET, "PIOCSET", "set process flags" }, 191 { PIOCSEXIT, "PIOCSEXIT", "set traced syscall exit set" }, 192 { PIOCSFAULT, "PIOCSFAULT", "set traced fault set" }, 193 { PIOCSFORK, "PIOCSFORK", "set inherit-on-fork flag" }, 194 { PIOCSFPREG, "PIOCSFPREG", "set floating point registers" }, 195 { PIOCSHOLD, "PIOCSHOLD", "set held signal set" }, 196 { PIOCSREG, "PIOCSREG", "set general registers" }, 197 { PIOCSRLC, "PIOCSRLC", "set run-on-last-close flag" }, 198 { PIOCSSIG, "PIOCSSIG", "set current signal" }, 199 { PIOCSTATUS, "PIOCSTATUS", "get process status" }, 200 { PIOCSTOP, "PIOCSTOP", "post stop request" }, 201 { PIOCSTRACE, "PIOCSTRACE", "set traced signal set" }, 202 { PIOCUNKILL, "PIOCUNKILL", "delete a signal" }, 203 #ifdef PIOCUSAGE /* solaris */ 204 { PIOCUSAGE, "PIOCUSAGE", "get resource usage" }, 205 #endif 206 { PIOCWSTOP, "PIOCWSTOP", "wait for process to stop" }, 207 208 #ifdef PIOCNTHR /* osf threads */ 209 { PIOCNTHR, "PIOCNTHR", "get thread count" }, 210 { PIOCRTINH, "PIOCRTINH", "reset inherit-on-thread-creation" }, 211 { PIOCSTINH, "PIOCSTINH", "set inherit-on-thread-creation" }, 212 { PIOCTLIST, "PIOCTLIST", "get thread ids" }, 213 { PIOCXPTH, "PIOCXPTH", "translate port to thread handle" }, 214 { PIOCTRUN, "PIOCTRUN", "make thread runnable" }, 215 { PIOCTSTATUS, "PIOCTSTATUS", "get thread status" }, 216 { PIOCTSTOP, "PIOCTSTOP", "stop a thread" }, 217 /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT 218 TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY 219 TGEXIT TSEXIT TSHOLD ... thread functions */ 220 #endif /* osf threads */ 221 { -1, NULL, NULL } 222 }; 223 224 int 225 ioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line) 226 { 227 int i = 0; 228 int ret; 229 int arg1; 230 231 prepare_to_trace (); 232 233 if (procfs_trace) 234 { 235 for (i = 0; ioctl_table[i].name != NULL; i++) 236 if (ioctl_table[i].value == opcode) 237 break; 238 239 if (info_verbose) 240 fprintf (procfs_file ? procfs_file : stdout, 241 "%s:%d -- ", file, line); 242 switch (opcode) { 243 case PIOCSET: 244 arg1 = ptr ? *(long *) ptr : 0; 245 fprintf (procfs_file ? procfs_file : stdout, 246 "ioctl (PIOCSET, %s) %s\n", 247 arg1 == PR_FORK ? "PR_FORK" : 248 arg1 == PR_RLC ? "PR_RLC" : 249 #ifdef PR_ASYNC 250 arg1 == PR_ASYNC ? "PR_ASYNC" : 251 #endif 252 "<unknown flag>", 253 info_verbose ? ioctl_table[i].desc : ""); 254 break; 255 case PIOCRESET: 256 arg1 = ptr ? *(long *) ptr : 0; 257 fprintf (procfs_file ? procfs_file : stdout, 258 "ioctl (PIOCRESET, %s) %s\n", 259 arg1 == PR_FORK ? "PR_FORK" : 260 arg1 == PR_RLC ? "PR_RLC" : 261 #ifdef PR_ASYNC 262 arg1 == PR_ASYNC ? "PR_ASYNC" : 263 #endif 264 "<unknown flag>", 265 info_verbose ? ioctl_table[i].desc : ""); 266 break; 267 case PIOCSTRACE: 268 fprintf (procfs_file ? procfs_file : stdout, 269 "ioctl (PIOCSTRACE) "); 270 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 271 (sigset_t *) ptr, 0); 272 break; 273 case PIOCSFAULT: 274 fprintf (procfs_file ? procfs_file : stdout, 275 "ioctl (%s) ", 276 opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT"); 277 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout, 278 (fltset_t *) ptr, 0); 279 break; 280 case PIOCSENTRY: 281 fprintf (procfs_file ? procfs_file : stdout, 282 "ioctl (%s) ", 283 opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY"); 284 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 285 (sysset_t *) ptr, 0); 286 break; 287 case PIOCSEXIT: 288 fprintf (procfs_file ? procfs_file : stdout, 289 "ioctl (%s) ", 290 opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT"); 291 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 292 (sysset_t *) ptr, 0); 293 break; 294 case PIOCSHOLD: 295 fprintf (procfs_file ? procfs_file : stdout, 296 "ioctl (%s) ", 297 opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD"); 298 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 299 (sigset_t *) ptr, 0); 300 break; 301 case PIOCSSIG: 302 fprintf (procfs_file ? procfs_file : stdout, 303 "ioctl (PIOCSSIG) "); 304 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 305 ptr ? ((siginfo_t *) ptr)->si_signo : 0, 306 0); 307 fprintf (procfs_file ? procfs_file : stdout, "\n"); 308 break; 309 case PIOCRUN: 310 fprintf (procfs_file ? procfs_file : stdout, 311 "ioctl (PIOCRUN) "); 312 313 arg1 = ptr ? *(long *) ptr : 0; 314 if (arg1 & PRCSIG) 315 fprintf (procfs_file ? procfs_file : stdout, "clearSig "); 316 if (arg1 & PRCFAULT) 317 fprintf (procfs_file ? procfs_file : stdout, "clearFlt "); 318 if (arg1 & PRSTRACE) 319 fprintf (procfs_file ? procfs_file : stdout, "setTrace "); 320 if (arg1 & PRSHOLD) 321 fprintf (procfs_file ? procfs_file : stdout, "setHold "); 322 if (arg1 & PRSFAULT) 323 fprintf (procfs_file ? procfs_file : stdout, "setFlt "); 324 if (arg1 & PRSVADDR) 325 fprintf (procfs_file ? procfs_file : stdout, "setVaddr "); 326 if (arg1 & PRSTEP) 327 fprintf (procfs_file ? procfs_file : stdout, "step "); 328 if (arg1 & PRSABORT) 329 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort "); 330 if (arg1 & PRSTOP) 331 fprintf (procfs_file ? procfs_file : stdout, "stopReq "); 332 333 fprintf (procfs_file ? procfs_file : stdout, "\n"); 334 break; 335 case PIOCKILL: 336 fprintf (procfs_file ? procfs_file : stdout, 337 "ioctl (PIOCKILL) "); 338 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 339 ptr ? *(long *) ptr : 0, 0); 340 fprintf (procfs_file ? procfs_file : stdout, "\n"); 341 break; 342 #ifdef PIOCSSPCACT 343 case PIOCSSPCACT: 344 fprintf (procfs_file ? procfs_file : stdout, 345 "ioctl (PIOCSSPCACT) "); 346 arg1 = ptr ? *(long *) ptr : 0; 347 if (arg1 & PRFS_STOPFORK) 348 fprintf (procfs_file ? procfs_file : stdout, "stopFork "); 349 if (arg1 & PRFS_STOPEXEC) 350 fprintf (procfs_file ? procfs_file : stdout, "stopExec "); 351 if (arg1 & PRFS_STOPTERM) 352 fprintf (procfs_file ? procfs_file : stdout, "stopTerm "); 353 if (arg1 & PRFS_STOPTCR) 354 fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate "); 355 if (arg1 & PRFS_STOPTTERM) 356 fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm "); 357 if (arg1 & PRFS_KOLC) 358 fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose "); 359 fprintf (procfs_file ? procfs_file : stdout, "\n"); 360 break; 361 #endif /* PIOCSSPCACT */ 362 default: 363 if (ioctl_table[i].name) 364 fprintf (procfs_file ? procfs_file : stdout, 365 "ioctl (%s) %s\n", 366 ioctl_table[i].name, 367 info_verbose ? ioctl_table[i].desc : ""); 368 else 369 fprintf (procfs_file ? procfs_file : stdout, 370 "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode); 371 break; 372 } 373 if (procfs_file) 374 fflush (procfs_file); 375 } 376 errno = 0; 377 ret = ioctl (fd, opcode, ptr); 378 if (procfs_trace && ret < 0) 379 { 380 fprintf (procfs_file ? procfs_file : stdout, 381 "[ioctl (%s) FAILED! (%s)]\n", 382 ioctl_table[i].name != NULL ? 383 ioctl_table[i].name : "<unknown>", 384 safe_strerror (errno)); 385 if (procfs_file) 386 fflush (procfs_file); 387 } 388 389 return ret; 390 } 391 392 #else /* NEW_PROC_API */ 393 394 static struct trans rw_table[] = { 395 #ifdef PCAGENT /* solaris */ 396 { PCAGENT, "PCAGENT", "create agent lwp with regs from argument" }, 397 #endif 398 { PCCFAULT, "PCCFAULT", "clear current fault" }, 399 #ifdef PCCSIG /* solaris */ 400 { PCCSIG, "PCCSIG", "clear current signal" }, 401 #endif 402 #ifdef PCDSTOP /* solaris */ 403 { PCDSTOP, "PCDSTOP", "post stop request" }, 404 #endif 405 { PCKILL, "PCKILL", "post a signal" }, 406 #ifdef PCNICE /* solaris */ 407 { PCNICE, "PCNICE", "set nice priority" }, 408 #endif 409 #ifdef PCREAD /* solaris */ 410 { PCREAD, "PCREAD", "read from the address space" }, 411 { PCWRITE, "PCWRITE", "write to the address space" }, 412 #endif 413 #ifdef PCRESET /* unixware */ 414 { PCRESET, "PCRESET", "unset modes" }, 415 #endif 416 { PCRUN, "PCRUN", "make process/lwp runnable" }, 417 #ifdef PCSASRS /* solaris 2.7 only */ 418 { PCSASRS, "PCSASRS", "set ancillary state registers" }, 419 #endif 420 #ifdef PCSCRED /* solaris */ 421 { PCSCRED, "PCSCRED", "set process credentials" }, 422 #endif 423 { PCSENTRY, "PCSENTRY", "set traced syscall entry set" }, 424 { PCSET, "PCSET", "set modes" }, 425 { PCSEXIT, "PCSEXIT", "set traced syscall exit set" }, 426 { PCSFAULT, "PCSFAULT", "set traced fault set" }, 427 { PCSFPREG, "PCSFPREG", "set floating point registers" }, 428 #ifdef PCSHOLD /* solaris */ 429 { PCSHOLD, "PCSHOLD", "set signal mask" }, 430 #endif 431 { PCSREG, "PCSREG", "set general registers" }, 432 { PCSSIG, "PCSSIG", "set current signal" }, 433 { PCSTOP, "PCSTOP", "post stop request and wait" }, 434 { PCSTRACE, "PCSTRACE", "set traced signal set" }, 435 #ifdef PCSVADDR /* solaris */ 436 { PCSVADDR, "PCSVADDR", "set pc virtual address" }, 437 #endif 438 #ifdef PCSXREG /* solaris sparc only */ 439 { PCSXREG, "PCSXREG", "set extra registers" }, 440 #endif 441 #ifdef PCTWSTOP /* solaris */ 442 { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" }, 443 #endif 444 #ifdef PCUNKILL /* solaris */ 445 { PCUNKILL, "PCUNKILL", "delete a pending signal" }, 446 #endif 447 #ifdef PCUNSET /* solaris */ 448 { PCUNSET, "PCUNSET", "unset modes" }, 449 #endif 450 #ifdef PCWATCH /* solaris */ 451 { PCWATCH, "PCWATCH", "set/unset watched memory area" }, 452 #endif 453 { PCWSTOP, "PCWSTOP", "wait for process/lwp to stop, no timeout" }, 454 { 0, NULL, NULL } 455 }; 456 457 static off_t lseek_offset; 458 459 int 460 write_with_trace (int fd, void *varg, size_t len, char *file, int line) 461 { 462 int i = ARRAY_SIZE (rw_table) - 1; 463 int ret; 464 procfs_ctl_t *arg = (procfs_ctl_t *) varg; 465 466 prepare_to_trace (); 467 if (procfs_trace) 468 { 469 procfs_ctl_t opcode = arg[0]; 470 for (i = 0; rw_table[i].name != NULL; i++) 471 if (rw_table[i].value == opcode) 472 break; 473 474 if (info_verbose) 475 fprintf (procfs_file ? procfs_file : stdout, 476 "%s:%d -- ", file, line); 477 switch (opcode) { 478 case PCSET: 479 fprintf (procfs_file ? procfs_file : stdout, 480 "write (PCSET, %s) %s\n", 481 arg[1] == PR_FORK ? "PR_FORK" : 482 arg[1] == PR_RLC ? "PR_RLC" : 483 #ifdef PR_ASYNC 484 arg[1] == PR_ASYNC ? "PR_ASYNC" : 485 #endif 486 "<unknown flag>", 487 info_verbose ? rw_table[i].desc : ""); 488 break; 489 #ifdef PCUNSET 490 case PCUNSET: 491 #endif 492 #ifdef PCRESET 493 #if PCRESET != PCUNSET 494 case PCRESET: 495 #endif 496 #endif 497 fprintf (procfs_file ? procfs_file : stdout, 498 "write (PCRESET, %s) %s\n", 499 arg[1] == PR_FORK ? "PR_FORK" : 500 arg[1] == PR_RLC ? "PR_RLC" : 501 #ifdef PR_ASYNC 502 arg[1] == PR_ASYNC ? "PR_ASYNC" : 503 #endif 504 "<unknown flag>", 505 info_verbose ? rw_table[i].desc : ""); 506 break; 507 case PCSTRACE: 508 fprintf (procfs_file ? procfs_file : stdout, 509 "write (PCSTRACE) "); 510 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 511 (sigset_t *) &arg[1], 0); 512 break; 513 case PCSFAULT: 514 fprintf (procfs_file ? procfs_file : stdout, 515 "write (PCSFAULT) "); 516 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout, 517 (fltset_t *) &arg[1], 0); 518 break; 519 case PCSENTRY: 520 fprintf (procfs_file ? procfs_file : stdout, 521 "write (PCSENTRY) "); 522 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 523 (sysset_t *) &arg[1], 0); 524 break; 525 case PCSEXIT: 526 fprintf (procfs_file ? procfs_file : stdout, 527 "write (PCSEXIT) "); 528 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, 529 (sysset_t *) &arg[1], 0); 530 break; 531 #ifdef PCSHOLD 532 case PCSHOLD: 533 fprintf (procfs_file ? procfs_file : stdout, 534 "write (PCSHOLD) "); 535 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, 536 (sigset_t *) &arg[1], 0); 537 break; 538 #endif 539 case PCSSIG: 540 fprintf (procfs_file ? procfs_file : stdout, 541 "write (PCSSIG) "); 542 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 543 arg[1] ? ((siginfo_t *) &arg[1])->si_signo 544 : 0, 545 0); 546 fprintf (procfs_file ? procfs_file : stdout, "\n"); 547 break; 548 case PCRUN: 549 fprintf (procfs_file ? procfs_file : stdout, 550 "write (PCRUN) "); 551 if (arg[1] & PRCSIG) 552 fprintf (procfs_file ? procfs_file : stdout, "clearSig "); 553 if (arg[1] & PRCFAULT) 554 fprintf (procfs_file ? procfs_file : stdout, "clearFlt "); 555 if (arg[1] & PRSTEP) 556 fprintf (procfs_file ? procfs_file : stdout, "step "); 557 #ifdef PRSABORT 558 if (arg[1] & PRSABORT) 559 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort "); 560 #endif 561 #ifdef PRSTOP 562 if (arg[1] & PRSTOP) 563 fprintf (procfs_file ? procfs_file : stdout, "stopReq "); 564 #endif 565 566 fprintf (procfs_file ? procfs_file : stdout, "\n"); 567 break; 568 case PCKILL: 569 fprintf (procfs_file ? procfs_file : stdout, 570 "write (PCKILL) "); 571 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, 572 arg[1], 0); 573 fprintf (procfs_file ? procfs_file : stdout, "\n"); 574 break; 575 default: 576 { 577 if (rw_table[i].name) 578 fprintf (procfs_file ? procfs_file : stdout, 579 "write (%s) %s\n", 580 rw_table[i].name, 581 info_verbose ? rw_table[i].desc : ""); 582 else 583 { 584 if (lseek_offset != -1) 585 fprintf (procfs_file ? procfs_file : stdout, 586 "write (<unknown>, %lud bytes at 0x%08lx) \n", 587 (unsigned long) len, (unsigned long) lseek_offset); 588 else 589 fprintf (procfs_file ? procfs_file : stdout, 590 "write (<unknown>, %lud bytes) \n", 591 (unsigned long) len); 592 } 593 break; 594 } 595 } 596 if (procfs_file) 597 fflush (procfs_file); 598 } 599 errno = 0; 600 ret = write (fd, (void *) arg, len); 601 if (procfs_trace && ret != len) 602 { 603 fprintf (procfs_file ? procfs_file : stdout, 604 "[write (%s) FAILED! (%s)]\n", 605 rw_table[i].name != NULL ? 606 rw_table[i].name : "<unknown>", 607 safe_strerror (errno)); 608 if (procfs_file) 609 fflush (procfs_file); 610 } 611 612 lseek_offset = -1; 613 return ret; 614 } 615 616 off_t 617 lseek_with_trace (int fd, off_t offset, int whence, char *file, int line) 618 { 619 off_t ret; 620 621 prepare_to_trace (); 622 errno = 0; 623 ret = lseek (fd, offset, whence); 624 lseek_offset = ret; 625 if (procfs_trace && (ret == -1 || errno != 0)) 626 { 627 fprintf (procfs_file ? procfs_file : stdout, 628 "[lseek (0x%08lx) FAILED! (%s)]\n", 629 (unsigned long) offset, safe_strerror (errno)); 630 if (procfs_file) 631 fflush (procfs_file); 632 } 633 634 return ret; 635 } 636 637 #endif /* NEW_PROC_API */ 638 639 int 640 open_with_trace (char *filename, int mode, char *file, int line) 641 { 642 int ret; 643 644 prepare_to_trace (); 645 errno = 0; 646 ret = open (filename, mode); 647 if (procfs_trace) 648 { 649 if (info_verbose) 650 fprintf (procfs_file ? procfs_file : stdout, 651 "%s:%d -- ", file, line); 652 653 if (errno) 654 { 655 fprintf (procfs_file ? procfs_file : stdout, 656 "[open FAILED! (%s) line %d]\\n", 657 safe_strerror (errno), line); 658 } 659 else 660 { 661 fprintf (procfs_file ? procfs_file : stdout, 662 "%d = open (%s, ", ret, filename); 663 if (mode == O_RDONLY) 664 fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n", 665 line); 666 else if (mode == O_WRONLY) 667 fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n", 668 line); 669 else if (mode == O_RDWR) 670 fprintf (procfs_file ? procfs_file : stdout, "O_RDWR) %d\n", 671 line); 672 } 673 if (procfs_file) 674 fflush (procfs_file); 675 } 676 677 return ret; 678 } 679 680 int 681 close_with_trace (int fd, char *file, int line) 682 { 683 int ret; 684 685 prepare_to_trace (); 686 errno = 0; 687 ret = close (fd); 688 if (procfs_trace) 689 { 690 if (info_verbose) 691 fprintf (procfs_file ? procfs_file : stdout, 692 "%s:%d -- ", file, line); 693 if (errno) 694 fprintf (procfs_file ? procfs_file : stdout, 695 "[close FAILED! (%s)]\n", safe_strerror (errno)); 696 else 697 fprintf (procfs_file ? procfs_file : stdout, 698 "%d = close (%d)\n", ret, fd); 699 if (procfs_file) 700 fflush (procfs_file); 701 } 702 703 return ret; 704 } 705 706 pid_t 707 wait_with_trace (int *wstat, char *file, int line) 708 { 709 int ret, lstat = 0; 710 711 prepare_to_trace (); 712 if (procfs_trace) 713 { 714 if (info_verbose) 715 fprintf (procfs_file ? procfs_file : stdout, 716 "%s:%d -- ", file, line); 717 fprintf (procfs_file ? procfs_file : stdout, 718 "wait (line %d) ", line); 719 if (procfs_file) 720 fflush (procfs_file); 721 } 722 errno = 0; 723 ret = wait (&lstat); 724 if (procfs_trace) 725 { 726 if (errno) 727 fprintf (procfs_file ? procfs_file : stdout, 728 "[wait FAILED! (%s)]\n", safe_strerror (errno)); 729 else 730 fprintf (procfs_file ? procfs_file : stdout, 731 "returned pid %d, status 0x%x\n", ret, lstat); 732 if (procfs_file) 733 fflush (procfs_file); 734 } 735 if (wstat) 736 *wstat = lstat; 737 738 return ret; 739 } 740 741 void 742 procfs_note (char *msg, char *file, int line) 743 { 744 prepare_to_trace (); 745 if (procfs_trace) 746 { 747 if (info_verbose) 748 fprintf (procfs_file ? procfs_file : stdout, 749 "%s:%d -- ", file, line); 750 fprintf (procfs_file ? procfs_file : stdout, "%s", msg); 751 if (procfs_file) 752 fflush (procfs_file); 753 } 754 } 755 756 void 757 proc_prettyfprint_status (long flags, int why, int what, int thread) 758 { 759 prepare_to_trace (); 760 if (procfs_trace) 761 { 762 if (thread) 763 fprintf (procfs_file ? procfs_file : stdout, 764 "Thread %d: ", thread); 765 766 proc_prettyfprint_flags (procfs_file ? procfs_file : stdout, 767 flags, 0); 768 769 if (flags & (PR_STOPPED | PR_ISTOP)) 770 proc_prettyfprint_why (procfs_file ? procfs_file : stdout, 771 why, what, 0); 772 if (procfs_file) 773 fflush (procfs_file); 774 } 775 } 776 777 778 void 779 _initialize_proc_api (void) 780 { 781 struct cmd_list_element *c; 782 783 c = add_set_cmd ("procfs-trace", no_class, 784 var_boolean, (char *) &procfs_trace, 785 "Set tracing for /proc api calls.\n", &setlist); 786 787 deprecated_add_show_from_set (c, &showlist); 788 set_cmd_sfunc (c, set_procfs_trace_cmd); 789 set_cmd_completer (c, filename_completer); 790 791 c = add_set_cmd ("procfs-file", no_class, var_filename, 792 (char *) &procfs_filename, 793 "Set filename for /proc tracefile.\n", &setlist); 794 795 deprecated_add_show_from_set (c, &showlist); 796 set_cmd_sfunc (c, set_procfs_file_cmd); 797 } 798