* defs.h (make_cleanup): Change PTR to void * when inside PARAMS.
authorJim Kingdon <jkingdon@engr.sgi.com>
Sat, 18 Sep 1993 19:15:36 +0000 (19:15 +0000)
committerJim Kingdon <jkingdon@engr.sgi.com>
Sat, 18 Sep 1993 19:15:36 +0000 (19:15 +0000)
Some of the following is in #ifdef CALL_DUMMY_BREAKPOINT_OFFSET.
* breakpoint.h (enum bptype): Add bp_call_dummy.
(struct bpstat_what): Add call_dummy field.
* infrun.c (wait_for_inferior): Deal with it.
* breakpoint.c (bpstat_what): Deal with call dummy breakpoint.
* infcmd.c (run_stack_dummy): Set the call dummy breakpoint.
* config/sparc/tm-sparc.h: Define CALL_DUMMY_BREAKPOINT_OFFSET.

gdb/ChangeLog
gdb/breakpoint.c
gdb/breakpoint.h
gdb/config/sparc/tm-sparc.h
gdb/defs.h
gdb/infcmd.c
gdb/infrun.c

index 615adae8d6dc454f575891559986186fb0d24442..2a174a59eb70277f243f10c9b913eb2211d8d630 100644 (file)
@@ -1,4 +1,14 @@
-Fri Sep 17 10:10:05 1993  Jim Kingdon  (kingdon@rtl.cygnus.com)
+Sat Sep 18 10:13:18 1993  Jim Kingdon  (kingdon@poseidon.cygnus.com)
+
+       * defs.h (make_cleanup): Change PTR to void * when inside PARAMS.
+
+       Some of the following is in #ifdef CALL_DUMMY_BREAKPOINT_OFFSET.
+       * breakpoint.h (enum bptype): Add bp_call_dummy.
+       (struct bpstat_what): Add call_dummy field.
+       * infrun.c (wait_for_inferior): Deal with it.
+       * breakpoint.c (bpstat_what): Deal with call dummy breakpoint.
+       * infcmd.c (run_stack_dummy): Set the call dummy breakpoint.
+       * config/sparc/tm-sparc.h: Define CALL_DUMMY_BREAKPOINT_OFFSET.
 
        * remote-sim.h: New file.
        * remote-sim.c: Add remote debug feature.  Rename stuff to distinguish
index 5e955c00894a51bfd18be0ec37b43c1bcd9ffc45..bec31eb89091ef5e71aa6cad11d507ce01b3d8f3 100644 (file)
@@ -1221,6 +1221,12 @@ bpstat_what (bs)
 #define err BPSTAT_WHAT_STOP_NOISY
 
   /* Given an old action and a class, come up with a new action.  */
