[patch 1/2] Convert hardware watchpoints to use breakpoint_ops

Thiago Jung Bauermann
2010-08-17T19:41:26Z

Hi all,

So I'm continuing my saga of submitting the patches implementing
advanced hardware debug features of the PowerPC BookE processors...

This one is in preparation for the patch for masked hardware watchpoints
and ranged hardware watchpoints. The next e-mail will explain better
what they are.

The point of this patch is that previous incarnations of the masked and
ranged hardware watchpoint implementation added many special cases in
breakpoint.c and by using the breakpoint_ops infrastructure most of them
can be eliminated. This follows a suggestion Joel made once when
reviewing the patch on ranged and masked breakpoints (which I'll submit
again later):

> In terms of implementation, I'm almost thinking that this type of
> breakpoint should be implemented using the breakpoint_ops structure.
> It would cause a bit of code redundancy, but your patch is typically
> doing:
>
> if (is_range_breakpoint (...))
> {
> do something
> }
> else
> {
> do the regular thing;
> }
>
> I'll let you explore this and let me know what you think. I'm 50/50
> on this suggestion, as it has pros and cons. The advantage is that
> you no longer have to check for the type of hw_breakpoint that you
> have.
> I can immediately assume that this is the type that you have. The
> downside is a bit of code duplication in how we display the
> information.
> We might be able to work around this by factorizing the code out of
> print_it_typical, print_one_breakpoint_location, etc...

This patch actually fixes some inconsistencies in the catchpoints
support: target.c sets the default implementation of
to_remove_{fork,vfork,exec}_catchpoint to be tcomplain, which throws an
exception, but remove_breakpoint_1 is not prepared to deal with it. The
only target which implements catchpoints is linux-nat.c and it doesn't
actually implement the to_remove_* methods, so in theory an exception
would be thrown when GDB tried to remove the catchpoints. The only
reason it works is that inf-child.c implements the remove methods to
return 0 indicating that the target doesn't support the feature and
linux-nat.c inherits those...

Also, remove_breakpoint_1 expects breakpoint_ops.remove to return 0 on
success and 1 on failure, but as I mentioned before inf-child.c uses a
different convention. This patch makes breakpoint_ops.insert and
breakpoint_ops.remove use the same convention used by
target_insert_watchpoint and target_remove_watchpoint, and they don't
throw exceptions anymore.

I could have implement the print_* methods for watchpoints which would
IMHO make watchpoint handling more object-oriented (= organized? :-) ),
but it would actually make the code slightly bigger (one switch
statement to distinguish between bp_hardware_watchpoint,
bp_read_watchpoint and bp_access_watchpoint per method) so I left this
out. I can implement them if you think it's a good idea.

Tested on ppc-linux, ppc64-linux and i686-linux with no regressions. Ok
to commit?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center

2010-08-17 Thiago Jung Bauermann <bauerman@br.ibm.com>

Convert hardware watchpoints to use breakpoint_ops.

gdb/
* breakpoint.c (insert_catchpoint): Delete function.
(update_watchpoint): Save and restore OPS to/from OLD_OPS when
changing the type of the watchpoint.
(insert_bp_location): Call the watchpoint or catchpoint's
breakpoint_ops.insert method.
(remove_breakpoint_1): Call the watchpoint or catchpoint's
breakpoint_ops.remove method.
(set_raw_breakpoint_without_location): Initialize the OLD_OPS field.
(insert_watchpoint, remove_watchpoint): New functions.
(watchpoint_breakpoint_ops): New structure.
(watch_command_1): Initialize the OPS field.
* breakpoint.h (breakpoint_ops) <insert>: Return int instead of void.
Accept pointer to struct bp_location instead of pointer to
struct breakpoint. Adapt all implementations.
(breakpoint_ops) <remove>: Accept pointer to struct bp_location instead
of pointer to struct breakpoint. Adapt all implementations.
(breakpoint) <old_ops>: New field.
* inf-child.c (inf_child_insert_fork_catchpoint)
(inf_child_remove_fork_catchpoint, inf_child_insert_vfork_catchpoint)
(inf_child_remove_vfork_catchpoint, inf_child_insert_exec_catchpoint)
(inf_child_remove_exec_catchpoint, inf_child_set_syscall_catchpoint):
Delete functions.
(inf_child_target): Remove initialization of to_insert_fork_catchpoint,
to_remove_fork_catchpoint, to_insert_vfork_catchpoint,
to_remove_vfork_catchpoint, to_insert_exec_catchpoint,
to_remove_exec_catchpoint and to_set_syscall_catchpoint.
* target.c (update_current_target): Change default implementation of
to_insert_fork_catchpoint, to_remove_fork_catchpoint,
to_insert_vfork_catchpoint, to_remove_vfork_catchpoint,
to_insert_exec_catchpoint, to_remove_exec_catchpoint and
to_set_syscall_catchpoint to return_one.
(debug_to_insert_fork_catchpoint, debug_to_insert_vfork_catchpoint)
(debug_to_insert_exec_catchpoint): Report return value.
* target.h (to_insert_fork_catchpoint, to_insert_vfork_catchpoint)
(to_insert_fork_catchpoint): Change declaration to return int instead
of void.

