public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-sergio-catch-syscall: Allow multiple syscalls for a given catch point.
@ 2008-11-12 19:54 tromey
  0 siblings, 0 replies; only message in thread
From: tromey @ 2008-11-12 19:54 UTC (permalink / raw)
  To: archer-commits

The branch, archer-sergio-catch-syscall has been updated
       via  589b9ef4c57807e3a2f5038f841b55b600bd9036 (commit)
      from  443ed1699101789baaf5f4aed9fa428421c55d6a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 589b9ef4c57807e3a2f5038f841b55b600bd9036
Author: Tom Tromey <tromey@redhat.com>
Date:   Wed Nov 12 12:54:09 2008 -0700

    Allow multiple syscalls for a given catch point.
    Refactor target API to allow target-side filtering.

-----------------------------------------------------------------------

Summary of changes:
 gdb/breakpoint.c |  214 ++++++++++++++++++++++++++++++++++++------------------
 gdb/breakpoint.h |   26 ++++---
 gdb/inf-child.c  |   13 +---
 gdb/linux-nat.c  |   14 +--
 gdb/target.c     |   10 +--
 gdb/target.h     |   18 +++--
 6 files changed, 180 insertions(+), 115 deletions(-)

First 500 lines of diff:
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 8a897e3..c185559 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -194,10 +194,6 @@ static void insert_breakpoint_locations (void);
 
 static int syscall_catchpoint_p (struct breakpoint *b);
 
-/* The maximum number of arguments the user can provide to
-   the 'catch syscall' command.  */
-#define MAX_CATCH_SYSCALL_ARGS 10
-
 static const char *
 bpdisp_text (enum bpdisp disp)
 {
@@ -4352,7 +4348,7 @@ set_raw_breakpoint_without_location (enum bptype bptype)
   b->triggered_dll_pathname = NULL;
   b->forked_inferior_pid = null_ptid;
   b->exec_pathname = NULL;
-  b->syscall_to_be_caught = CATCHING_ANY_SYSCALL;
+  b->syscalls_to_be_caught = NULL;
   b->syscall_number = UNKNOWN_SYSCALL;
   b->ops = NULL;
   b->condition_not_parsed = 0;
@@ -4898,13 +4894,53 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops =
   print_mention_catch_vfork
 };
 
+/* We keep a count of the number of times the user has requested a
+   particular syscall to be tracked, and pass this information to the
+   target.  This lets capable targets implement filtering directly.  */
+
+/* Number of times that "any" syscall is requested.  */
+static int any_syscall_count;
+
+/* Count of each system call.  */
+static int *syscalls_counts;
+
+/* Number of system entries in SYSCALLS_COUNTS.  */
+static int syscalls_size;
+
+/* This counts all syscall catch requests, so we can readily determine
+   if any catching is necessary.  */
+static int total_syscalls_count;
+
 /* Implement the "insert" breakpoint_ops method for syscall
    catchpoints.  */
 
 static void
 insert_catch_syscall (struct breakpoint *b)
 {
-  target_insert_syscall_catchpoint (PIDGET (inferior_ptid));
+  ++total_syscalls_count;
+  if (!b->syscalls_to_be_caught)
+    ++any_syscall_count;
+  else
+    {
+      struct syscall_filter *iter;
+      for (iter = b->syscalls_to_be_caught; iter; iter = iter->next)
+	{
+	  if (iter->syscall >= syscalls_size)
+	    {
+	      syscalls_counts = xrealloc (syscalls_counts,
+					  (iter->syscall + 1) * sizeof (int));
+	      memset (&syscalls_counts[syscalls_size], 0,
+		      (iter->syscall + 1 - syscalls_size) * sizeof (int));
+	    }
+	  ++syscalls_counts[iter->syscall];
+	}
+    }
+
+  target_set_syscall_catchpoint (PIDGET (inferior_ptid),
+				 total_syscalls_count != 0,
+				 any_syscall_count,
+				 syscalls_size,
+				 syscalls_counts);
 }
 
 /* Implement the "remove" breakpoint_ops method for syscall
@@ -4913,7 +4949,28 @@ insert_catch_syscall (struct breakpoint *b)
 static int
 remove_catch_syscall (struct breakpoint *b)
 {
-  return target_remove_syscall_catchpoint (PIDGET (inferior_ptid));
+  --total_syscalls_count;
+  if (!b->syscalls_to_be_caught)
+    --any_syscall_count;
+  else
+    {
+      struct syscall_filter *iter;
+      for (iter = b->syscalls_to_be_caught; iter; iter = iter->next)
+	{
+	  if (iter->syscall >= syscalls_size)
+	    {
+	      /* Shouldn't happen.  */
+	      continue;
+	    }
+	  --syscalls_counts[iter->syscall];
+	}
+    }
+
+  return target_set_syscall_catchpoint (PIDGET (inferior_ptid),
+					total_syscalls_count != 0,
+					any_syscall_count,
+					syscalls_size,
+					syscalls_counts);
 }
 
 /* Implement the "breakpoint_hit" breakpoint_ops method for syscall
@@ -4931,10 +4988,16 @@ breakpoint_hit_catch_syscall (struct breakpoint *b)
     return 0;
 
   /* Now, checking if the syscall is the same.  */
