This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Observer mode, for real this time


Here is the complete patch for observer mode and permission flags, as originally presented in http://sourceware.org/ml/gdb-patches/2010-04/msg00961.html . This patch includes some behavioral tweaks made in response to user feedback, and a bit of testsuite - not very much though, since full support requires a target-side agent that can start up and interact with GDB without bothering the inferior.

Stan

2010-06-04 Stan Shebs <stan@codesourcery.com>

Add per-operation permission flags.

   * target.h (struct target_ops): New method to_set_permissions.
   (target_set_permissions): New macro.
   (target_insert_breakpoint): Change macro to function.
   (target_remove_breakpoint): Ditto.
   (target_stop): Ditto.
   (may_write_registers): Declare.
   (may_write_memory): Declare.
   (may_insert_breakpoints): Declare.
   (may_insert_tracepoints): Declare.
   (may_insert_fast_tracepoints): Declare.
   (may_stop): Declare.
   * target.c (may_write_registers, may_write_registers_1): New globals.
   (may_write_memory, may_write_memory_1): New globals.
   (may_insert_breakpoints, may_insert_breakpoints_1): New globals.
   (may_insert_tracepoints, may_insert_tracepoints_1): New globals.
   (may_insert_fast_tracepoints, may_insert_fast_tracepoints_1): New
   globals.
   (may_stop, may_stop_1): New global.
   (target_xfer_partial): Test for write permission.
   (target_store_registers): Ditto.
   (target_insert_breakpoint): New function.
   (target_remove_breakpoint): New function.
   (target_stop): New function.
   (_initialize_targets): Add new set/show variables.
   (set_write_memory_permission): New function.
   (update_target_permissions): New function.
   (set_target_permissions): New function.
   (update_current_target): Default to_set_permissions.
   (_initialize_targets): Use new globals and setter function.
   * tracepoint.c (start_tracing): Test for permission.
   * inferior.h (update_observer_mode): Declare.
   * infrun.c (non_stop_1): Define earlier.
   (observer_mode, observer_mode_1): New globals.
   (set_observer_mode, show_observer_mode): New functions.
   (update_observer_mode): New function.
   (_initialize_infrun): Define "set observer" command.
   * remote.c (PACKET_QAllow): New optional packet.
   (remote_protocol_features): Add QAllow.
   (remote_set_permissions): New function.
   (remote_start_remote): Call it.
   (init_remote_ops): Add it to target vector.
   (_initialize_remote): Add config command for QAllow.

* gdb.texinfo (Observer Mode): New section.
(General Query Packets): Document QAllow.
* gdb.base/permissions.exp: New file.


Index: inferior.h
===================================================================
RCS file: /cvs/src/src/gdb/inferior.h,v
retrieving revision 1.143
diff -p -r1.143 inferior.h
*** inferior.h	25 Mar 2010 20:48:53 -0000	1.143
--- inferior.h	3 Jun 2010 23:44:48 -0000
*************** extern int number_of_inferiors (void);
*** 628,631 ****
--- 628,633 ----
  
  extern struct inferior *add_inferior_with_spaces (void);
  