gdb/testsuite/
* gdb.base/foll-exec.exp: Adapt to new error string when the catchpoint
type is not supported.
* gdb.base/foll-fork.exp: Likewise.
* gdb.base/foll-vfork.exp: Likewise.

Index: gdb.git/gdb/breakpoint.c
===================================================================
--- gdb.git.orig/gdb/breakpoint.c 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/breakpoint.c 2010-08-16 20:17:23.000000000 -0300
@@ -1194,18 +1194,6 @@ breakpoint_restore_shadows (gdb_byte *bu
}
\f

-/* A wrapper function for inserting catchpoints. */
-static void
-insert_catchpoint (struct ui_out *uo, void *args)
-{
- struct breakpoint *b = (struct breakpoint *) args;
-
- gdb_assert (b->type == bp_catchpoint);
- gdb_assert (b->ops != NULL && b->ops->insert != NULL);
-
- b->ops->insert (b);
-}
-
/* Return true if BPT is of any hardware watchpoint kind. */

static int
@@ -1420,15 +1408,37 @@ update_watchpoint (struct breakpoint *b,
mem_cnt = can_use_hardware_watchpoint (val_chain);

if (!mem_cnt)
- b->type = bp_watchpoint;
+ {
+ b->type = bp_watchpoint;
+
+ /* When downgrading to a software watchpoint, we have to
+ remember the value of the OPS field so that we can restore
+ it when upgrading to a hardware watchpoint again. */
+ if (b->ops)
+ {
+ b->old_ops = b->ops;
+ b->ops = NULL;
+ }
+ }
else
{
int target_resources_ok = target_can_use_hardware_watchpoint
(bp_hardware_watchpoint, i + mem_cnt, other_type_used);
if (target_resources_ok <= 0)
- b->type = bp_watchpoint;
+ {
+ b->type = bp_watchpoint;
+ if (b->ops)
+ {
+ b->old_ops = b->ops;
+ b->ops = NULL;
+ }
+ }
else
- b->type = bp_hardware_watchpoint;
+ {
+ b->type = bp_hardware_watchpoint;
+ if (b->old_ops)
+ b->ops = b->old_ops;
+ }
}
}

@@ -1742,10 +1752,7 @@ Note: automatically using hardware break
watchpoints. It's not clear that it's necessary... */
&& bpt->owner->disposition != disp_del_at_next_stop)
{
- val = target_insert_watchpoint (bpt->address,
- bpt->length,
- bpt->watchpoint_type,
- bpt->owner->cond_exp);
+ val = bpt->owner->ops->insert (bpt);

/* If trying to set a read-watchpoint, and it turns out it's not
supported, try emulating one with an access watchpoint. */
@@ -1771,12 +1778,12 @@ Note: automatically using hardware break

if (val == 1)
{
- val = target_insert_watchpoint (bpt->address,
- bpt->length,
- hw_access,
- bpt->owner->cond_exp);
- if (val == 0)
- bpt->watchpoint_type = hw_access;
+ bpt->watchpoint_type = hw_access;
+ val = bpt->owner->ops->insert (bpt);
+
+ if (val)
+ /* Back to the original value. */
+ bpt->watchpoint_type = hw_read;
}
}