+  /* One interesting property of this table is that wp_silent is the same
+     as bp_silent and wp_noisy is the same as bp_noisy.  That is because
+     after stopping, the check for whether to step over a breakpoint
+     (BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without
+     reference to how we stopped.  We retain separate wp_silent and bp_silent
+     codes in case we want to change that someday.  */
   static const enum bpstat_what_main_action
     table[(int)class_last][(int)BPSTAT_WHAT_LAST] =
       {
@@ -1245,7 +1251,7 @@ bpstat_what (bs)
 #undef clrlrs
 #undef err
   enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
-  int found_step_resume = 0;
+  struct bpstat_what retval;
 
   for (; bs != NULL; bs = bs->next)
     {
@@ -1297,7 +1303,7 @@ bpstat_what (bs)
          if (bs->stop)
            {
 #endif
-             found_step_resume = 1;
+             retval.step_resume = 1;
              /* We don't handle this via the main_action.  */
              bs_class = no_effect;
 #if 0
@@ -1307,15 +1313,16 @@ bpstat_what (bs)
            bs_class = bp_nostop;
 #endif
          break;
+       case bp_call_dummy:
+         /* Make sure the action is stop (silent or noisy), so infrun.c
+            pops the dummy frame.  */
+         bs_class = bp_silent;
+         retval.call_dummy = 1;
        }
       current_action = table[(int)bs_class][(int)current_action];
     }
-  {
-    struct bpstat_what retval;
-    retval.main_action = current_action;
-    retval.step_resume = found_step_resume;
-    return retval;
-  }
+  retval.main_action = current_action;
+  return retval;
 }
 
 /* Nonzero if we should step constantly (e.g. watchpoints on machines
@@ -1347,7 +1354,7 @@ breakpoint_1 (bnum, allflag)
   CORE_ADDR last_addr = (CORE_ADDR)-1;
   int found_a_breakpoint = 0;
   static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint",
-                             "longjmp", "longjmp resume"};
+                             "longjmp", "longjmp resume", "step resume"};
   static char *bpdisps[] = {"del", "dis", "keep"};
   static char bpenables[] = "ny";
   char wrap_indent[80];
@@ -1379,11 +1386,13 @@ breakpoint_1 (bnum, allflag)
          case bp_watchpoint:
            print_expression (b->exp, stdout);
            break;
+
          case bp_breakpoint:
          case bp_until:
          case bp_finish:
          case bp_longjmp:
          case bp_longjmp_resume:
+         case bp_step_resume:
            if (addressprint)
              printf_filtered ("%s ", local_hex_string_custom(b->address, "08"));
 
@@ -1403,8 +1412,6 @@ breakpoint_1 (bnum, allflag)
              }
            else
              print_address_symbolic (b->address, stdout, demangle, " ");
-           /* intentional fall-through */
-         case bp_step_resume: /* do nothing. */
            break;
          }
 
index 3949777c69615ed6b2d0cd3f7ced67e7dcb69439..5c7e69d116d3dad10a5f11f5e2f9ebd11a47a8c5 100644 (file)
@@ -29,7 +29,122 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #define        BREAKPOINT_MAX  16
 \f
