From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23440 invoked by alias); 12 Nov 2008 19:54:28 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 23313 invoked by uid 306); 12 Nov 2008 19:54:27 -0000 Date: Wed, 12 Nov 2008 19:54:00 -0000 Message-ID: <20081112195427.23283.qmail@sourceware.org> From: tromey@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-sergio-catch-syscall: Allow multiple syscalls for a given catch point. X-Git-Refname: refs/heads/archer-sergio-catch-syscall X-Git-Reftype: branch X-Git-Oldrev: 443ed1699101789baaf5f4aed9fa428421c55d6a X-Git-Newrev: 589b9ef4c57807e3a2f5038f841b55b600bd9036 X-SW-Source: 2008-q4/txt/msg00100.txt.bz2 List-Id: 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 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 [ ... ] - 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 -/* 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 ". - - 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.