@@ -1785,14 +1792,22 @@ Note: automatically using hardware break

else if (bpt->owner->type == bp_catchpoint)
{
- struct gdb_exception e = catch_exception (uiout, insert_catchpoint,
- bpt->owner, RETURN_MASK_ERROR);
- exception_fprintf (gdb_stderr, e, "warning: inserting catchpoint %d: ",
- bpt->owner->number);
- if (e.reason < 0)
- bpt->owner->enable_state = bp_disabled;
- else
- bpt->inserted = 1;
+ gdb_assert (bpt->owner->ops != NULL && bpt->owner->ops->insert != NULL);
+
+ val = bpt->owner->ops->insert (bpt);
+ if (val)
+ {
+ bpt->owner->enable_state = bp_disabled;
+
+ if (val == 1)
+ warning (_("\
+Inserting catchpoint %d: Your system does not support this type of catchpoint."),
+ bpt->owner->number);
+ else
+ warning (_("Error inserting catchpoint %d."), bpt->owner->number);
+ }
+
+ bpt->inserted = (val == 0);

/* We've already printed an error message if there was a problem
inserting this catchpoint, and we've disabled the catchpoint,
@@ -2443,8 +2458,7 @@ remove_breakpoint_1 (struct bp_location
else if (b->loc_type == bp_loc_hardware_watchpoint)
{
b->inserted = (is == mark_inserted);
- val = target_remove_watchpoint (b->address, b->length,
- b->watchpoint_type, b->owner->cond_exp);
+ b->owner->ops->remove (b);

/* Failure to remove any of the hardware watchpoints comes here. */
if ((is == mark_uninserted) && (b->inserted))
@@ -2457,9 +2471,10 @@ remove_breakpoint_1 (struct bp_location
{
gdb_assert (b->owner->ops != NULL && b->owner->ops->remove != NULL);

- val = b->owner->ops->remove (b->owner);
+ val = b->owner->ops->remove (b);
if (val)
return val;
+
b->inserted = (is == mark_inserted);
}

@@ -5426,6 +5441,7 @@ set_raw_breakpoint_without_location (str
b->exec_pathname = NULL;
b->syscalls_to_be_caught = NULL;
b->ops = NULL;
+ b->old_ops = NULL;
b->condition_not_parsed = 0;

/* Add this breakpoint to the end of the chain
@@ -5809,16 +5825,16 @@ disable_breakpoints_in_unloaded_shlib (s

/* Implement the "insert" breakpoint_ops method for fork catchpoints. */

-static void
-insert_catch_fork (struct breakpoint *b)
+static int
+insert_catch_fork (struct bp_location *b)
{
- target_insert_fork_catchpoint (PIDGET (inferior_ptid));
+ return target_insert_fork_catchpoint (PIDGET (inferior_ptid));
}

/* Implement the "remove" breakpoint_ops method for fork catchpoints. */

static int
-remove_catch_fork (struct breakpoint *b)
+remove_catch_fork (struct bp_location *b)
{
return target_remove_fork_catchpoint (PIDGET (inferior_ptid));
}
@@ -5901,16 +5917,16 @@ static struct breakpoint_ops catch_fork_

/* Implement the "insert" breakpoint_ops method for vfork catchpoints. */

-static void
-insert_catch_vfork (struct breakpoint *b)
+static int
+insert_catch_vfork (struct bp_location *b)
{
- target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
+ return target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
}

/* Implement the "remove" breakpoint_ops method for vfork catchpoints. */

static int
-remove_catch_vfork (struct breakpoint *b)
+remove_catch_vfork (struct bp_location *b)
{
return target_remove_vfork_catchpoint (PIDGET (inferior_ptid));
}
@@ -5993,20 +6009,20 @@ static struct breakpoint_ops catch_vfork
/* Implement the "insert" breakpoint_ops method for syscall
catchpoints. */

-static void
-insert_catch_syscall (struct breakpoint *b)
+static int
+insert_catch_syscall (struct bp_location *b)
{
struct inferior *inf = current_inferior ();

++inf->total_syscalls_count;
- if (!b->syscalls_to_be_caught)
+ if (!b->owner->syscalls_to_be_caught)
++inf->any_syscall_count;
else
{
int i, iter;

for (i = 0;
- VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
+ VEC_iterate (int, b->owner->syscalls_to_be_caught, i, iter);
i++)
{
int elem;
@@ -6027,30 +6043,30 @@ insert_catch_syscall (struct breakpoint
}
}

- target_set_syscall_catchpoint (PIDGET (inferior_ptid),
- inf->total_syscalls_count != 0,
- inf->any_syscall_count,
- VEC_length (int, inf->syscalls_counts),
- VEC_address (int, inf->syscalls_counts));
+ return target_set_syscall_catchpoint (PIDGET (inferior_ptid),
+ inf->total_syscalls_count != 0,
+ inf->any_syscall_count,
+ VEC_length (int, inf->syscalls_counts),
+ VEC_address (int, inf->syscalls_counts));
}

/* Implement the "remove" breakpoint_ops method for syscall
catchpoints. */

static int
-remove_catch_syscall (struct breakpoint *b)
+remove_catch_syscall (struct bp_location *b)
{
struct inferior *inf = current_inferior ();

--inf->total_syscalls_count;
- if (!b->syscalls_to_be_caught)
+ if (!b->owner->syscalls_to_be_caught)
--inf->any_syscall_count;
else
{
int i, iter;

for (i = 0;
- VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
+ VEC_iterate (int, b->owner->syscalls_to_be_caught, i, iter);
i++)
{
int elem;
@@ -6349,14 +6365,14 @@ create_fork_vfork_event_catchpoint (stru

/* Exec catchpoints. */

-static void
-insert_catch_exec (struct breakpoint *b)
+static int
+insert_catch_exec (struct bp_location *b)
{
- target_insert_exec_catchpoint (PIDGET (inferior_ptid));
+ return target_insert_exec_catchpoint (PIDGET (inferior_ptid));
}

static int
-remove_catch_exec (struct breakpoint *b)
+remove_catch_exec (struct bp_location *b)
{
return target_remove_exec_catchpoint (PIDGET (inferior_ptid));
}
@@ -7984,6 +8000,37 @@ watchpoint_exp_is_const (const struct ex
return 1;
}

+/* Implement the "insert" breakpoint_ops method for hardware watchpoints. */
+
+static int
+insert_watchpoint (struct bp_location *bpt)
+{
+ return target_insert_watchpoint (bpt->address, bpt->length,
+ bpt->watchpoint_type, bpt->owner->cond_exp);
+}
+
+/* Implement the "remove" breakpoint_ops method for hardware watchpoints. */
+
+static int
+remove_watchpoint (struct bp_location *bpt)
+{
+ return target_remove_watchpoint (bpt->address, bpt->length,
+ bpt->watchpoint_type, bpt->owner->cond_exp);
+}
+
+/* The breakpoint_ops structure to be used in hardware watchpoints. */
+
+static struct breakpoint_ops watchpoint_breakpoint_ops =
+{
+ insert_watchpoint,
+ remove_watchpoint,
+ NULL, /* breakpoint_hit */
+ NULL, /* print_it */
+ NULL, /* print_one */
+ NULL, /* print_mention */
+ NULL /* print_recreate */
+};
+
/* accessflag: hw_write: watch write,
hw_read: watch read,
hw_access: watch access (read or write) */
@@ -8226,6 +8273,8 @@ watch_command_1 (char *arg, int accessfl
b->exp_string = savestring (exp_start, exp_end - exp_start);
b->val = val;
b->val_valid = 1;
+ b->ops = &watchpoint_breakpoint_ops;
+
if (cond_start)
b->cond_string = savestring (cond_start, cond_end - cond_start);
else
Index: gdb.git/gdb/breakpoint.h
===================================================================
--- gdb.git.orig/gdb/breakpoint.h 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/breakpoint.h 2010-08-16 20:17:23.000000000 -0300
@@ -339,16 +339,18 @@ struct bp_location
will be called instead of the performing the default action for this
bptype. */

-struct breakpoint_ops
+struct breakpoint_ops
{
- /* Insert the breakpoint or activate the catchpoint. Should raise
- an exception if the operation failed. */
- void (*insert) (struct breakpoint *);
+ /* Insert the breakpoint or watchpoint or activate the catchpoint.
+ Return 0 for success, 1 if the breakpoint, watchpoint or catchpoint
+ type is not supported, -1 for failure. */
+ int (*insert) (struct bp_location *);

/* Remove the breakpoint/catchpoint that was previously inserted
- with the "insert" method above. Return non-zero if the operation
- succeeded. */
- int (*remove) (struct breakpoint *);
+ with the "insert" method above. Return 0 for success, 1 if the
+ breakpoint, watchpoint or catchpoint type is not supported,
+ -1 for failure. */
+ int (*remove) (struct bp_location *);

/* Return non-zero if the debugger should tell the user that this
breakpoint was hit. */
@@ -525,6 +527,11 @@ struct breakpoint
/* Methods associated with this breakpoint. */
struct breakpoint_ops *ops;

+ /* When a watchpoint changes from hardware to software watchpoint, its
+ OPS field will be set to NULL. We need to remember its original value
+ so that we can restore it if the watchpoint is upgraded again later. */
+ struct breakpoint_ops *old_ops;
+
/* Is breakpoint's condition not yet parsed because we found
no location initially so had no context to parse
the condition in. */
Index: gdb.git/gdb/inf-child.c
===================================================================
--- gdb.git.orig/gdb/inf-child.c 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/inf-child.c 2010-08-16 20:17:23.000000000 -0300
@@ -94,36 +94,6 @@ inf_child_acknowledge_created_inferior (
created inferior" operation by a debugger. */
}

-static void
-inf_child_insert_fork_catchpoint (int pid)
-{
- /* This version of Unix doesn't support notification of fork
- events. */
-}
-
-static int
-inf_child_remove_fork_catchpoint (int pid)
-{
- /* This version of Unix doesn't support notification of fork
- events. */
- return 0;
-}
-
-static void
-inf_child_insert_vfork_catchpoint (int pid)
-{
- /* This version of Unix doesn't support notification of vfork
- events. */
-}
-
-static int
-inf_child_remove_vfork_catchpoint (int pid)
-{
- /* This version of Unix doesn't support notification of vfork
- events. */
- return 0;
-}
-
static int
inf_child_follow_fork (struct target_ops *ops, int follow_child)
{
@@ -132,30 +102,6 @@ inf_child_follow_fork (struct target_ops
return 0;
}

-static void
-inf_child_insert_exec_catchpoint (int pid)
-{
- /* This version of Unix doesn't support notification of exec
- events. */
-}
-
-static int
-inf_child_remove_exec_catchpoint (int pid)
-{
- /* This version of Unix doesn't support notification of exec
- events. */
- return 0;
-}
-
-static int
-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. */
- return 0;
-}
-
static int
inf_child_can_run (void)
{
@@ -193,14 +139,7 @@ inf_child_target (void)
t->to_terminal_info = child_terminal_info;
t->to_post_startup_inferior = inf_child_post_startup_inferior;
t->to_acknowledge_created_inferior = inf_child_acknowledge_created_inferior;
- t->to_insert_fork_catchpoint = inf_child_insert_fork_catchpoint;
- t->to_remove_fork_catchpoint = inf_child_remove_fork_catchpoint;
- t->to_insert_vfork_catchpoint = inf_child_insert_vfork_catchpoint;
- t->to_remove_vfork_catchpoint = inf_child_remove_vfork_catchpoint;
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_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;
Index: gdb.git/gdb/linux-nat.c
===================================================================
--- gdb.git.orig/gdb/linux-nat.c 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/linux-nat.c 2010-08-16 20:17:23.000000000 -0300
@@ -961,36 +961,34 @@ Attaching after process %d fork to child
}

\f
-static void
+static int
linux_child_insert_fork_catchpoint (int pid)
{
- if (! linux_supports_tracefork (pid))
- error (_("Your system does not support fork catchpoints."));
+ return !linux_supports_tracefork (pid);
}

-static void
+static int
linux_child_insert_vfork_catchpoint (int pid)
{
- if (!linux_supports_tracefork (pid))
- error (_("Your system does not support vfork catchpoints."));
+ return !linux_supports_tracefork (pid);
}

-static void
+static int
linux_child_insert_exec_catchpoint (int pid)
{
- if (!linux_supports_tracefork (pid))
- error (_("Your system does not support exec catchpoints."));
+ return !linux_supports_tracefork (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."));
+ if (!linux_supports_tracesysgood (pid))
+ return 1;
+
/* On GNU/Linux, we ignore the arguments. It means that we only
enable the syscall catchpoints, but do not disable them.
-
+
Also, we do not use the `table' information because we do not
filter system calls here. We let GDB do the logic for us. */
return 0;
Index: gdb.git/gdb/target.c
===================================================================
--- gdb.git.orig/gdb/target.c 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/target.c 2010-08-16 20:17:23.000000000 -0300
@@ -782,26 +782,26 @@ update_current_target (void)
(void (*) (int))
target_ignore);
de_fault (to_insert_fork_catchpoint,
- (void (*) (int))
- tcomplain);
+ (int (*) (int))
+ return_one);
de_fault (to_remove_fork_catchpoint,
(int (*) (int))
- tcomplain);
+ return_one);
de_fault (to_insert_vfork_catchpoint,
- (void (*) (int))
- tcomplain);
+ (int (*) (int))
+ return_one);
de_fault (to_remove_vfork_catchpoint,
(int (*) (int))
- tcomplain);
+ return_one);
de_fault (to_insert_exec_catchpoint,
- (void (*) (int))
- tcomplain);
+ (int (*) (int))
+ return_one);
de_fault (to_remove_exec_catchpoint,
(int (*) (int))
- tcomplain);
+ return_one);
de_fault (to_set_syscall_catchpoint,
(int (*) (int, int, int, int, int *))
- tcomplain);
+ return_one);
de_fault (to_has_exited,
(int (*) (int, int, int *))
return_zero);
@@ -3657,13 +3657,17 @@ debug_to_acknowledge_created_inferior (i
pid);
}

-static void
+static int
debug_to_insert_fork_catchpoint (int pid)
{
- debug_target.to_insert_fork_catchpoint (pid);
+ int retval;

- fprintf_unfiltered (gdb_stdlog, "target_insert_fork_catchpoint (%d)\n",
- pid);
+ retval = debug_target.to_insert_fork_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stdlog, "target_insert_fork_catchpoint (%d) = %d\n",
+ pid, retval);
+
+ return retval;
}

static int
@@ -3679,13 +3683,17 @@ debug_to_remove_fork_catchpoint (int pid
return retval;
}

-static void
+static int
debug_to_insert_vfork_catchpoint (int pid)
{
- debug_target.to_insert_vfork_catchpoint (pid);
+ int retval;

- fprintf_unfiltered (gdb_stdlog, "target_insert_vfork_catchpoint (%d)\n",
- pid);
+ retval = debug_target.to_insert_vfork_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stdlog, "target_insert_vfork_catchpoint (%d) = %d\n",
+ pid, retval);
+
+ return retval;
}

static int
@@ -3701,13 +3709,17 @@ debug_to_remove_vfork_catchpoint (int pi
return retval;
}

-static void
+static int
debug_to_insert_exec_catchpoint (int pid)
{
- debug_target.to_insert_exec_catchpoint (pid);
+ int retval;

- fprintf_unfiltered (gdb_stdlog, "target_insert_exec_catchpoint (%d)\n",
- pid);
+ retval = debug_target.to_insert_exec_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stdlog, "target_insert_exec_catchpoint (%d) = %d\n",
+ pid, retval);
+
+ return retval;
}