-  if (b->syscall_to_be_caught != CATCHING_ANY_SYSCALL
-      && b->syscall_to_be_caught != syscall_number)
-    /* Not the same.  */
-    return 0;
+  if (b->syscalls_to_be_caught)
+    {
+      struct syscall_filter *iter;
+      for (iter = b->syscalls_to_be_caught; iter; iter = iter->next)
+	if (syscall_number == iter->syscall)
+	  break;
+      /* Not the same.  */
+      if (!iter)
+	return 0;
+    }
 
   /* It's the same syscall.  We can update the breakpoint struct
      with the correct information.  */
@@ -5017,11 +5080,16 @@ print_one_catch_syscall (struct breakpoint *b, CORE_ADDR *last_addr)
 static void
 print_mention_catch_syscall (struct breakpoint *b)
 {
-  if (b->syscall_to_be_caught != CATCHING_ANY_SYSCALL)
-    printf_filtered (_("Catchpoint %d (syscall '%s')"),
-                     b->number,
-                     gdbarch_syscall_name_from_number (current_gdbarch,
-                                                   b->syscall_to_be_caught));
+  if (b->syscalls_to_be_caught)
+    {
+      struct syscall_filter *iter;
+      printf_filtered (_("Catchpoint %d (syscalls"), b->number);
+      for (iter = b->syscalls_to_be_caught; iter; iter = iter->next)
+	printf_filtered (" %s",
+			 gdbarch_syscall_name_from_number (current_gdbarch,
+							   iter->syscall));
+      printf_filtered (")");
+    }
   else
     printf_filtered (_("Catchpoint %d (syscall)"),
                      b->number);
@@ -5180,13 +5248,13 @@ static struct breakpoint_ops catch_exec_breakpoint_ops =
 };
 
 static void
