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).