static int
Index: gdb.git/gdb/target.h
===================================================================
--- gdb.git.orig/gdb/target.h 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/target.h 2010-08-16 20:17:23.000000000 -0300
@@ -468,12 +468,12 @@ struct target_ops
char *, char *, char **, int);
void (*to_post_startup_inferior) (ptid_t);
void (*to_acknowledge_created_inferior) (int);
- void (*to_insert_fork_catchpoint) (int);
+ int (*to_insert_fork_catchpoint) (int);
int (*to_remove_fork_catchpoint) (int);
- void (*to_insert_vfork_catchpoint) (int);
+ int (*to_insert_vfork_catchpoint) (int);
int (*to_remove_vfork_catchpoint) (int);
int (*to_follow_fork) (struct target_ops *, int);
- void (*to_insert_exec_catchpoint) (int);
+ int (*to_insert_exec_catchpoint) (int);
int (*to_remove_exec_catchpoint) (int);
int (*to_set_syscall_catchpoint) (int, int, int, int, int *);
int (*to_has_exited) (int, int, int *);
@@ -1087,7 +1087,10 @@ int target_follow_fork (int follow_child

TABLE is an array of ints, indexed by syscall number. An element in
this array is nonzero if that syscall should be caught. This argument
- only matters if ANY_COUNT is zero. */
+ only matters if ANY_COUNT is zero.
+
+ Return 0 for success, 1 if syscall catchpoints are not supported or -1
+ for failure. */

#define target_set_syscall_catchpoint(pid, needed, any_count, table_size, table) \
(*current_target.to_set_syscall_catchpoint) (pid, needed, any_count, \
Index: gdb.git/gdb/testsuite/gdb.base/foll-exec.exp
===================================================================
--- gdb.git.orig/gdb/testsuite/gdb.base/foll-exec.exp 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/testsuite/gdb.base/foll-exec.exp 2010-08-16 20:17:23.000000000 -0300
@@ -89,7 +89,7 @@ proc do_exec_tests {} {
gdb_test "catch exec" "Catchpoint \[0-9\]* \\(exec\\)" "insert first exec catchpoint"
set has_exec_catchpoints 0
gdb_test_multiple "continue" "continue to first exec catchpoint" {
- -re ".*Your system does not support exec catchpoints.*$gdb_prompt $" {
+ -re ".*Your system does not support this type of catchpoint.*$gdb_prompt $" {
unsupported "continue to first exec catchpoint"
}
-re ".*Catchpoint.*$gdb_prompt $" {
Index: gdb.git/gdb/testsuite/gdb.base/foll-fork.exp
===================================================================
--- gdb.git.orig/gdb/testsuite/gdb.base/foll-fork.exp 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/testsuite/gdb.base/foll-fork.exp 2010-08-16 20:17:23.000000000 -0300
@@ -45,7 +45,7 @@ proc check_fork_catchpoints {} {
gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" "insert first fork catchpoint"
set has_fork_catchpoints 0
gdb_test_multiple "continue" "continue to first fork catchpoint" {
- -re ".*Your system does not support fork catchpoints.*$gdb_prompt $" {
+ -re ".*Your system does not support this type of catchpoint.*$gdb_prompt $" {
unsupported "continue to first fork catchpoint"
}
-re ".*Catchpoint.*$gdb_prompt $" {
Index: gdb.git/gdb/testsuite/gdb.base/foll-vfork.exp
===================================================================
--- gdb.git.orig/gdb/testsuite/gdb.base/foll-vfork.exp 2010-08-16 20:17:16.000000000 -0300
+++ gdb.git/gdb/testsuite/gdb.base/foll-vfork.exp 2010-08-16 20:17:23.000000000 -0300
@@ -74,7 +74,7 @@ proc check_vfork_catchpoints {} {
gdb_test "catch vfork" "Catchpoint \[0-9\]* \\(vfork\\)" "insert first vfork catchpoint"
set has_vfork_catchpoints 0
gdb_test_multiple "continue" "continue to first vfork catchpoint" {
- -re ".*Your system does not support vfork catchpoints.*$gdb_prompt $" {
+ -re ".*Your system does not support this type of catchpoint.*$gdb_prompt $" {
unsupported "continue to first vfork catchpoint"
}
-re ".*Catchpoint.*$gdb_prompt $" {