|
|
1.1 ! root 1: /* Low level interface to ptrace, for GDB when running under Unix. ! 2: Copyright (C) 1986, 1987 Free Software Foundation, Inc. ! 3: ! 4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY ! 5: WARRANTY. No author or distributor accepts responsibility to anyone ! 6: for the consequences of using it or for whether it serves any ! 7: particular purpose or works at all, unless he says so in writing. ! 8: Refer to the GDB General Public License for full details. ! 9: ! 10: Everyone is granted permission to copy, modify and redistribute GDB, ! 11: but only under the conditions described in the GDB General Public ! 12: License. A copy of this license is supposed to have been given to you ! 13: along with GDB so you can know your rights and responsibilities. It ! 14: should be in a file named COPYING. Among other things, the copyright ! 15: notice and this notice must be preserved on all copies. ! 16: ! 17: In other words, go ahead and share GDB, but don't try to stop ! 18: anyone else from sharing it farther. Help stamp out software hoarding! ! 19: */ ! 20: ! 21: #include "defs.h" ! 22: #include "initialize.h" ! 23: #include "param.h" ! 24: #include "frame.h" ! 25: #include "inferior.h" ! 26: ! 27: #include <stdio.h> ! 28: #include <sys/param.h> ! 29: #include <sys/dir.h> ! 30: #ifndef UMAX_PTRACE ! 31: #include <sys/user.h> ! 32: #endif ! 33: #include <signal.h> ! 34: #include <sys/ioctl.h> ! 35: #include <fcntl.h> ! 36: ! 37: #ifdef UMAX_PTRACE ! 38: #include <a.out.h> ! 39: #include <sys/ptrace.h> ! 40: #define PTRACE_ATTACH PT_ATTACH ! 41: #define PTRACE_DETACH PT_FREEPROC ! 42: #endif ! 43: ! 44: #ifdef NEW_SUN_PTRACE ! 45: #include <sys/ptrace.h> ! 46: #include <machine/reg.h> ! 47: #endif ! 48: ! 49: #ifdef HP9K320 ! 50: #include <sys/ptrace.h> ! 51: #include <sys/reg.h> ! 52: #include <sys/trap.h> ! 53: #endif ! 54: ! 55: #ifdef HAVE_TERMIO ! 56: #include <termio.h> ! 57: #undef TIOCGETP ! 58: #define TIOCGETP TCGETA ! 59: #undef TIOCSETN ! 60: #define TIOCSETN TCSETA ! 61: #undef TIOCSETP ! 62: #define TIOCSETP TCSETAF ! 63: #define TERMINAL struct termio ! 64: #else ! 65: #include <sgtty.h> ! 66: #define TERMINAL struct sgttyb ! 67: #endif ! 68: ! 69: extern int errno; ! 70: ! 71: /* Nonzero if we are debugging an attached outside process ! 72: rather than an inferior. */ ! 73: ! 74: static int attach_flag; ! 75: ! 76: START_FILE ! 77: ! 78: /* Record terminal status separately for debugger and inferior. */ ! 79: ! 80: static TERMINAL sg_inferior; ! 81: static TERMINAL sg_ours; ! 82: static int tflags_inferior; ! 83: static int tflags_ours; ! 84: ! 85: #ifdef TIOCGLTC ! 86: static struct tchars tc_inferior; ! 87: static struct tchars tc_ours; ! 88: static struct ltchars ltc_inferior; ! 89: static struct ltchars ltc_ours; ! 90: static int lmode_inferior; ! 91: static int lmode_ours; ! 92: #endif /* TIOCGLTC */ ! 93: ! 94: #ifdef TIOCGPGRP ! 95: static int pgrp_inferior; ! 96: static int pgrp_ours; ! 97: #else ! 98: static int (*sigint_ours) (); ! 99: static int (*sigquit_ours) (); ! 100: #endif /* TIOCGPGRP */ ! 101: ! 102: /* Copy of inferior_io_terminal when inferior was last started. */ ! 103: static char *inferior_thisrun_terminal; ! 104: ! 105: static void terminal_ours_1 (); ! 106: ! 107: /* Nonzero if our terminal settings are in effect. ! 108: Zero if the inferior's settings are in effect. */ ! 109: static int terminal_is_ours; ! 110: ! 111: /* Initialize the terminal settings we record for the inferior, ! 112: before we actually run the inferior. */ ! 113: ! 114: void ! 115: terminal_init_inferior () ! 116: { ! 117: if (remote_debugging) ! 118: return; ! 119: ! 120: sg_inferior = sg_ours; ! 121: tflags_inferior = tflags_ours; ! 122: ! 123: #ifdef TIOCGLTC ! 124: tc_inferior = tc_ours; ! 125: ltc_inferior = ltc_ours; ! 126: lmode_inferior = lmode_ours; ! 127: #endif /* TIOCGLTC */ ! 128: ! 129: #ifdef TIOCGPGRP ! 130: pgrp_inferior = inferior_pid; ! 131: #endif /* TIOCGPGRP */ ! 132: ! 133: terminal_is_ours = 1; ! 134: } ! 135: ! 136: /* Put the inferior's terminal settings into effect. ! 137: This is preparation for starting or resuming the inferior. */ ! 138: ! 139: void ! 140: terminal_inferior () ! 141: { ! 142: if (remote_debugging) ! 143: return; ! 144: ! 145: if (terminal_is_ours) /* && inferior_thisrun_terminal == 0) */ ! 146: { ! 147: fcntl (0, F_SETFL, tflags_inferior); ! 148: fcntl (0, F_SETFL, tflags_inferior); ! 149: ioctl (0, TIOCSETN, &sg_inferior); ! 150: ! 151: #ifdef TIOCGLTC ! 152: ioctl (0, TIOCSETC, &tc_inferior); ! 153: ioctl (0, TIOCSLTC, <c_inferior); ! 154: ioctl (0, TIOCLSET, &lmode_inferior); ! 155: #endif /* TIOCGLTC */ ! 156: ! 157: #ifdef TIOCGPGRP ! 158: ioctl (0, TIOCSPGRP, &pgrp_inferior); ! 159: #else ! 160: sigint_ours = (signal (SIGINT, SIG_IGN)); ! 161: sigquit_ours = (signal (SIGQUIT, SIG_IGN)); ! 162: #endif /* TIOCGPGRP */ ! 163: } ! 164: terminal_is_ours = 0; ! 165: } ! 166: ! 167: /* Put some of our terminal settings into effect, ! 168: enough to get proper results from our output, ! 169: but do not change into or out of RAW mode ! 170: so that no input is discarded. ! 171: ! 172: After doing this, either terminal_ours or terminal_inferior ! 173: should be called to get back to a normal state of affairs. */ ! 174: ! 175: void ! 176: terminal_ours_for_output () ! 177: { ! 178: if (remote_debugging) ! 179: return; ! 180: ! 181: terminal_ours_1 (1); ! 182: } ! 183: ! 184: /* Put our terminal settings into effect. ! 185: First record the inferior's terminal settings ! 186: so they can be restored properly later. */ ! 187: ! 188: void ! 189: terminal_ours () ! 190: { ! 191: if (remote_debugging) ! 192: return; ! 193: ! 194: terminal_ours_1 (0); ! 195: } ! 196: ! 197: static void ! 198: terminal_ours_1 (output_only) ! 199: int output_only; ! 200: { ! 201: #ifdef TIOCGPGRP ! 202: /* Ignore this signal since it will happen when we try to set the pgrp. */ ! 203: int (*osigttou) (); ! 204: #endif /* TIOCGPGRP */ ! 205: ! 206: if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */ ! 207: { ! 208: terminal_is_ours = 1; ! 209: ! 210: #ifdef TIOCGPGRP ! 211: osigttou = signal (SIGTTOU, SIG_IGN); ! 212: ! 213: ioctl (0, TIOCGPGRP, &pgrp_inferior); ! 214: ioctl (0, TIOCSPGRP, &pgrp_ours); ! 215: ! 216: signal (SIGTTOU, osigttou); ! 217: #else ! 218: signal (SIGINT, sigint_ours); ! 219: signal (SIGQUIT, sigquit_ours); ! 220: #endif /* TIOCGPGRP */ ! 221: ! 222: tflags_inferior = fcntl (0, F_GETFL, 0); ! 223: ioctl (0, TIOCGETP, &sg_inferior); ! 224: ! 225: #ifdef TIOCGLTC ! 226: ioctl (0, TIOCGETC, &tc_inferior); ! 227: ioctl (0, TIOCGLTC, <c_inferior); ! 228: ioctl (0, TIOCLGET, &lmode_inferior); ! 229: #endif /* TIOCGLTC */ ! 230: } ! 231: ! 232: #ifdef HAVE_TERMIO ! 233: sg_ours.c_lflag |= ICANON; ! 234: if (output_only && !(sg_inferior.c_lflag & ICANON)) ! 235: sg_ours.c_lflag &= ~ICANON; ! 236: #else /* not HAVE_TERMIO */ ! 237: sg_ours.sg_flags &= ~RAW & ~CBREAK; ! 238: if (output_only) ! 239: sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags; ! 240: #endif /* not HAVE_TERMIO */ ! 241: ! 242: fcntl (0, F_SETFL, tflags_ours); ! 243: fcntl (0, F_SETFL, tflags_ours); ! 244: ioctl (0, TIOCSETN, &sg_ours); ! 245: ! 246: #ifdef TIOCGLTC ! 247: ioctl (0, TIOCSETC, &tc_ours); ! 248: ioctl (0, TIOCSLTC, <c_ours); ! 249: ioctl (0, TIOCLSET, &lmode_ours); ! 250: #endif /* TIOCGLTC */ ! 251: ! 252: ! 253: #ifdef HAVE_TERMIO ! 254: sg_ours.c_lflag |= ICANON; ! 255: #else /* not HAVE_TERMIO */ ! 256: sg_ours.sg_flags &= ~RAW & ~CBREAK; ! 257: #endif /* not HAVE_TERMIO */ ! 258: } ! 259: ! 260: static void ! 261: term_status_command () ! 262: { ! 263: register int i; ! 264: ! 265: if (remote_debugging) ! 266: { ! 267: printf ("No terminal status when remote debugging.\n"); ! 268: return; ! 269: } ! 270: ! 271: printf ("Inferior's terminal status (currently saved by GDB):\n"); ! 272: ! 273: #ifdef HAVE_TERMIO ! 274: ! 275: printf ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n", ! 276: tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag); ! 277: printf ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", ! 278: sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line); ! 279: printf ("c_cc: "); ! 280: for (i = 0; (i < NCC); i += 1) ! 281: printf ("0x%x ", sg_inferior.c_cc[i]); ! 282: printf ("\n"); ! 283: ! 284: #else /* not HAVE_TERMIO */ ! 285: ! 286: printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n", ! 287: tflags_inferior, lmode_inferior, ! 288: sg_inferior.sg_flags, pgrp_inferior); ! 289: printf ("tchars: "); ! 290: for (i = 0; i < sizeof (struct tchars); i++) ! 291: printf ("0x%x ", ((char *)&tc_inferior)[i]); ! 292: printf ("\n"); ! 293: printf ("ltchars: "); ! 294: for (i = 0; i < sizeof (struct ltchars); i++) ! 295: printf ("0x%x ", ((char *)<c_inferior)[i]); ! 296: ! 297: #endif /* not HAVE_TERMIO */ ! 298: } ! 299: ! 300: static void ! 301: new_tty (ttyname) ! 302: char *ttyname; ! 303: { ! 304: register int tty; ! 305: register int fd; ! 306: ! 307: #if 0 ! 308: /* I think it is better not to do this. Then C-z on the GDB terminal ! 309: will still stop the program, while C-z on the data terminal ! 310: will be input. */ ! 311: ! 312: /* Disconnect the child process from our controlling terminal. */ ! 313: tty = open("/dev/tty", O_RDWR); ! 314: if (tty > 0) ! 315: { ! 316: ioctl(tty, TIOCNOTTY, 0); ! 317: close(tty); ! 318: } ! 319: #endif ! 320: /* Now open the specified new terminal. */ ! 321: ! 322: tty = open(ttyname, O_RDWR); ! 323: if (tty == -1) ! 324: _exit(1); ! 325: ! 326: dup2(tty, 0); ! 327: dup2(tty, 1); ! 328: dup2(tty, 2); ! 329: close(tty); ! 330: } ! 331: ! 332: /* Start an inferior process and returns its pid. ! 333: ALLARGS is a string containing shell command to run the program. ! 334: ENV is the environment vector to pass. */ ! 335: ! 336: #ifndef SHELL_FILE ! 337: #define SHELL_FILE "/bin/sh" ! 338: #endif ! 339: ! 340: int ! 341: create_inferior (allargs, env) ! 342: char *allargs; ! 343: char **env; ! 344: { ! 345: int pid; ! 346: char *shell_command; ! 347: extern int sys_nerr; ! 348: extern char *sys_errlist[]; ! 349: extern int errno; ! 350: ! 351: /* If desired, concat something onto the front of ALLARGS. ! 352: SHELL_COMMAND is the result. */ ! 353: #ifdef SHELL_COMMAND_CONCAT ! 354: shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1); ! 355: strcpy (shell_command, SHELL_COMMAND_CONCAT); ! 356: strcat (shell_command, allargs); ! 357: #else ! 358: shell_command = allargs; ! 359: #endif ! 360: ! 361: /* exec is said to fail if the executable is open. */ ! 362: close_exec_file (); ! 363: ! 364: pid = vfork (); ! 365: if (pid < 0) ! 366: perror_with_name ("vfork"); ! 367: ! 368: if (pid == 0) ! 369: { ! 370: char *args[4]; ! 371: ! 372: #ifdef TIOCGPGRP ! 373: /* Run inferior in a separate process group. */ ! 374: setpgrp (getpid (), getpid ()); ! 375: #endif /* TIOCGPGRP */ ! 376: ! 377: inferior_thisrun_terminal = inferior_io_terminal; ! 378: if (inferior_io_terminal != 0) ! 379: new_tty (inferior_io_terminal); ! 380: ! 381: /* Not needed on Sun, at least, and loses there ! 382: because it clobbers the superior. */ ! 383: /*??? signal (SIGQUIT, SIG_DFL); ! 384: signal (SIGINT, SIG_DFL); */ ! 385: ! 386: ptrace (0); ! 387: ! 388: args[0] = "sh"; ! 389: args[1] = "-c"; ! 390: args[2] = shell_command; ! 391: args[3] = 0; ! 392: ! 393: execve (SHELL_FILE, args, env); ! 394: ! 395: fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE, ! 396: errno < sys_nerr ? sys_errlist[errno] : "unknown error"); ! 397: fflush (stderr); ! 398: _exit (0177); ! 399: } ! 400: return pid; ! 401: } ! 402: ! 403: /* Kill the inferior process. Make us have no inferior. */ ! 404: ! 405: static void ! 406: kill_command () ! 407: { ! 408: if (remote_debugging) ! 409: return; ! 410: if (inferior_pid == 0) ! 411: error ("The program is not being run."); ! 412: if (!query ("Kill the inferior process? ")) ! 413: error ("Not confirmed."); ! 414: kill_inferior (); ! 415: } ! 416: ! 417: kill_inferior () ! 418: { ! 419: if (remote_debugging) ! 420: return; ! 421: if (inferior_pid == 0) ! 422: return; ! 423: ptrace (8, inferior_pid, 0, 0); ! 424: wait (0); ! 425: inferior_died (); ! 426: } ! 427: ! 428: /* This is used when GDB is exiting. It gives less chance of error.*/ ! 429: ! 430: kill_inferior_fast () ! 431: { ! 432: if (remote_debugging) ! 433: return; ! 434: if (inferior_pid == 0) ! 435: return; ! 436: ptrace (8, inferior_pid, 0, 0); ! 437: wait (0); ! 438: } ! 439: ! 440: inferior_died () ! 441: { ! 442: inferior_pid = 0; ! 443: attach_flag = 0; ! 444: mark_breakpoints_out (); ! 445: reopen_exec_file (); ! 446: if (have_core_file_p ()) ! 447: set_current_frame (read_register (FP_REGNUM)); ! 448: } ! 449: ! 450: /* Resume execution of the inferior process. ! 451: If STEP is nonzero, single-step it. ! 452: If SIGNAL is nonzero, give it that signal. */ ! 453: ! 454: void ! 455: resume (step, signal) ! 456: int step; ! 457: int signal; ! 458: { ! 459: errno = 0; ! 460: if (remote_debugging) ! 461: remote_resume (step, signal); ! 462: else ! 463: { ! 464: ptrace (step ? 9 : 7, inferior_pid, 1, signal); ! 465: if (errno) ! 466: perror_with_name ("ptrace"); ! 467: } ! 468: } ! 469: ! 470: #ifdef ATTACH_DETACH ! 471: ! 472: /* Start debugging the process whose number is PID. */ ! 473: ! 474: attach (pid) ! 475: int pid; ! 476: { ! 477: errno = 0; ! 478: ptrace (PTRACE_ATTACH, pid, 0, 0); ! 479: if (errno) ! 480: perror_with_name ("ptrace"); ! 481: attach_flag = 1; ! 482: return pid; ! 483: } ! 484: ! 485: /* Stop debugging the process whose number is PID ! 486: and continue it with signal number SIGNAL. ! 487: SIGNAL = 0 means just continue it. */ ! 488: ! 489: void ! 490: detach (signal) ! 491: int signal; ! 492: { ! 493: errno = 0; ! 494: ptrace (PTRACE_DETACH, inferior_pid, 1, signal); ! 495: if (errno) ! 496: perror_with_name ("ptrace"); ! 497: attach_flag = 0; ! 498: } ! 499: #endif /* ATTACH_DETACH */ ! 500: ! 501: #ifdef NEW_SUN_PTRACE ! 502: ! 503: void ! 504: fetch_inferior_registers () ! 505: { ! 506: struct regs inferior_registers; ! 507: struct fp_status inferior_fp_registers; ! 508: extern char registers[]; ! 509: ! 510: if (remote_debugging) ! 511: remote_fetch_registers (registers); ! 512: else ! 513: { ! 514: ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers); ! 515: ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers); ! 516: ! 517: bcopy (&inferior_registers, registers, 16 * 4); ! 518: bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], ! 519: sizeof inferior_fp_registers.fps_regs); ! 520: *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; ! 521: *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc; ! 522: bcopy (&inferior_fp_registers.fps_control, ! 523: ®isters[REGISTER_BYTE (FPC_REGNUM)], ! 524: sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs); ! 525: } ! 526: } ! 527: ! 528: /* Store our register values back into the inferior. ! 529: If REGNO is -1, do this for all registers. ! 530: Otherwise, REGNO specifies which register (so we can save time). */ ! 531: ! 532: store_inferior_registers (regno) ! 533: int regno; ! 534: { ! 535: struct regs inferior_registers; ! 536: struct fp_status inferior_fp_registers; ! 537: extern char registers[]; ! 538: ! 539: if (remote_debugging) ! 540: remote_store_registers (registers); ! 541: else ! 542: { ! 543: bcopy (registers, &inferior_registers, 16 * 4); ! 544: bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers, ! 545: sizeof inferior_fp_registers.fps_regs); ! 546: inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)]; ! 547: inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)]; ! 548: bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)], ! 549: &inferior_fp_registers.fps_control, ! 550: sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs); ! 551: ! 552: ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers); ! 553: ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers); ! 554: } ! 555: } ! 556: ! 557: #else ! 558: #ifdef HP9K320 ! 559: ! 560: #define FP_REGISTER_ADDR_DIFF(u, regno) \ ! 561: (((char *) (FP_REGISTER_ADDR (u, regno))) - ((char *) &(u))) ! 562: ! 563: #define INFERIOR_AR0(u) \ ! 564: ((ptrace \ ! 565: (PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0)) \ ! 566: - KERNEL_U_ADDR) ! 567: ! 568: static void ! 569: fetch_inferior_register (regno, regaddr) ! 570: register int regno; ! 571: register unsigned int regaddr; ! 572: { ! 573: #ifndef HPUX_VERSION_5 ! 574: if (regno == PS_REGNUM) ! 575: { ! 576: union { int i; short s[2]; } ps_val; ! 577: int regval; ! 578: ! 579: ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0)); ! 580: regval = ps_val.s[0]; ! 581: supply_register (regno, ®val); ! 582: } ! 583: else ! 584: #endif /* not HPUX_VERSION_5 */ ! 585: { ! 586: char buf[MAX_REGISTER_RAW_SIZE]; ! 587: register int i; ! 588: ! 589: for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) ! 590: { ! 591: *(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0); ! 592: regaddr += sizeof (int); ! 593: } ! 594: supply_register (regno, buf); ! 595: } ! 596: return; ! 597: } ! 598: ! 599: static void ! 600: store_inferior_register_1 (regno, regaddr, value) ! 601: int regno; ! 602: unsigned int regaddr; ! 603: int value; ! 604: { ! 605: errno = 0; ! 606: ptrace (PT_WUAREA, inferior_pid, regaddr, value); ! 607: #if 0 ! 608: /* HP-UX randomly sets errno to non-zero for regno == 25. ! 609: However, the value is correctly written, so ignore errno. */ ! 610: if (errno != 0) ! 611: { ! 612: char string_buf[64]; ! 613: ! 614: sprintf (string_buf, "writing register number %d", regno); ! 615: perror_with_name (string_buf); ! 616: } ! 617: #endif ! 618: return; ! 619: } ! 620: ! 621: static void ! 622: store_inferior_register (regno, regaddr) ! 623: register int regno; ! 624: register unsigned int regaddr; ! 625: { ! 626: #ifndef HPUX_VERSION_5 ! 627: if (regno == PS_REGNUM) ! 628: { ! 629: union { int i; short s[2]; } ps_val; ! 630: ! 631: ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0)); ! 632: ps_val.s[0] = (read_register (regno)); ! 633: store_inferior_register_1 (regno, regaddr, ps_val.i); ! 634: } ! 635: else ! 636: #endif /* not HPUX_VERSION_5 */ ! 637: { ! 638: char buf[MAX_REGISTER_RAW_SIZE]; ! 639: register int i; ! 640: extern char registers[]; ! 641: ! 642: for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) ! 643: { ! 644: store_inferior_register_1 ! 645: (regno, regaddr, ! 646: (*(int *) ®isters[(REGISTER_BYTE (regno)) + i])); ! 647: regaddr += sizeof (int); ! 648: } ! 649: } ! 650: return; ! 651: } ! 652: ! 653: void ! 654: fetch_inferior_registers () ! 655: { ! 656: struct user u; ! 657: register int regno; ! 658: register unsigned int ar0_offset; ! 659: ! 660: ar0_offset = (INFERIOR_AR0 (u)); ! 661: for (regno = 0; (regno < FP0_REGNUM); regno++) ! 662: fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); ! 663: for (; (regno < NUM_REGS); regno++) ! 664: fetch_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno))); ! 665: } ! 666: ! 667: /* Store our register values back into the inferior. ! 668: If REGNO is -1, do this for all registers. ! 669: Otherwise, REGNO specifies which register (so we can save time). */ ! 670: ! 671: store_inferior_registers (regno) ! 672: register int regno; ! 673: { ! 674: struct user u; ! 675: register unsigned int ar0_offset; ! 676: ! 677: if (regno >= FP0_REGNUM) ! 678: { ! 679: store_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno))); ! 680: return; ! 681: } ! 682: ! 683: ar0_offset = (INFERIOR_AR0 (u)); ! 684: if (regno >= 0) ! 685: { ! 686: store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); ! 687: return; ! 688: } ! 689: ! 690: for (regno = 0; (regno < FP0_REGNUM); regno++) ! 691: store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); ! 692: for (; (regno < NUM_REGS); regno++) ! 693: store_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno))); ! 694: return; ! 695: } ! 696: ! 697: #else /* not HP9K320 */ ! 698: ! 699: void ! 700: fetch_inferior_registers () ! 701: { ! 702: register int regno; ! 703: register unsigned int regaddr; ! 704: char buf[MAX_REGISTER_RAW_SIZE]; ! 705: register int i; ! 706: ! 707: #ifdef UMAX_PTRACE ! 708: unsigned int offset = 0; ! 709: #else ! 710: struct user u; ! 711: unsigned int offset = (char *) &u.u_ar0 - (char *) &u; ! 712: offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; ! 713: #endif ! 714: ! 715: for (regno = 0; regno < NUM_REGS; regno++) ! 716: { ! 717: regaddr = register_addr (regno, offset); ! 718: for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) ! 719: { ! 720: *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0); ! 721: regaddr += sizeof (int); ! 722: } ! 723: supply_register (regno, buf); ! 724: } ! 725: } ! 726: ! 727: /* Store our register values back into the inferior. ! 728: If REGNO is -1, do this for all registers. ! 729: Otherwise, REGNO specifies which register (so we can save time). */ ! 730: ! 731: store_inferior_registers (regno) ! 732: int regno; ! 733: { ! 734: register unsigned int regaddr; ! 735: char buf[80]; ! 736: extern char registers[]; ! 737: int i; ! 738: ! 739: #ifdef UMAX_PTRACE ! 740: unsigned int offset = 0; ! 741: #else ! 742: struct user u; ! 743: unsigned int offset = (char *) &u.u_ar0 - (char *) &u; ! 744: offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; ! 745: #endif ! 746: ! 747: if (regno >= 0) ! 748: { ! 749: regaddr = register_addr (regno, offset); ! 750: for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) ! 751: { ! 752: errno = 0; ! 753: ptrace (6, inferior_pid, regaddr, ! 754: *(int *) ®isters[REGISTER_BYTE (regno) + i]); ! 755: if (errno != 0) ! 756: { ! 757: sprintf (buf, "writing register number %d(%d)", regno, i); ! 758: perror_with_name (buf); ! 759: } ! 760: regaddr += sizeof(int); ! 761: } ! 762: } ! 763: else for (regno = 0; regno < NUM_REGS; regno++) ! 764: { ! 765: regaddr = register_addr (regno, offset); ! 766: for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) ! 767: { ! 768: errno = 0; ! 769: ptrace (6, inferior_pid, regaddr, ! 770: *(int *) ®isters[REGISTER_BYTE (regno) + i]); ! 771: if (errno != 0) ! 772: { ! 773: sprintf (buf, "writing register number %d(%d)", regno, i); ! 774: perror_with_name (buf); ! 775: } ! 776: regaddr += sizeof(int); ! 777: } ! 778: } ! 779: } ! 780: ! 781: #endif /* not HP9K320 */ ! 782: #endif /* not NEW_SUN_PTRACE */ ! 783: ! 784: /* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory ! 785: in the NEW_SUN_PTRACE case. ! 786: It ought to be straightforward. But it appears that writing did ! 787: not write the data that I specified. I cannot understand where ! 788: it got the data that it actually did write. */ ! 789: ! 790: /* Copy LEN bytes from inferior's memory starting at MEMADDR ! 791: to debugger memory starting at MYADDR. */ ! 792: ! 793: read_inferior_memory (memaddr, myaddr, len) ! 794: CORE_ADDR memaddr; ! 795: char *myaddr; ! 796: int len; ! 797: { ! 798: register int i; ! 799: /* Round starting address down to longword boundary. */ ! 800: register CORE_ADDR addr = memaddr & - sizeof (int); ! 801: /* Round ending address up; get number of longwords that makes. */ ! 802: register int count ! 803: = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); ! 804: /* Allocate buffer of that many longwords. */ ! 805: register int *buffer = (int *) alloca (count * sizeof (int)); ! 806: ! 807: /* Read all the longwords */ ! 808: for (i = 0; i < count; i++, addr += sizeof (int)) ! 809: { ! 810: if (remote_debugging) ! 811: buffer[i] = remote_fetch_word (addr); ! 812: else ! 813: buffer[i] = ptrace (1, inferior_pid, addr, 0); ! 814: } ! 815: ! 816: /* Copy appropriate bytes out of the buffer. */ ! 817: bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); ! 818: } ! 819: ! 820: /* Copy LEN bytes of data from debugger memory at MYADDR ! 821: to inferior's memory at MEMADDR. ! 822: On failure (cannot write the inferior) ! 823: returns the value of errno. */ ! 824: ! 825: int ! 826: write_inferior_memory (memaddr, myaddr, len) ! 827: CORE_ADDR memaddr; ! 828: char *myaddr; ! 829: int len; ! 830: { ! 831: register int i; ! 832: /* Round starting address down to longword boundary. */ ! 833: register CORE_ADDR addr = memaddr & - sizeof (int); ! 834: /* Round ending address up; get number of longwords that makes. */ ! 835: register int count ! 836: = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); ! 837: /* Allocate buffer of that many longwords. */ ! 838: register int *buffer = (int *) alloca (count * sizeof (int)); ! 839: extern int errno; ! 840: ! 841: /* Fill start and end extra bytes of buffer with existing memory data. */ ! 842: ! 843: if (remote_debugging) ! 844: buffer[0] = remote_fetch_word (addr); ! 845: else ! 846: buffer[0] = ptrace (1, inferior_pid, addr, 0); ! 847: ! 848: if (count > 1) ! 849: { ! 850: if (remote_debugging) ! 851: buffer[count - 1] ! 852: = remote_fetch_word (addr + (count - 1) * sizeof (int)); ! 853: else ! 854: buffer[count - 1] ! 855: = ptrace (1, inferior_pid, ! 856: addr + (count - 1) * sizeof (int), 0); ! 857: } ! 858: ! 859: /* Copy data to be written over corresponding part of buffer */ ! 860: ! 861: bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); ! 862: ! 863: /* Write the entire buffer. */ ! 864: ! 865: for (i = 0; i < count; i++, addr += sizeof (int)) ! 866: { ! 867: errno = 0; ! 868: if (remote_debugging) ! 869: remote_store_word (addr, buffer[i]); ! 870: else ! 871: ptrace (4, inferior_pid, addr, buffer[i]); ! 872: if (errno) ! 873: return errno; ! 874: } ! 875: ! 876: return 0; ! 877: } ! 878: ! 879: static void ! 880: try_writing_regs_command () ! 881: { ! 882: register int i; ! 883: register int value; ! 884: extern int errno; ! 885: ! 886: if (inferior_pid == 0) ! 887: error ("There is no inferior process now."); ! 888: ! 889: for (i = 0; ; i += 2) ! 890: { ! 891: QUIT; ! 892: errno = 0; ! 893: value = ptrace (3, inferior_pid, i, 0); ! 894: ptrace (6, inferior_pid, i, value); ! 895: if (errno == 0) ! 896: { ! 897: printf (" Succeeded with address 0x%x; value 0x%x (%d).\n", ! 898: i, value, value); ! 899: } ! 900: else if ((i & 0377) == 0) ! 901: printf (" Failed at 0x%x.\n", i); ! 902: } ! 903: } ! 904: ! 905: static ! 906: initialize () ! 907: { ! 908: add_com ("term-status", class_obscure, term_status_command, ! 909: "Print info on inferior's saved terminal status."); ! 910: ! 911: add_com ("try-writing-regs", class_obscure, try_writing_regs_command, ! 912: "Try writing all locations in inferior's system block.\n\ ! 913: Report which ones can be written."); ! 914: ! 915: add_com ("kill", class_run, kill_command, ! 916: "Kill execution of program being debugged."); ! 917: ! 918: inferior_pid = 0; ! 919: ! 920: ioctl (0, TIOCGETP, &sg_ours); ! 921: fcntl (0, F_GETFL, tflags_ours); ! 922: ! 923: #ifdef TIOCGLTC ! 924: ioctl (0, TIOCGETC, &tc_ours); ! 925: ioctl (0, TIOCGLTC, <c_ours); ! 926: ioctl (0, TIOCLGET, &lmode_ours); ! 927: #endif /* TIOCGLTC */ ! 928: ! 929: #ifdef TIOCGPGRP ! 930: ioctl (0, TIOCGPGRP, &pgrp_ours); ! 931: #endif /* TIOCGPGRP */ ! 932: ! 933: terminal_is_ours = 1; ! 934: } ! 935: ! 936: END_FILE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.