diff options
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/inflow.c | 43 | ||||
-rw-r--r-- | gdb/target.c | 141 |
3 files changed, 161 insertions, 28 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5e85142..7ad1e1a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +Wed Sep 29 10:52:19 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * target.c (target_detach): Call generic_mourn_inferior. + * inflow.c (generic_mourn_inferior): Call flush_cached_frames. + Tue Sep 28 23:08:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com) * dbxread.c, coffread.c, elfread.c: A few changes to comments. diff --git a/gdb/inflow.c b/gdb/inflow.c index a591d80..fddfe84 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -78,8 +78,9 @@ static void (*sigquit_ours) (); static char *inferior_thisrun_terminal; -/* Nonzero if our terminal settings are in effect. - Zero if the inferior's settings are in effect. */ +/* Nonzero if our terminal settings are in effect. Zero if the + inferior's settings are in effect. Ignored if !gdb_has_a_terminal + (). */ static int terminal_is_ours; @@ -100,7 +101,9 @@ gdb_has_a_terminal () all!). Can't do this in _initialize_inflow because SERIAL_FDOPEN won't work until the serial_ops_list is initialized. */ +#ifdef F_GETFL tflags_ours = fcntl (0, F_GETFL, 0); +#endif gdb_has_a_terminal_flag = no; stdin_serial = SERIAL_FDOPEN (0); @@ -130,20 +133,20 @@ static void terminal_ours_1 PARAMS ((int)); void terminal_init_inferior () { - /* Make sure that our_ttystate (etc) are initialized. */ - gdb_has_a_terminal (); - - /* We could just as well copy our_ttystate (if we felt like adding - a new function SERIAL_COPY_TTY_STATE). */ - if (inferior_ttystate) - free (inferior_ttystate); - inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial); - SERIAL_SET_PROCESS_GROUP (stdin_serial, inferior_ttystate, inferior_pid); - - /* Make sure that next time we call terminal_inferior (which will be - before the program runs, as it needs to be), we install the new - process group. */ - terminal_is_ours = 1; + if (gdb_has_a_terminal ()) + { + /* We could just as well copy our_ttystate (if we felt like adding + a new function SERIAL_COPY_TTY_STATE). */ + if (inferior_ttystate) + free (inferior_ttystate); + inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial); + SERIAL_SET_PROCESS_GROUP (stdin_serial, inferior_ttystate, inferior_pid); + + /* Make sure that next time we call terminal_inferior (which will be + before the program runs, as it needs to be), we install the new + process group. */ + terminal_is_ours = 1; + } } /* Put the inferior's terminal settings into effect. @@ -157,12 +160,14 @@ terminal_inferior () { int result; +#ifdef F_GETFL /* Is there a reason this is being done twice? It happens both places we use F_SETFL, so I'm inclined to think perhaps there is some reason, however perverse. Perhaps not though... */ result = fcntl (0, F_SETFL, tflags_inferior); result = fcntl (0, F_SETFL, tflags_inferior); OOPSY ("fcntl F_SETFL"); +#endif /* Because we were careful to not change in or out of raw mode in terminal_ours, we will not change in our out of raw mode with @@ -274,6 +279,7 @@ terminal_ours_1 (output_only) signal (SIGQUIT, sigquit_ours); } +#ifdef F_GETFL tflags_inferior = fcntl (0, F_GETFL, 0); /* Is there a reason this is being done twice? It happens both @@ -281,6 +287,7 @@ terminal_ours_1 (output_only) is some reason, however perverse. Perhaps not though... */ result = fcntl (0, F_SETFL, tflags_ours); result = fcntl (0, F_SETFL, tflags_ours); +#endif result = result; /* lint */ } @@ -384,7 +391,6 @@ void new_tty () { register int tty; - void (*osigttou) (); if (inferior_thisrun_terminal == 0) return; @@ -396,6 +402,8 @@ new_tty () tty = open("/dev/tty", O_RDWR); if (tty > 0) { + void (*osigttou) (); + osigttou = (void (*)()) signal(SIGTTOU, SIG_IGN); ioctl(tty, TIOCNOTTY, 0); close(tty); @@ -470,6 +478,7 @@ generic_mourn_inferior () #endif reopen_exec_file (); + flush_cached_frames (); if (target_has_stack) { set_current_frame ( create_new_frame (read_register (FP_REGNUM), read_pc ())); diff --git a/gdb/target.c b/gdb/target.c index 5af8aae..e8eddef 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1,5 +1,5 @@ /* Select target systems and architectures at runtime for GDB. - Copyright 1990, 1992 Free Software Foundation, Inc. + Copyright 1990, 1992, 1993 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB. @@ -95,6 +95,7 @@ struct target_ops dummy_target = {"None", "None", "", find_default_create_inferior, /* create_inferior */ 0, /* mourn_inferior */ 0, /* can_run */ + 0, /* notice_signals */ dummy_stratum, 0, /* stratum, next */ 0, 0, 0, 0, 0, /* all mem, mem, stack, regs, exec */ 0, 0, /* section pointers */ @@ -335,6 +336,7 @@ cleanup_target (t) de_fault (to_create_inferior, maybe_kill_then_create_inferior); de_fault (to_mourn_inferior, (void (*)())noprocess); de_fault (to_can_run, return_zero); + de_fault (to_notice_signals, (void (*)())ignore); de_fault (to_next, 0); de_fault (to_has_all_memory, 0); de_fault (to_has_memory, 0); @@ -420,10 +422,16 @@ pop_target () { (current_target->to_close)(0); /* Let it clean up */ current_target = current_target->to_next; +#if 0 + /* This will dump core if ever called--push_target expects current_target + to be non-NULL. But I don't think it's needed; I don't see how the + dummy_target could ever be removed from the stack. */ if (!current_target) /* At bottom, push dummy. */ push_target (&dummy_target); +#endif } +#undef MIN #define MIN(A, B) (((A) <= (B)) ? (A) : (B)) /* target_read_string -- read a null terminated string from MEMADDR in target. @@ -466,15 +474,15 @@ target_read_string (memaddr, myaddr, len) return origlen; } -/* Move memory to or from the targets. Iterate until all of it has - been moved, if necessary. The top target gets priority; anything - it doesn't want, is offered to the next one down, etc. Note the - business with curlen: if an early target says "no, but I have a - boundary overlapping this xfer" then we shorten what we offer to - the subsequent targets so the early guy will get a chance at the - tail before the subsequent ones do. +/* Read LEN bytes of target memory at address MEMADDR, placing the results in + GDB's memory at MYADDR. Returns either 0 for success or an errno value + if any error occurs. - Result is 0 or errno value. */ + If an error occurs, no guarantee is made about the contents of the data at + MYADDR. In particular, the caller should not depend upon partial reads + filling the buffer with good data. There is no way for the caller to know + how much good data might have been transfered anyway. Callers that can + deal with partial reads should call target_read_memory_partial. */ int target_read_memory (memaddr, myaddr, len) @@ -485,6 +493,48 @@ target_read_memory (memaddr, myaddr, len) return target_xfer_memory (memaddr, myaddr, len, 0); } +/* Read LEN bytes of target memory at address MEMADDR, placing the results + in GDB's memory at MYADDR. Returns a count of the bytes actually read, + and optionally an errno value in the location pointed to by ERRNOPTR + if ERRNOPTR is non-null. */ + +int +target_read_memory_partial (memaddr, myaddr, len, errnoptr) + CORE_ADDR memaddr; + char *myaddr; + int len; + int *errnoptr; +{ + int nread; /* Number of bytes actually read. */ + int errcode; /* Error from last read. */ + + /* First try a complete read. */ + errcode = target_xfer_memory (memaddr, myaddr, len, 0); + if (errcode == 0) + { + /* Got it all. */ + nread = len; + } + else + { + /* Loop, reading one byte at a time until we get as much as we can. */ + for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--) + { + errcode = target_xfer_memory (memaddr++, myaddr++, 1, 0); + } + /* If an error, the last read was unsuccessful, so adjust count. */ + if (errcode != 0) + { + nread--; + } + } + if (errnoptr != NULL) + { + *errnoptr = errcode; + } + return (nread); +} + int target_write_memory (memaddr, myaddr, len) CORE_ADDR memaddr; @@ -494,6 +544,16 @@ target_write_memory (memaddr, myaddr, len) return target_xfer_memory (memaddr, myaddr, len, 1); } +/* Move memory to or from the targets. Iterate until all of it has + been moved, if necessary. The top target gets priority; anything + it doesn't want, is offered to the next one down, etc. Note the + business with curlen: if an early target says "no, but I have a + boundary overlapping this xfer" then we shorten what we offer to + the subsequent targets so the early guy will get a chance at the + tail before the subsequent ones do. + + Result is 0 or errno value. */ + int target_xfer_memory (memaddr, myaddr, len, write) CORE_ADDR memaddr; @@ -504,7 +564,11 @@ target_xfer_memory (memaddr, myaddr, len, write) int curlen; int res; struct target_ops *t; - + + /* to_xfer_memory is not guaranteed to set errno, even when it returns + 0. */ + errno = 0; + /* The quick case is that the top target does it all. */ res = current_target->to_xfer_memory (memaddr, myaddr, len, write, current_target); @@ -596,6 +660,25 @@ target_preopen (from_tty) } } +/* Detach a target after doing deferred register stores. */ + +void +target_detach (args, from_tty) + char *args; + int from_tty; +{ + /* Handle any optimized stores to the inferior. */ +#ifdef DO_DEFERRED_STORES + DO_DEFERRED_STORES; +#endif + (current_target->to_detach) (args, from_tty); + + /* It is correct to do this because the top process can never be as high + as process_stratum now. This is needed at least in the case where + we detach a corefile, and thus need to flush the frame cache. */ + generic_mourn_inferior (); +} + /* Look through the list of possible targets for a target that can execute a run or attach command without any other data. This is used to locate the default process stratum. @@ -607,7 +690,7 @@ find_default_run_target (do_mesg) char *do_mesg; { struct target_ops **t; - struct target_ops *runable; + struct target_ops *runable = NULL; int count; count = 0; @@ -659,6 +742,42 @@ return_zero () return 0; } +struct target_ops * +find_core_target () +{ + struct target_ops **t; + struct target_ops *runable = NULL; + int count; + + count = 0; + + for (t = target_structs; t < target_structs + target_struct_size; + ++t) + { + if ((*t)->to_stratum == core_stratum) + { + runable = *t; + ++count; + } + } + + return(count == 1 ? runable : NULL); +} + +/* Convert a normal process ID to a string. Returns the string in a static + buffer. */ + +char * +normal_pid_to_str (pid) + int pid; +{ + static char buf[30]; + + sprintf (buf, "process %d", pid); + + return buf; +} + static char targ_desc[] = "Names of targets and files being debugged.\n\ Shows the entire stack of targets currently in use (including the exec-file,\n\ |