-/* The follow stuff is an abstract data type "bpstat" ("breakpoint status").
+/* Type of breakpoint. */
+/* FIXME In the future, we should fold all other breakpoint-like things into
+   here.  This includes:
+
+   * call-dummy (the breakpoint at the end of a subroutine stub that gdb
+      uses to call functions in the target) (definately). 
+
+   * single-step (for machines where we have to simulate single stepping)
+      (probably, though perhaps it is better for it to look as much as
+      possible like a single-step to wait_for_inferior).  */
+
+enum bptype {
+  bp_breakpoint,               /* Normal breakpoint */
+  bp_until,                    /* used by until command */
+  bp_finish,                   /* used by finish command */
+  bp_watchpoint,               /* Watchpoint */
+  bp_longjmp,                  /* secret breakpoint to find longjmp() */
+  bp_longjmp_resume,           /* secret breakpoint to escape longjmp() */
+
+  /* Used by wait_for_inferior for stepping over subroutine calls, for
+     stepping over signal handlers, and for skipping prologues.  */
+  bp_step_resume,
+
+  /* The breakpoint at the end of a call dummy.  */
+  bp_call_dummy
+};
+
+/* States of enablement of breakpoint. */
+
+enum enable { disabled, enabled};
+
+/* Disposition of breakpoint.  Ie: what to do after hitting it. */
+
+enum bpdisp {
+  delete,                      /* Delete it */
+  disable,                     /* Disable it */
+  donttouch                    /* Leave it alone */
+};
+
+/* Note that the ->silent field is not currently used by any commands
+   (though the code is in there if it was to be, and set_raw_breakpoint
+   does set it to 0).  I implemented it because I thought it would be
+   useful for a hack I had to put in; I'm going to leave it in because
+   I can see how there might be times when it would indeed be useful */
+
+/* This is for a breakpoint or a watchpoint.  */
+
+struct breakpoint
+{
+  struct breakpoint *next;
+  /* Type of breakpoint. */
+  enum bptype type;
+  /* Zero means disabled; remember the info but don't break here.  */
+  enum enable enable;
+  /* What to do with this breakpoint after we hit it. */
+  enum bpdisp disposition;
+  /* Number assigned to distinguish breakpoints.  */
+  int number;
+
+  /* Address to break at, or NULL if not a breakpoint.  */
+  CORE_ADDR address;
+
+  /* Line number of this address.  Only matters if address is
+     non-NULL.  */
+
+  int line_number;
+
+  /* Source file name of this address.  Only matters if address is
+     non-NULL.  */
+
+  char *source_file;
+
+  /* Non-zero means a silent breakpoint (don't print frame info
+     if we stop here). */
+  unsigned char silent;
+  /* Number of stops at this breakpoint that should
+     be continued automatically before really stopping.  */
+  int ignore_count;
+  /* "Real" contents of byte where breakpoint has been inserted.
+     Valid only when breakpoints are in the program.  Under the complete
+     control of the target insert_breakpoint and remove_breakpoint routines.
+     No other code should assume anything about the value(s) here.  */
+  char shadow_contents[BREAKPOINT_MAX];
+  /* Nonzero if this breakpoint is now inserted.  Only matters if address
+     is non-NULL.  */
+  char inserted;
+  /* Nonzero if this is not the first breakpoint in the list
+     for the given address.  Only matters if address is non-NULL.  */
+  char duplicate;
+  /* Chain of command lines to execute when this breakpoint is hit.  */
+  struct command_line *commands;
+  /* Stack depth (address of frame).  If nonzero, break only if fp
+     equals this.  */
+  FRAME_ADDR frame;
+  /* Conditional.  Break only if this expression's value is nonzero.  */
+  struct expression *cond;
+
+  /* String we used to set the breakpoint (malloc'd).  Only matters if
+     address is non-NULL.  */
+  char *addr_string;
+  /* String form of the breakpoint condition (malloc'd), or NULL if there
+     is no condition.  */
+  char *cond_string;
+  /* String form of exp (malloc'd), or NULL if none.  */
+  char *exp_string;
+
+  /* The expression we are watching, or NULL if not a watchpoint.  */
+  struct expression *exp;
+  /* The largest block within which it is valid, or NULL if it is
+     valid anywhere (e.g. consists just of global symbols).  */
+  struct block *exp_valid_block;
+  /* Value of the watchpoint the last time we checked it.  */
+  value val;
+};
+\f
+/* The following stuff is an abstract data type "bpstat" ("breakpoint status").
    This provides the ability to determine whether we have stopped at a
    breakpoint, and what we should do about it.  */
 
@@ -49,9 +164,11 @@ extern bpstat bpstat_copy PARAMS ((bpstat));
    breakpoint (if we hit a breakpoint).  */
 /* FIXME:  prototypes uses equivalence between FRAME_ADDR and CORE_ADDR */
 extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, CORE_ADDR));
+\f
+/* This bpstat_what stuff tells wait_for_inferior what to do with a
+   breakpoint (a challenging task).  */
 