+ extern void update_observer_mode (void);
+ 
  #endif /* !defined (INFERIOR_H) */
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.441
diff -p -r1.441 infrun.c
*** infrun.c	17 May 2010 10:40:06 -0000	1.441
--- infrun.c	3 Jun 2010 23:44:48 -0000
*************** show_debug_infrun (struct ui_file *file,
*** 178,183 ****
--- 178,262 ----
  #define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
  #endif
  
+ /* "Observer mode" is somewhat like a more extreme version of
+    non-stop, in which all GDB operations that might affect the
+    target's execution have been disabled.  */
+ 
+ static int non_stop_1 = 0;
+ 
+ int observer_mode = 0;
+ static int observer_mode_1 = 0;
+ 
+ static void
+ set_observer_mode (char *args, int from_tty,
+ 		   struct cmd_list_element *c)
+ {
+   extern int pagination_enabled;
+ 
+   if (target_has_execution)
+     {
+       observer_mode_1 = observer_mode;
+       error (_("Cannot change this setting while the inferior is running."));
+     }
+ 
+   observer_mode = observer_mode_1;
+ 
+   may_write_registers = !observer_mode;
+   may_write_memory = !observer_mode;
+   may_insert_breakpoints = !observer_mode;
+   may_insert_tracepoints = !observer_mode;
+   /* We can insert fast tracepoints in or out of observer mode,
+      but enable them if we're going into this mode.  */
+   if (observer_mode)
+     may_insert_fast_tracepoints = 1;
+   may_stop = !observer_mode;
+   update_target_permissions ();
+ 
+   /* Going *into* observer mode we must force non-stop, then
+      going out we leave it that way.  */
+   if (observer_mode)
+     {
+       target_async_permitted = 1;
+       pagination_enabled = 0;
+       non_stop = non_stop_1 = 1;
+     }
+ 
+   if (from_tty)
+     printf_filtered (_("Observer mode is now %s.\n"),
+ 		     (observer_mode ? "on" : "off"));
+ }
+ 
+ static void
+ show_observer_mode (struct ui_file *file, int from_tty,
+ 		    struct cmd_list_element *c, const char *value)
+ {
+   fprintf_filtered (file, _("Observer mode is %s.\n"), value);
+ }
+ 
+ /* This updates the value of observer mode based on changes in
+    permissions.  Note that we are deliberately ignoring the values of
+    may-write-registers and may-write-memory, since the user may have
+    reason to enable these during a session, for instance to turn on a
+    debugging-related global.  */
+ 
+ void
+ update_observer_mode (void)
+ {
+   int newval;
+ 
+   newval = (!may_insert_breakpoints
+ 	    && !may_insert_tracepoints
+ 	    && may_insert_fast_tracepoints
+ 	    && !may_stop
+ 	    && non_stop);
+ 
+   /* Let the user know if things change.  */
+   if (newval != observer_mode)
+     printf_filtered (_("Observer mode is now %s.\n"),
+ 		     (newval ? "on" : "off"));
+ 
+   observer_mode = observer_mode_1 = newval;
+ }
  
  /* Tables of how to react to signals; the user sets them.  */
  
*************** show_exec_direction_func (struct ui_file
*** 6423,6429 ****
  /* User interface for non-stop mode.  */
  
  int non_stop = 0;
- static int non_stop_1 = 0;
  
  static void
  set_non_stop (char *args, int from_tty,
--- 6502,6507 ----
*************** Tells gdb whether to detach the child of
*** 6725,6728 ****
--- 6803,6819 ----
       isn't initialized yet.  At this point, we're quite sure there
       isn't another convenience variable of the same name.  */
    create_internalvar_type_lazy ("_siginfo", siginfo_make_value);
+ 
+   add_setshow_boolean_cmd ("observer", no_class,
+ 			   &observer_mode_1, _("\
+ Set whether gdb controls the inferior in observer mode."), _("\
+ Show whether gdb controls the inferior in observer mode."), _("\
+ In observer mode, GDB can get data from the inferior, but not\n\
+ affect its execution.  Registers and memory may not be changed,\n\
+ breakpoints may not be set, and the program cannot be interrupted\n\
+ or signalled."),
+ 			   set_observer_mode,
+ 			   show_observer_mode,
+ 			   &setlist,
+ 			   &showlist);
  }
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.415
diff -p -r1.415 remote.c
*** remote.c	2 Jun 2010 22:21:53 -0000	1.415
--- remote.c	3 Jun 2010 23:44:49 -0000
*************** static void show_remote_protocol_packet_
*** 212,217 ****
--- 212,219 ----
  static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
  static ptid_t read_ptid (char *buf, char **obuf);
  
+ static void remote_set_permissions (void);
+ 
  struct remote_state;
  static int remote_get_trace_status (struct trace_status *ts);
  
*************** enum {
*** 1213,1218 ****
--- 1215,1221 ----
    PACKET_bc,
    PACKET_bs,
    PACKET_TracepointSource,
+   PACKET_QAllow,
    PACKET_MAX
  };
  
*************** remote_start_remote (struct ui_out *uiou
*** 3046,3051 ****
--- 3049,3058 ----
       which later probes to skip.  */
    remote_query_supported ();
  
+   /* If the stub wants to get a QAllow, compose one and send it.  */
+   if (remote_protocol_packets[PACKET_QAllow].support != PACKET_DISABLE)
+     remote_set_permissions ();
+ 
    /* Next, we possibly activate noack mode.
  
       If the QStartNoAckMode packet configuration is set to AUTO,
*************** Some events may be lost, rendering furth
*** 3392,3397 ****
--- 3399,3434 ----
    return serial_open (name);
  }
  
+ /* Inform the target of our permission settings.  The permission flags
+    work without this, but if the target knows the settings, it can do
+    a couple things.  First, it can add its own check, to catch cases
+    that somehow manage to get by the permissions checks in target
+    methods.  Second, if the target is wired to disallow particular
+    settings (for instance, a system in the field that is not set up to
+    be able to stop at a breakpoint), it can object to any unavailable
+    permissions.  */
+ 
+ void
+ remote_set_permissions (void)
+ {
+   struct remote_state *rs = get_remote_state ();
+ 
+   sprintf (rs->buf, "QAllow:"
+ 	   "WriteReg:%x;WriteMem:%x;"
+ 	   "InsertBreak:%x;InsertTrace:%x;"
+ 	   "InsertFastTrace:%x;Stop:%x",
+ 	   may_write_registers, may_write_memory,
+ 	   may_insert_breakpoints, may_insert_tracepoints,
+ 	   may_insert_fast_tracepoints, may_stop);
+   putpkt (rs->buf);
+   getpkt (&rs->buf, &rs->buf_size, 0);
+ 
+   /* If the target didn't like the packet, warn the user.  Do not try
+      to undo the user's settings, that would just be maddening.  */
+   if (strcmp (rs->buf, "OK") != 0)
+     warning ("Remote refused setting permissions with: %s", rs->buf);
+ }
+ 
  /* This type describes each known response to the qSupported
     packet.  */
  struct protocol_feature
*************** static struct protocol_feature remote_pr
*** 3563,3568 ****
--- 3600,3607 ----
      PACKET_bs },
    { "TracepointSource", PACKET_DISABLE, remote_supported_packet,
      PACKET_TracepointSource },
+   { "QAllow", PACKET_DISABLE, remote_supported_packet,
+     PACKET_QAllow },
  };
  
  static char *remote_support_xml;
*************** Specify the serial device it is connecte
*** 10060,10065 ****
--- 10099,10105 ----
    remote_ops.to_core_of_thread = remote_core_of_thread;
    remote_ops.to_verify_memory = remote_verify_memory;
    remote_ops.to_get_tib_address = remote_get_tib_address;
+   remote_ops.to_set_permissions = remote_set_permissions;
  }
  
  /* Set up the extended remote vector by making a copy of the standard
*************** Show the maximum size of the address (in
*** 10535,10540 ****
--- 10575,10583 ----
    add_packet_config_cmd (&remote_protocol_packets[PACKET_TracepointSource],
  			 "TracepointSource", "TracepointSource", 0);
  
+   add_packet_config_cmd (&remote_protocol_packets[PACKET_QAllow],
+ 			 "QAllow", "allow", 0);
+ 
    /* Keep the old ``set remote Z-packet ...'' working.  Each individual
       Z sub-packet has its own set and show commands, but users may
       have sets to this variable in their .gdbinit files (or in their
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.255
diff -p -r1.255 target.c
*** target.c	23 May 2010 14:23:31 -0000	1.255
--- target.c	3 Jun 2010 23:44:49 -0000
*************** static int trust_readonly = 0;
*** 195,200 ****
--- 195,216 ----
  
  static int show_memory_breakpoints = 0;
  
+ /* These globals control whether GDB attempts to perform these
+    operations; they are useful for targets that need to prevent
+    inadvertant disruption, such as in non-stop mode.  */
+ 
+ int may_write_registers = 1;
+ 
+ int may_write_memory = 1;
+ 
+ int may_insert_breakpoints = 1;
+ 
+ int may_insert_tracepoints = 1;
+ 
+ int may_insert_fast_tracepoints = 1;
+ 
+ int may_stop = 1;
+ 
  /* Non-zero if we want to see trace of target level stuff.  */
  
  static int targetdebug = 0;