-create_syscall_event_catchpoint (int tempflag, int syscall_number,
+create_syscall_event_catchpoint (int tempflag, struct syscall_filter *filter,
                                  struct breakpoint_ops *ops)
 {
   struct breakpoint *b =
     create_catchpoint_without_mention (tempflag, NULL, ops);
 
-  b->syscall_to_be_caught = syscall_number;
+  b->syscalls_to_be_caught = filter;
   /* We still don't know the syscall that will be caught :-).  */
   b->syscall_number = UNKNOWN_SYSCALL;
 
@@ -7175,40 +7243,44 @@ catch_ada_exception_command (char *arg, int from_tty,
                                    from_tty);
 }
 
-/* Splits the argument using space as delimiter.
-   Returns the number of args.  */
-static int
-catch_syscall_split_args (char *arg, int *syscalls_numbers)
+/* Cleanup function for a syscall filter list.  */
+static void
+clean_up_filters (void *arg)
 {
-  int nargs = 0, i;
-  char *arg_p = arg;
-  char cur_name[128];
-  char c;
+  struct syscall_filter *iter = *(struct syscall_filter **) arg;
+  while (iter)
+    {
+      struct syscall_filter *next = iter->next;
+      xfree (iter);
+      iter = next;
+    }
+}
+
+/* Splits the argument using space as delimiter.  Returns an xmalloc'd
+   filter list, or NULL if no filtering is required.  */
+static struct syscall_filter *
+catch_syscall_split_args (char *arg)
+{
+  struct syscall_filter *result = NULL;
+  struct cleanup *cleanup = make_cleanup (clean_up_filters, &result);
 
-  while (*arg_p != '\0')
+  while (*arg != '\0')
     {
-      int out = 0;
+      int i;
       int syscall_number;
-      memset ((void *) cur_name, '\0', 128 * sizeof (char));
+      char cur_name[128];
+      struct syscall_filter *new_filter;
 
-      /* Skipping white-spaces.  */
-      while (isspace (*arg_p))
-        arg_p++;
+      /* Skip whitespace.  */
+      while (isspace (*arg))
+        arg++;
 
-      for (i = 0; out == 0; i++)
-        {
-          c = *arg_p;
-          cur_name[i] = c;
-          if (isspace (c) || c == '\0')
-            {
-              out = 1;
-              cur_name[i] = '\0';
-            }
-          else
-            arg_p++;
-        }
+      for (i = 0; arg[i] && !isspace (arg[i]); ++i)
+	cur_name[i] = arg[i];
+      cur_name[i] = '\0';
+      arg += i;
 
-      /* Checking if the user provided a syscall name or a number.  */
+      /* Check if the user provided a syscall name or a number.  */
       if (isdigit (cur_name[0]))
         {
           /* We have a number.  Let's check if it's valid.  */
@@ -7229,11 +7301,16 @@ catch_syscall_split_args (char *arg, int *syscalls_numbers)
           if (syscall_number == UNKNOWN_SYSCALL)
             error (_("Invalid syscall name '%s'."), cur_name);
         }
+
       /* Ok, it's valid.  */
-      syscalls_numbers[nargs++] = syscall_number;
+      new_filter = XNEW (struct syscall_filter);
+      new_filter->syscall = syscall_number;
+      new_filter->next = result;
+      result = new_filter;
     }
 
-    return nargs;
+  discard_cleanups (cleanup);
+  return result;
 }
 
 /* Implement the "catch syscall" command.  */
@@ -7242,6 +7319,7 @@ static void
 catch_syscall_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
 {
   int tempflag;
+  struct syscall_filter *filter;
 
   /* Checking if the feature if supported.  */
   if (gdbarch_get_syscall_number_p (current_gdbarch) == 0)
@@ -7256,24 +7334,15 @@ this architeture yet."));
      catch syscall
      catch syscall <name | number> [<name | number> ... <name | number>]
 
-     The maximum number of arguments this command can take
-     is define by MAX_CATCH_SYSCALL_ARGS.
-
      Let's check if there's a syscall name.  */
 
   if (arg != NULL)
-    {
-      int syscalls_numbers[MAX_CATCH_SYSCALL_ARGS];
-      int nargs = catch_syscall_split_args (arg, syscalls_numbers);
-      int i;
-
-      for (i = 0; i < nargs; i++)
-        create_syscall_event_catchpoint (tempflag, syscalls_numbers[i],
-                                         &catch_syscall_breakpoint_ops);
-    }
+    filter = catch_syscall_split_args (arg);
   else
-    create_syscall_event_catchpoint (tempflag, CATCHING_ANY_SYSCALL,
-                                     &catch_syscall_breakpoint_ops);
+    filter = NULL;
+
+  create_syscall_event_catchpoint (tempflag, filter,
+				   &catch_syscall_breakpoint_ops);
 }
 
 /* Implement the "catch assert" command.  */
@@ -7733,6 +7802,7 @@ delete_breakpoint (struct breakpoint *bpt)
     xfree (bpt->triggered_dll_pathname);
   if (bpt->exec_pathname != NULL)
     xfree (bpt->exec_pathname);
+  clean_up_filters (&bpt->syscalls_to_be_caught);
 
   /* Be sure no bpstat's are pointing at it after it's been freed.  */
   /* FIXME, how can we find all bpstat's?
@@ -8705,13 +8775,7 @@ is_syscall_catchpoint_enabled (struct breakpoint *bp)
 int
 catch_syscall_enabled (void)
 {
-  struct breakpoint *bp;
-
-  ALL_BREAKPOINTS (bp)
-    if (is_syscall_catchpoint_enabled (bp))
-      return 1;
-
-  return 0;
+  return total_syscalls_count != 0;
 }
 
 int
@@ -8721,9 +8785,17 @@ catching_syscall_number (int syscall_number)
 
   ALL_BREAKPOINTS (bp)
     if (is_syscall_catchpoint_enabled (bp))
-      if (bp->syscall_to_be_caught == syscall_number
-          || bp->syscall_to_be_caught == CATCHING_ANY_SYSCALL)
-        return 1;
+      {
+	if (bp->syscalls_to_be_caught)
+	  {
+	    struct syscall_filter *iter;
+	    for (iter = bp->syscalls_to_be_caught; iter; iter = iter->next)
+	      if (syscall_number == iter->syscall)
+		return 1;
+	  }
+	else
+	  return 1;
+      }
 
   return 0;
 }
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index caecba9..464b851 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -34,10 +34,6 @@ struct block;
 #define	BREAKPOINT_MAX	16
 \f
 
-/* A number to represent wether we are catching any syscalls.  */
-
-#define CATCHING_ANY_SYSCALL (-1)
-
 /* Type of breakpoint.  */
 /* FIXME In the future, we should fold all other breakpoint-like things into
    here.  This includes:
@@ -354,6 +350,17 @@ enum watchpoint_triggered
   watch_triggered_yes  
 };
 
+/* A syscall filter is represented as a linked list of syscall
+   numbers.  */
+struct syscall_filter
+{
+  /* The system call to accept.  */
+  int syscall;
+
+  /* The next filter.  */
+  struct syscall_filter *next;
+};
+
 typedef struct bp_location *bp_location_p;
 DEF_VEC_P(bp_location_p);
 
@@ -477,12 +484,11 @@ struct breakpoint
        triggered.  */
     int syscall_number;
 
-    /* This field is used when we are "filtering" the syscalls
-       (i.e., when the user types "catch syscall <SYSCALL_NAME>".
-
-       It stores the syscall number in case we are in the "filter mode",
-       or CATCHING_ANY_SYSCALL otherwise.  */
-    int syscall_to_be_caught;
+    /* Syscall numbers used for the 'catch syscall' feature.
+       If no syscall has been specified for filtering, its value is NULL.
+       Otherwise, it holds a list of all syscalls to be caught.
+       The list elements are allocated with xmalloc.  */
+    struct syscall_filter *syscalls_to_be_caught;
 
     /* Methods associated with this breakpoint.  */
     struct breakpoint_ops *ops;
diff --git a/gdb/inf-child.c b/gdb/inf-child.c
index 058cb34..8991a8b 100644
--- a/gdb/inf-child.c
+++ b/gdb/inf-child.c
@@ -144,15 +144,9 @@ inf_child_remove_exec_catchpoint (int pid)
   return 0;
 }
 
