"Cannot remove breakpoints because program is no longer writable" & catchpoints (was: Re: [patch 1/2] Convert hardware watchpoints to use breakpoint_ops)

Pedro Alves
2011-04-29T15:51:08Z

I just noticed:

(gdb) catch fork
Catchpoint 2 (fork)
(gdb) n
Cannot remove breakpoints because program is no longer writable.
Further execution is probably impossible.
96 args[j] = j;
(gdb)

Turns out to be a a simple overlook:

On Tuesday 11 January 2011 19:30:20, Thiago Jung Bauermann wrote:

> 2010-01-11 Thiago Jung Bauermann <bauerman@br.ibm.com>
>
> Convert hardware watchpoints to use breakpoint_ops.
>
> gdb/
> * 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.

On Tuesday 17 August 2010 20:41:11, Thiago Jung Bauermann wrote:
> 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...

Since inf_child_remove_*_catchpoint functions were removed (which
were returning success), the linux-nat.c target needs to gain its
own implementation of these functions, otherwise, it gets the default
implementation, that now returns error.

Tested on x86_64-linux. Applying on trunk and branch.

Pedro Alves

2011-04-29 Pedro Alves <pedro@codesourcery.com>

gdb/
* linux-nat.c (linux_child_remove_fork_catchpoint)
(linux_child_remove_vfork_catchpoint)
(linux_child_remove_exec_catchpoint): New functions.
(linux_target_install_ops): Install them.

---
gdb/linux-nat.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c 2011-04-29 16:32:33.605644000 +0100
+++ src/gdb/linux-nat.c 2011-04-29 16:36:16.285644002 +0100
@@ -944,18 +944,36 @@ linux_child_insert_fork_catchpoint (int
}

static int
+linux_child_remove_fork_catchpoint (int pid)
+{
+ return 0;
+}
+
+static int
linux_child_insert_vfork_catchpoint (int pid)
{
return !linux_supports_tracefork (pid);
}

static int
+linux_child_remove_vfork_catchpoint (int pid)
+{
+ return 0;
+}
+
+static int
linux_child_insert_exec_catchpoint (int pid)
{
return !linux_supports_tracefork (pid);
}

static int
+linux_child_remove_exec_catchpoint (int pid)
+{
+ return 0;
+}
+
+static int
linux_child_set_syscall_catchpoint (int pid, int needed, int any_count,
int table_size, int *table)
{
@@ -5214,8 +5232,11 @@ static void
linux_target_install_ops (struct target_ops *t)
{
t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint;
+ t->to_remove_fork_catchpoint = linux_child_remove_fork_catchpoint;
t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint;
+ t->to_remove_vfork_catchpoint = linux_child_remove_vfork_catchpoint;
t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
+ t->to_remove_exec_catchpoint = linux_child_remove_exec_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;