*************** update_current_target (void)
*** 662,667 ****
--- 678,684 ----
        INHERIT (to_set_disconnected_tracing, t);
        INHERIT (to_set_circular_trace_buffer, t);
        INHERIT (to_get_tib_address, t);
+       INHERIT (to_set_permissions, t);
        INHERIT (to_magic, t);
        /* Do not inherit to_memory_map.  */
        /* Do not inherit to_flash_erase.  */
*************** update_current_target (void)
*** 858,863 ****
--- 875,883 ----
    de_fault (to_get_tib_address,
  	    (int (*) (ptid_t, CORE_ADDR *))
  	    tcomplain);
+   de_fault (to_set_permissions,
+ 	    (void (*) (void))
+ 	    target_ignore);
  #undef de_fault
  
    /* Finally, position the target-stack beneath the squashed
*************** target_xfer_partial (struct target_ops *
*** 1404,1409 ****
--- 1424,1433 ----
  
    gdb_assert (ops->to_xfer_partial != NULL);
  
+   if (writebuf && !may_write_memory)
+     error (_("Writing to memory is not allowed (addr %s, len %s)"),
+ 	   core_addr_to_string_nz (offset), plongest (len));
+ 
    /* If this is a memory transfer, let the memory-specific code
       have a look at it instead.  Memory transfers are more
       complicated.  */