-static void
-inf_child_insert_syscall_catchpoint (int pid)
-{
-  /* This version of Unix doesn't support notification of syscall
-     events.  */
-}
-
 static int
-inf_child_remove_syscall_catchpoint (int pid)
+inf_child_set_syscall_catchpoint (int pid, int needed, int any_count,
+				  int table_size, int *table)
 {
   /* This version of Unix doesn't support notification of syscall
      events.  */
@@ -202,8 +196,7 @@ inf_child_target (void)
   t->to_follow_fork = inf_child_follow_fork;
   t->to_insert_exec_catchpoint = inf_child_insert_exec_catchpoint;
   t->to_remove_exec_catchpoint = inf_child_remove_exec_catchpoint;
-  t->to_insert_syscall_catchpoint = inf_child_insert_syscall_catchpoint;
-  t->to_remove_syscall_catchpoint = inf_child_remove_syscall_catchpoint;
+  t->to_set_syscall_catchpoint = inf_child_set_syscall_catchpoint;
   t->to_can_run = inf_child_can_run;
   t->to_pid_to_exec_file = inf_child_pid_to_exec_file;
   t->to_stratum = process_stratum;
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 53cc018..7f72568 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -985,16 +985,13 @@ linux_child_insert_exec_catchpoint (int pid)
     error (_("Your system does not support exec catchpoints."));
 }
 