-/* Return values from bpstat_what.  */
-enum bpstat_what {
+enum bpstat_what_main_action {
   /* Perform various other tests; that is, this bpstat does not
      say to perform any action (e.g. failed watchpoint and nothing
      else).  */
@@ -70,7 +187,9 @@ enum bpstat_what {
   BPSTAT_WHAT_STOP_NOISY,
 
   /* Remove breakpoints, single step once, then put them back in and
-     go back to what we were doing.  */
+     go back to what we were doing.  It's possible that this should be
+     removed from the main_action and put into a separate field, to more
+     cleanly handle BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE.  */
   BPSTAT_WHAT_SINGLE,
 
   /* Set longjmp_resume breakpoint, remove all other breakpoints,
@@ -90,9 +209,24 @@ enum bpstat_what {
   BPSTAT_WHAT_LAST
 };
 
-/* Tell what to do about this bpstat.  */
-enum bpstat_what bpstat_what PARAMS ((bpstat));
+struct bpstat_what {
+  enum bpstat_what_main_action main_action : 4;
+
+  /* Did we hit the step resume breakpoint?  This is separate from the
+     main_action to allow for it to be combined with any of the main
+     actions.  */
+  unsigned int step_resume : 1;
+
+  /* Did we hit a call dummy breakpoint?  This only goes with a main_action
+     of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of
+     continuing from a call dummy without popping the frame is not a
+     useful one).  */
+  unsigned int call_dummy : 1;
+};
 
+/* Tell what to do about this bpstat.  */
+struct bpstat_what bpstat_what PARAMS ((bpstat));
+\f
 /* Find the bpstat associated with a breakpoint.  NULL otherwise. */
 bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *));
 
@@ -119,7 +253,9 @@ extern int bpstat_print PARAMS ((bpstat));
    Return 0 if passed a bpstat which does not indicate any breakpoints.  */
 extern int bpstat_num PARAMS ((bpstat *));
 
-/* Perform actions associated with having stopped at *BSP.  */
+/* Perform actions associated with having stopped at *BSP.  Actually, we just
+   use this for breakpoint commands.  Perhaps other actions will go here
+   later, but this is executed at a late time (from the command loop).  */
 extern void bpstat_do_actions PARAMS ((bpstat *));
 
 /* Modify BS so that the actions will not be performed.  */
@@ -150,112 +286,6 @@ struct bpstat
   int (*print_it) PARAMS((bpstat bs));
 };
 \f
-/* Type of breakpoint. */
-/* FIXME In the future, we should fold all other breakpoint-like things into
-   here.  This includes:
-
-   1) single-step (for machines where we have to simulate single stepping),
-   2) step-resume (for 'next'ing over subroutine calls),
-   3) call-dummy (the breakpoint at the end of a subroutine stub that gdb
-      uses to call functions in the target).
-
-   I definately agree with (2) and (3); I'm not as sure about (1)
-   (it is a low-level thing, perhaps the best thing is that it looks
-   as much as possible like a single-step to wait_for_inferior)
-   -kingdon, 8 Apr 93.
-*/
-
-enum bptype {
-  bp_breakpoint,               /* Normal breakpoint */
-  bp_until,                    /* used by until command */
-  bp_finish,                   /* used by finish command */
-  bp_watchpoint,               /* Watchpoint */
-  bp_longjmp,                  /* secret breakpoint to find longjmp() */
-  bp_longjmp_resume            /* secret breakpoint to escape longjmp() */
-};
-
-/* States of enablement of breakpoint. */
-
-enum enable { disabled, enabled};
-
-/* Disposition of breakpoint.  Ie: what to do after hitting it. */
-
-enum bpdisp {
-  delete,                      /* Delete it */
-  disable,                     /* Disable it */
-  donttouch                    /* Leave it alone */
-};
-
-/* Note that the ->silent field is not currently used by any commands
-   (though the code is in there if it was to be, and set_raw_breakpoint
-   does set it to 0).  I implemented it because I thought it would be
-   useful for a hack I had to put in; I'm going to leave it in because
-   I can see how there might be times when it would indeed be useful */
-
-/* This is for a breakpoint or a watchpoint.  */
-
-struct breakpoint
-{
-  struct breakpoint *next;
-  /* Type of breakpoint. */
-  enum bptype type;
-  /* Zero means disabled; remember the info but don't break here.  */
-  enum enable enable;
-  /* What to do with this breakpoint after we hit it. */
-  enum bpdisp disposition;
-  /* Number assigned to distinguish breakpoints.  */
-  int number;
-  /* Address to break at, or NULL if not a breakpoint.  */
-  CORE_ADDR address;
-  /* Line number of this address.  Redundant.  Only matters if address
-     is non-NULL.  */
-  int line_number;
-  /* Symtab of file of this address.  Redundant.  Only matters if address
-     is non-NULL.  */
-  struct symtab *symtab;
-  /* Non-zero means a silent breakpoint (don't print frame info
-     if we stop here). */
-  unsigned char silent;
-  /* Number of stops at this breakpoint that should
-     be continued automatically before really stopping.  */
-  int ignore_count;
-  /* "Real" contents of byte where breakpoint has been inserted.
-     Valid only when breakpoints are in the program.  Under the complete
-     control of the target insert_breakpoint and remove_breakpoint routines.
-     No other code should assume anything about the value(s) here.  */
-  char shadow_contents[BREAKPOINT_MAX];
-  /* Nonzero if this breakpoint is now inserted.  Only matters if address
-     is non-NULL.  */
-  char inserted;
-  /* Nonzero if this is not the first breakpoint in the list
-     for the given address.  Only matters if address is non-NULL.  */
-  char duplicate;
-  /* Chain of command lines to execute when this breakpoint is hit.  */
-  struct command_line *commands;
-  /* Stack depth (address of frame).  If nonzero, break only if fp
-     equals this.  */
-  FRAME_ADDR frame;
-  /* Conditional.  Break only if this expression's value is nonzero.  */
-  struct expression *cond;
-
-  /* String we used to set the breakpoint (malloc'd).  Only matters if
-     address is non-NULL.  */
-  char *addr_string;
-  /* String form of the breakpoint condition (malloc'd), or NULL if there
-     is no condition.  */
-  char *cond_string;
-  /* String form of exp (malloc'd), or NULL if none.  */
-  char *exp_string;
-
-  /* The expression we are watching, or NULL if not a watchpoint.  */
-  struct expression *exp;
-  /* The largest block within which it is valid, or NULL if it is
-     valid anywhere (e.g. consists just of global symbols).  */
-  struct block *exp_valid_block;
-  /* Value of the watchpoint the last time we checked it.  */
-  value val;
-};
-\f
 /* Prototypes for breakpoint-related functions.  */
 
 #ifdef __STDC__                /* Forward declarations for prototypes */