*************** get_target_memory_unsigned (struct targe
*** 1967,1972 ****
--- 1991,2026 ----
    return extract_unsigned_integer (buf, len, byte_order);
  }
  
+ int
+ target_insert_breakpoint (struct gdbarch *gdbarch,
+ 			  struct bp_target_info *bp_tgt)
+ {
+   if (!may_insert_breakpoints)
+     {
+       warning (_("May not insert breakpoints"));
+       return 1;
+     }
+ 
+   return (*current_target.to_insert_breakpoint) (gdbarch, bp_tgt);
+ }
+ 
+ int
+ target_remove_breakpoint (struct gdbarch *gdbarch,
+ 			  struct bp_target_info *bp_tgt)
+ {
+   /* This is kind of a weird case to handle, but the permission might
+      have been changed after breakpoints were inserted - in which case
+      we should just take the user literally and assume that any
+      breakpoints should be left in place.  */
+   if (!may_insert_breakpoints)
+     {
+       warning (_("May not remove breakpoints"));
+       return 1;
+     }
+ 
+   return (*current_target.to_remove_breakpoint) (gdbarch, bp_tgt);
+ }
+ 
  static void
  target_info (char *args, int from_tty)
  {
*************** target_find_new_threads (void)
*** 2949,2954 ****
--- 3003,3020 ----
      }
  }
  