-static void
-linux_child_insert_syscall_catchpoint (int pid)
+static int
+linux_child_set_syscall_catchpoint (int pid, int needed, int any_count,
+				    int table_size, int *table)
 {
   if (! linux_supports_tracesysgood (pid))
     error (_("Your system does not support syscall catchpoints."));
-}
-
-static int
-linux_child_remove_syscall_catchpoint (int pid)
-{
+  /* We ignore the arguments.  */
   return 0;
 }
 
@@ -4144,8 +4141,7 @@ linux_target_install_ops (struct target_ops *t)
   t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint;
   t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint;
   t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
-  t->to_insert_syscall_catchpoint = linux_child_insert_syscall_catchpoint;
-  t->to_remove_syscall_catchpoint = linux_child_remove_syscall_catchpoint;
+  t->to_set_syscall_catchpoint = linux_child_set_syscall_catchpoint;
   t->to_pid_to_exec_file = linux_child_pid_to_exec_file;
   t->to_post_startup_inferior = linux_child_post_startup_inferior;
   t->to_post_attach = linux_child_post_attach;
diff --git a/gdb/target.c b/gdb/target.c
index 7883175..0e16512 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -457,8 +457,7 @@ update_current_target (void)
       INHERIT (to_insert_exec_catchpoint, t);
       INHERIT (to_remove_exec_catchpoint, t);
       INHERIT (to_passed_by_entrypoint, t);
-      INHERIT (to_insert_syscall_catchpoint, t);
-      INHERIT (to_remove_syscall_catchpoint, t);
+      INHERIT (to_set_syscall_catchpoint, t);
       INHERIT (to_enable_tracesysgood, t);
       INHERIT (to_has_exited, t);
       /* Do no inherit to_mourn_inferiour.  */
@@ -621,11 +620,8 @@ update_current_target (void)
   de_fault (to_remove_exec_catchpoint,
 	    (int (*) (int))
 	    tcomplain);
-  de_fault (to_insert_syscall_catchpoint,
-	    (void (*) (int))
-	    tcomplain);
-  de_fault (to_remove_syscall_catchpoint,
-	    (int (*) (int))
+  de_fault (to_set_syscall_catchpoint,
+	    (int (*) (int, int, int, int, int *))
 	    tcomplain);
   de_fault (to_enable_tracesysgood,
             (void (*) (ptid_t))
diff --git a/gdb/target.h b/gdb/target.h
index 8ec2924..bc209bf 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -400,8 +400,7 @@ struct target_ops
     void (*to_insert_exec_catchpoint) (int);
     int (*to_remove_exec_catchpoint) (int);
     int (*to_passed_by_entrypoint) (void);
-    void (*to_insert_syscall_catchpoint) (int);
-    int (*to_remove_syscall_catchpoint) (int);
+    int (*to_set_syscall_catchpoint) (int, int, int, int, int *);
     void (*to_enable_tracesysgood) (ptid_t);
     int (*to_has_exited) (int, int, int *);


hooks/post-receive
--
Repository for Project Archer.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-11-12 19:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-12 19:54 [SCM] archer-sergio-catch-syscall: Allow multiple syscalls for a given catch point tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).