index 70f1f20c4ab7fd7f801197dd6b2af81f24b7d43f..09193f8763a5e8a05fcc3f5dfc1833e4803dcbb4 100644 (file)
@@ -554,6 +554,8 @@ arguments.  */
 
 #define CALL_DUMMY_START_OFFSET 148
 
+#define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + (8 * 4))
+
 #define CALL_DUMMY_STACK_ADJUST 68
 
 /* Insert the specified number of args and function address
index f7b3d6129cd40238a18f15fa1d07232d5efb6121..4791f3abd05e6d48c2a295691e0957b866e914d4 100644 (file)
@@ -180,7 +180,7 @@ discard_cleanups PARAMS ((struct cleanup *));
 
    Should be, once all calls and called-functions are cleaned up:
 extern struct cleanup *
-make_cleanup PARAMS ((void (*function) (PTR), PTR));
+make_cleanup PARAMS ((void (*function) (void *), void *));
 
    Until then, lint and/or various type-checking compiler options will
    complain about make_cleanup calls.  It'd be wrong to just cast things,
index c0c5b7d243655e9751426b0d37d52990bca3e6ac..8cd99404c6e2fff81460306a6283a19ae5680cba 100644 (file)
@@ -497,6 +497,15 @@ signal_command (signum_exp, from_tty)
   proceed (stop_pc, signum, 0);
 }
 
+/* Call breakpoint_auto_delete on the current contents of the bpstat
+   pointed to by arg (which is really a bpstat *).  */
+void
+breakpoint_auto_delete_contents (arg)
+     PTR arg;
+{
+  breakpoint_auto_delete (*(bpstat *)arg);
+}
+
 /* Execute a "stack dummy", a piece of code stored in the stack
    by the debugger to be executed in the inferior.
 
@@ -522,6 +531,8 @@ run_stack_dummy (addr, buffer)
      CORE_ADDR addr;
      char buffer[REGISTER_BYTES];
 {
+  struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+
   /* Now proceed, having reached the desired place.  */
   clear_proceed_status ();
   if (stack_dummy_testing & 4)