+ void
+ target_stop (ptid_t ptid)
+ {
+   if (!may_stop)
+     {
+       warning (_("May not interrupt or stop the target, ignoring attempt"));
+       return;
+     }
+ 
+   (*current_target.to_stop) (ptid);
+ }
+ 
  static void
  debug_to_post_attach (int pid)
  {
*************** target_store_registers (struct regcache 
*** 3058,3063 ****
--- 3124,3132 ----
  {
    struct target_ops *t;
  
+   if (!may_write_registers)
+     error (_("Writing to registers is not allowed (regno %d)"), regno);
+ 
    for (t = current_target.beneath; t != NULL; t = t->beneath)
      {
        if (t->to_store_registers != NULL)
*************** show_maintenance_target_async_permitted 
*** 3675,3680 ****
--- 3744,3805 ----
  Controlling the inferior in asynchronous mode is %s.\n"), value);
  }
  
+ /* Temporary copies of permission settings.  */
+ 
+ static int may_write_registers_1 = 1;
+ static int may_write_memory_1 = 1;
+ static int may_insert_breakpoints_1 = 1;
+ static int may_insert_tracepoints_1 = 1;
+ static int may_insert_fast_tracepoints_1 = 1;
+ static int may_stop_1 = 1;
+ 
+ /* Make the user-set values match the real values again.  */
+ 
+ void
+ update_target_permissions (void)
+ {
+   may_write_registers_1 = may_write_registers;
+   may_write_memory_1 = may_write_memory;
+   may_insert_breakpoints_1 = may_insert_breakpoints;
+   may_insert_tracepoints_1 = may_insert_tracepoints;
+   may_insert_fast_tracepoints_1 = may_insert_fast_tracepoints;
+   may_stop_1 = may_stop;
+ }
+ 
+ /* The one function handles (most of) the permission flags in the same
+    way.  */
+ 
+ static void
+ set_target_permissions (char *args, int from_tty,
+ 			struct cmd_list_element *c)
+ {
+   if (target_has_execution)
+     {
+       update_target_permissions ();
+       error (_("Cannot change this setting while the inferior is running."));
+     }
+ 
+   /* Make the real values match the user-changed values.  */
+   may_write_registers = may_write_registers_1;
+   may_insert_breakpoints = may_insert_breakpoints_1;
+   may_insert_tracepoints = may_insert_tracepoints_1;
+   may_insert_fast_tracepoints = may_insert_fast_tracepoints_1;
+   may_stop = may_stop_1;
+   update_observer_mode ();
+ }
+ 
+ /* Set memory write permission independently of observer mode.  */
+ 
+ static void
+ set_write_memory_permission (char *args, int from_tty,
+ 			struct cmd_list_element *c)
+ {
+   /* Make the real values match the user-changed values.  */
+   may_write_memory = may_write_memory_1;
+   update_observer_mode ();
+ }
+ 
+ 
  void
  initialize_targets (void)
  {
*************** By default, caching for stack access is 
*** 3733,3737 ****
--- 3858,3917 ----
  			   show_stack_cache_enabled_p,
  			   &setlist, &showlist);
  
+   add_setshow_boolean_cmd ("may-write-registers", class_support,
+ 			   &may_write_registers_1, _("\
+ Set permission to write into registers."), _("\
+ Show permission to write into registers."), _("\
+ When this permission is on, GDB may write into the target's registers.\n\
+ Otherwise, any sort of write attempt will result in an error."),
+ 			   set_target_permissions, NULL,
+ 			   &setlist, &showlist);
+ 
+   add_setshow_boolean_cmd ("may-write-memory", class_support,
+ 			   &may_write_memory_1, _("\
+ Set permission to write into target memory."), _("\
+ Show permission to write into target memory."), _("\
+ When this permission is on, GDB may write into the target's memory.\n\
+ Otherwise, any sort of write attempt will result in an error."),
+ 			   set_write_memory_permission, NULL,
+ 			   &setlist, &showlist);
+ 
+   add_setshow_boolean_cmd ("may-insert-breakpoints", class_support,
+ 			   &may_insert_breakpoints_1, _("\
+ Set permission to insert breakpoints in the target."), _("\
+ Show permission to insert breakpoints in the target."), _("\
+ When this permission is on, GDB may insert breakpoints in the program.\n\
+ Otherwise, any sort of insertion attempt will result in an error."),
+ 			   set_target_permissions, NULL,
+ 			   &setlist, &showlist);
+ 
+   add_setshow_boolean_cmd ("may-insert-tracepoints", class_support,
+ 			   &may_insert_tracepoints_1, _("\
+ Set permission to insert tracepoints in the target."), _("\
+ Show permission to insert tracepoints in the target."), _("\
+ When this permission is on, GDB may insert tracepoints in the program.\n\
+ Otherwise, any sort of insertion attempt will result in an error."),
+ 			   set_target_permissions, NULL,
+ 			   &setlist, &showlist);
+ 
+   add_setshow_boolean_cmd ("may-insert-fast-tracepoints", class_support,
+ 			   &may_insert_fast_tracepoints_1, _("\
+ Set permission to insert fast tracepoints in the target."), _("\
+ Show permission to insert fast tracepoints in the target."), _("\
+ When this permission is on, GDB may insert fast tracepoints.\n\
+ Otherwise, any sort of insertion attempt will result in an error."),
+ 			   set_target_permissions, NULL,
+ 			   &setlist, &showlist);
+ 
+   add_setshow_boolean_cmd ("may-interrupt", class_support,
+ 			   &may_stop_1, _("\
+ Set permission to interrupt or signal the target."), _("\
+ Show permission to interrupt or signal the target."), _("\
+ When this permission is on, GDB may interrupt/stop the target's execution.\n\
+ Otherwise, any attempt to interrupt or stop will be ignored."),
+ 			   set_target_permissions, NULL,
+ 			   &setlist, &showlist);
+ 
+ 
    target_dcache = dcache_init ();
  }
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.182
diff -p -r1.182 target.h
*** target.h	23 May 2010 14:23:31 -0000	1.182
--- target.h	3 Jun 2010 23:44:49 -0000
*************** struct target_ops
*** 686,691 ****
--- 686,694 ----
         a Windows OS specific feature.  */
      int (*to_get_tib_address) (ptid_t ptid, CORE_ADDR *addr);
  
+     /* Send the new settings of write permission variables.  */
+     void (*to_set_permissions) (void);
+ 
      int to_magic;
      /* Need sub-structure for target machine related rather than comm related?
       */
*************** extern int inferior_has_called_syscall (
*** 889,902 ****
  /* Insert a breakpoint at address BP_TGT->placed_address in the target
     machine.  Result is 0 for success, or an errno value.  */
  
! #define	target_insert_breakpoint(gdbarch, bp_tgt)	\
!      (*current_target.to_insert_breakpoint) (gdbarch, bp_tgt)
  
  /* Remove a breakpoint at address BP_TGT->placed_address in the target
     machine.  Result is 0 for success, or an errno value.  */
  
! #define	target_remove_breakpoint(gdbarch, bp_tgt)	\
!      (*current_target.to_remove_breakpoint) (gdbarch, bp_tgt)
  
  /* Initialize the terminal settings we record for the inferior,
     before we actually run the inferior.  */
--- 892,905 ----
  /* Insert a breakpoint at address BP_TGT->placed_address in the target
     machine.  Result is 0 for success, or an errno value.  */
  
! extern int target_insert_breakpoint (struct gdbarch *gdbarch,
! 				     struct bp_target_info *bp_tgt);
  
  /* Remove a breakpoint at address BP_TGT->placed_address in the target
     machine.  Result is 0 for success, or an errno value.  */
  
! extern int target_remove_breakpoint (struct gdbarch *gdbarch,
! 				     struct bp_target_info *bp_tgt);
  
  /* Initialize the terminal settings we record for the inferior,
     before we actually run the inferior.  */
*************** extern void target_find_new_threads (voi
*** 1091,1097 ****
     Unix, this should act like SIGSTOP).  This function is normally
     used by GUIs to implement a stop button.  */
  
! #define target_stop(ptid) (*current_target.to_stop) (ptid)
  
  /* Send the specified COMMAND to the target's monitor
     (shell,interpreter) for execution.  The result of the query is
--- 1094,1100 ----
     Unix, this should act like SIGSTOP).  This function is normally
     used by GUIs to implement a stop button.  */
  
! extern void target_stop (ptid_t ptid);
  
  /* Send the specified COMMAND to the target's monitor
     (shell,interpreter) for execution.  The result of the query is
*************** extern int target_search_memory (CORE_AD
*** 1378,1383 ****
--- 1381,1389 ----
  #define target_get_tib_address(ptid, addr) \
    (*current_target.to_get_tib_address) ((ptid), (addr))
  
+ #define target_set_permissions() \
+   (*current_target.to_set_permissions) ()
+ 
  /* Command logging facility.  */
  
  #define target_log_command(p)						\
*************** extern enum target_signal target_signal_
*** 1540,1545 ****
--- 1546,1560 ----
     to restore it back to the current value.  */
  extern struct cleanup *make_show_memory_breakpoints_cleanup (int show);
  
+ extern int may_write_registers;
+ extern int may_write_memory;
+ extern int may_insert_breakpoints;
+ extern int may_insert_tracepoints;
+ extern int may_insert_fast_tracepoints;
+ extern int may_stop;
+ 
+ extern void update_target_permissions (void);
+ 
  
  /* Imported from machine dependent code */
  
Index: tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.c,v
retrieving revision 1.188
diff -p -r1.188 tracepoint.c
*** tracepoint.c	27 May 2010 22:06:00 -0000	1.188
--- tracepoint.c	3 Jun 2010 23:44:49 -0000
*************** start_tracing (void)
*** 1490,1496 ****
    int ix;
    struct breakpoint *t;
    struct trace_state_variable *tsv;
!   int any_enabled = 0;
    
    tp_vec = all_tracepoints ();
  
--- 1490,1496 ----
    int ix;
    struct breakpoint *t;
    struct trace_state_variable *tsv;
!   int any_enabled = 0, num_to_download = 0;
    
    tp_vec = all_tracepoints ();
  
*************** start_tracing (void)
*** 1504,1513 ****
    for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
      {
        if (t->enable_state == bp_enabled)
! 	{
! 	  any_enabled = 1;
! 	  break;
! 	}
      }
  
    /* No point in tracing with only disabled tracepoints.  */
--- 1504,1518 ----
    for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
      {
        if (t->enable_state == bp_enabled)
! 	any_enabled = 1;
! 
!       if ((t->type == bp_fast_tracepoint
! 	   ? may_insert_fast_tracepoints
! 	   : may_insert_tracepoints))
! 	++num_to_download;
!       else
! 	warning (_("May not insert %stracepoints, skipping tracepoint %d"),
! 		 (t->type == bp_fast_tracepoint ? "fast " : ""), t->number);
      }
  
    /* No point in tracing with only disabled tracepoints.  */
*************** start_tracing (void)
*** 1517,1526 ****
--- 1522,1542 ----
        error (_("No tracepoints enabled, not starting trace"));
      }
  
+   if (num_to_download <= 0)
+     {
+       VEC_free (breakpoint_p, tp_vec);
+       error (_("No tracepoints that may be downloaded, not starting trace"));
+     }
+ 
    target_trace_init ();
  
    for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
      {
+       if ((t->type == bp_fast_tracepoint
+ 	   ? !may_insert_fast_tracepoints
+ 	   : !may_insert_tracepoints))
+ 	continue;
+ 
        t->number_on_target = 0;
        target_download_tracepoint (t);
        t->number_on_target = t->number;
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.720
diff -p -r1.720 gdb.texinfo
*** doc/gdb.texinfo	2 Jun 2010 19:37:56 -0000	1.720
--- doc/gdb.texinfo	3 Jun 2010 23:44:49 -0000
*************** you examine the stopped thread in the de
*** 4958,4963 ****
--- 4958,4964 ----
  * Background Execution::	Running your program asynchronously
  * Thread-Specific Breakpoints::	Controlling breakpoints
  * Interrupted System Calls::	GDB may interfere with system calls
+ * Observer Mode::               GDB does not alter program behavior
  @end menu
  
  @node All-Stop Mode
*************** monitor certain events such as thread cr
*** 5318,5323 ****
--- 5319,5421 ----
  When such an event happens, a system call in another thread may return
  prematurely, even though your program does not appear to stop.
  
+ @node Observer Mode
+ @subsection Observer Mode
+ 
+ If you want to build on non-stop mode and observe program behavior
+ without any chance of disruption by @value{GDBN}, you can set
+ variables to disable all of the debugger's attempts to modify state,
+ whether by writing memory, inserting breakpoints, etc.  These operate
+ at a low level, intercepting operations from all commands.
+ 
+ When all of these are set to @code{off}, then @value{GDBN} is said to
+ be @dfn{observer mode}.  As a convenience, the variable
+ @code{observer} can be set to disable these, plus enable non-stop
+ mode.
+ 
+ Note that @value{GDBN} will not prevent you from making nonsensical
+ combinations of these settings. For instance, if you have enabled
+ @code{may-insert-breakpoints} but disabled @code{may-write-memory},
+ then breakpoints that work by writing trap instructions into the code
+ stream will still not be able to be placed.
+ 
+ @table @code
+ 
+ @kindex observer
+ @item set observer on
+ @itemx set observer off
+ When set to @code{on}, this disables all the permission variables
+ below (except for @code{insert-fast-tracepoints}), plus enables
+ non-stop debugging.  Setting this to @code{off} switches back to
+ normal debugging, though remaining in non-stop mode.
+ 
+ @item show observer
+ Show whether observer mode is on or off.
+ 
+ @kindex may-write-registers
+ @item set may-write-registers on
+ @itemx set may-write-registers off
+ This controls whether @value{GDBN} will attempt to alter the values of
+ registers, such as with assignment expressions in @code{print}, or the
+ @code{jump} command.  It defaults to @code{on}.
+ 
+ @item show may-write-registers
+ Show the current permission to write registers.
+ 
+ @kindex may-write-memory
+ @item set may-write-memory on
+ @itemx set may-write-memory off
+ This controls whether @value{GDBN} will attempt to alter the contents
+ of memory, such as with assignment expressions in @code{print}.  It
+ defaults to @code{on}.
+ 
+ @item show may-write-memory
+ Show the current permission to write memory.
+ 
+ @kindex may-insert-breakpoints
+ @item set may-insert-breakpoints on
+ @itemx set may-insert-breakpoints off
+ This controls whether @value{GDBN} will attempt to insert breakpoints.
+ This affects all breakpoints, including internal breakpoints defined
+ by @value{GDBN}.  It defaults to @code{on}.
+ 
+ @item show may-insert-breakpoints
+ Show the current permission to insert breakpoints.
+ 
+ @kindex may-insert-tracepoints
+ @item set may-insert-tracepoints on
+ @itemx set may-insert-tracepoints off
+ This controls whether @value{GDBN} will attempt to insert (regular)
+ tracepoints at the beginning of a tracing experiment.  It affects only
+ non-fast tracepoints, fast tracepoints being under the control of
+ @code{may-insert-fast-tracepoints}.  It defaults to @code{on}.
+ 
+ @item show may-insert-tracepoints
+ Show the current permission to insert tracepoints.
+ 
+ @kindex may-insert-fast-tracepoints
+ @item set may-insert-fast-tracepoints on
+ @itemx set may-insert-fast-tracepoints off
+ This controls whether @value{GDBN} will attempt to insert fast
+ tracepoints at the beginning of a tracing experiment.  It affects only
+ fast tracepoints, regular (non-fast) tracepoints being under the
+ control of @code{may-insert-tracepoints}.  It defaults to @code{on}.
+ 
+ @item show may-insert-fast-tracepoints
+ Show the current permission to insert fast tracepoints.
+ 
+ @kindex may-interrupt
+ @item set may-interrupt on
+ @itemx set may-interrupt off
+ This controls whether @value{GDBN} will attempt to interrupt or stop
+ program execution.  When this variable is @code{off}, the
+ @code{interrupt} command will have no effect, nor will
+ @kbd{Ctrl-c}. It defaults to @code{on}.
+ 
+ @item show may-interrupt
+ Show the current permission to interrupt or stop the program.
+ 
+ @end table
  
  @node Reverse Execution
  @chapter Running programs backward
*************** Here are the currently defined query and
*** 31168,31173 ****
--- 31266,31283 ----
  
  @table @samp
  
+ @item QAllow:@var{op}:@var{val}@dots{}
+ @cindex @samp{QAllow} packet
+ Specify which operations @value{GDBN} expects to request of the
+ target, as a semicolon-separated list of operation name and value
+ pairs.  Possible values for @var{op} include @samp{WriteReg},
+ @samp{WriteMem}, @samp{InsertBreak}, @samp{InsertTrace},
+ @samp{InsertFastTrace}, and @samp{Stop}. @var{val} is either 0,
+ indicating that @value{GDBN} will not request the operation, or 1,
+ indicating that it may.  (The target can then use this to set up its
+ own internals optimally, for instance if the debugger never expects to
+ insert breakpoints, it may not need to install its own trap handler.)
+ 
  @item qC
  @cindex current thread, remote request
  @cindex @samp{qC} packet
*************** These are the currently defined stub fea
*** 31689,31694 ****
--- 31799,31809 ----
  @tab @samp{-}
  @tab No
  
+ @item @samp{QAllow}
+ @tab No
+ @tab @samp{-}
+ @tab No
+ 
  @end multitable
  
  These are the currently defined stub features, in more detail:
*************** The remote stub accepts and implements t
*** 31786,31791 ****
--- 31901,31909 ----
  The remote stub understands the @samp{QTDPsrc} packet that supplies
  the source form of tracepoint definitions.
  
+ @item QAllow
+ The remote stub understands the @samp{QAllow} packet.
+ 
  @end table
  
  @item qSymbol::
Index: testsuite/gdb.base/permissions.exp
===================================================================
RCS file: testsuite/gdb.base/permissions.exp
diff -N testsuite/gdb.base/permissions.exp
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gdb.base/permissions.exp	3 Jun 2010 23:44:49 -0000
***************
*** 0 ****
--- 1,101 ----
+ # Copyright 2010 Free Software Foundation, Inc.
+ 
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+ # Tests for permissions and observer mode.
+ 
+ # The permissions flags are only fully functional with stubs or targets
+ # that can run asynchronously.
+ 
+ set testfile permission
+ set srcfile start.c
+ set binfile ${objdir}/${subdir}/${testfile}
+ 
+ if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug nowarnings}] != "" } {
+      untested permissions.exp
+      return -1
+     }
+ 
+ if [get_compiler_info $binfile] {
+     return -1
+ }
+ 
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ 
+ gdb_test "show may-write-registers" \
+     "Permission to write into registers is on."
+ 
+ gdb_test "show may-write-memory" \
+     "Permission to write into target memory is on."
+ 
+ gdb_test "show may-insert-breakpoints" \
+     "Permission to insert breakpoints in the target is on."
+ 
+ gdb_test "show may-insert-tracepoints" \
+     "Permission to insert tracepoints in the target is on."
+ 
+ gdb_test "show may-insert-fast-tracepoints" \
+     "Permission to insert fast tracepoints in the target is on."
+ 
+ gdb_test "show may-interrupt" \
+     "Permission to interrupt or signal the target is on."
+ 
+ gdb_test "set observer on" "Observer mode is now on." "enable observer mode"
+ 
+ gdb_test "show may-write-memory" \
+     "Permission to write into target memory is off."
+ 
+ gdb_test "show may-write-registers" \
+     "Permission to write into registers is off."
+ 
+ gdb_test "show may-insert-breakpoints" \
+     "Permission to insert breakpoints in the target is off."
+ 
+ gdb_test "show may-insert-tracepoints" \
+     "Permission to insert tracepoints in the target is off."
+ 
+ gdb_test "show may-insert-fast-tracepoints" \
+     "Permission to insert fast tracepoints in the target is on."
+ 
+ gdb_test "show may-interrupt" \
+     "Permission to interrupt or signal the target is off."
+ 
+ gdb_test "set observer off" "Observer mode is now off." "disable observer mode"
+ 
+ # Go back to all-stop mode.
+ 
+ gdb_test_no_output "set non-stop off"
+ 
+ gdb_load ${binfile}
+ 
+ if ![runto_main] then {
+     perror "couldn't run to breakpoint"
+     continue
+ }
+ 
+ gdb_test "print x = 45" "$decimal = 45" "set a global"
+ 
+ gdb_test "print x" "$decimal = 45"
+ 
+ gdb_test "set may-write-memory off"
+ 
+ gdb_test "print x = 92" "Writing to memory is not allowed.*" \
+     "try to set a global"
+ 
+ gdb_test "print x" "$decimal = 45"
+ 
+ # FIXME Add tests for other flags when a testsuite-able target becomes
+ # available.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]