@@ -529,9 +540,38 @@ run_stack_dummy (addr, buffer)
       POP_FRAME;
       return(0);
     }
+#ifdef CALL_DUMMY_BREAKPOINT_OFFSET
+  {
+    struct breakpoint *bpt;
+    struct symtab_and_line sal;
+
+    sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET;
+    sal.symtab = NULL;
+    sal.line = 0;
+
+    /* If defined, CALL_DUMMY_BREAKPOINT_OFFSET is where we need to put
+       a breakpoint instruction.  If not, the call dummy already has the
+       breakpoint instruction in it.
+
+       addr is the address of the call dummy plus the CALL_DUMMY_START_OFFSET,
+       so we need to subtract the CALL_DUMMY_START_OFFSET.  */
+    bpt = set_momentary_breakpoint (sal,
+                                   NULL,
+                                   bp_call_dummy);
+    bpt->disposition = delete;
+
+    /* If all error()s out of proceed ended up calling normal_stop (and
+       perhaps they should; it already does in the special case of error
+       out of resume()), then we wouldn't need this.  */
+    make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat);
+  }
+#endif /* CALL_DUMMY_BREAKPOINT_OFFSET.  */
+
   proceed_to_finish = 1;       /* We want stop_registers, please... */
   proceed (addr, 0, 0);
 
+  discard_cleanups (old_cleanups);
+
   if (!stop_stack_dummy)
     return 1;
 
index a9d8a64cd472ccb280efded82ac6ee49823c7042..3656c98ed9489bb68fea7250b849099b2ca6f7b5 100644 (file)
@@ -721,7 +721,9 @@ wait_for_inferior ()
            random_signal
              = !(bpstat_explains_signal (stop_bpstat)
                  || trap_expected
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
                  || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET.  */
                  || (step_range_end && step_resume_breakpoint == NULL));
          else
            {
@@ -730,7 +732,9 @@ wait_for_inferior ()
                    /* End of a stack dummy.  Some systems (e.g. Sony
                       news) give another signal besides SIGTRAP,
                       so check here as well as above.  */
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
                    || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET.  */
                    );
              if (!random_signal)
                stop_signal = SIGTRAP;
@@ -793,6 +797,14 @@ wait_for_inferior ()
 
        what = bpstat_what (stop_bpstat);
 
+       if (what.call_dummy)
+         {
+           stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+           trap_expected_after_continue = 1;
+#endif
+         }
+
        switch (what.main_action)
          {
          case BPSTAT_WHAT_SET_LONGJMP_RESUME:
@@ -887,6 +899,12 @@ wait_for_inferior ()
         test for stepping.  But, if not stepping,
         do not stop.  */
 
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+      /* This is the old way of detecting the end of the stack dummy.
+        An architecture which defines CALL_DUMMY_BREAKPOINT_OFFSET gets
+        handled above.  As soon as we can test it on all of them, all
+        architectures should define it.  */
+
       /* If this is the breakpoint at the end of a stack dummy,
         just stop silently, unless the user was doing an si/ni, in which
         case she'd better know what she's doing.  */
@@ -901,7 +919,8 @@ wait_for_inferior ()
 #endif
          break;
        }
-      
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET.  */
+
       if (step_resume_breakpoint)
        /* Having a step-resume breakpoint overrides anything
           else having to do with stepping commands until
@@ -1081,8 +1100,7 @@ step_into_function:
                 since on some machines the prologue
                 is where the new fp value is established.  */
              step_resume_breakpoint =
-               set_momentary_breakpoint (sr_sal, (CORE_ADDR)0,
-                                         bp_step_resume);
+               set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
              if (breakpoints_inserted)
                insert_breakpoints ();