This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[IRIX] eliminate deprecated_insert_raw_breakpoint uses


On 09/10/2014 04:50 PM, Maciej W. Rozycki wrote:
> On Wed, 10 Sep 2014, Pedro Alves wrote:
> 
>> Meanwhile, I'd prefer removing deprecated_insert_raw_breakpoint
>> now rather than keeping it just for IRIX.  I may send a
>> best-effort-but-untested patch for IRIX.  If things break, it'd be
>> the job of whoever shows up as wanting to maintain IRIX to
>> fix and modernize things further.  WDYT?
> 
>  FWIW I have no objections to this plan.  I wonder if there's anything 
> special here actually or if it's just that nobody bothered to convert this 
> code to using `create_internal_breakpoint' or suchlike.

There are definitely things here that could/should be modernized.
The loop in irix_solib_create_inferior_hook (and similars in other ports)
is something that's an old way of doing things and gotten in the way
before.

I think I understand this enough now.  See patch below, which
gets rid of that loop completely.

Untested, of course.

--------
>From 70c27f4a9a26c46d5ac356258ba2f76a6ac04269 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Wed, 10 Sep 2014 14:56:51 +0100
Subject: [PATCH] [IRIX] eliminate deprecated_insert_raw_breakpoint uses

The IRIX support wants to set a breakpoint to be hit when the startup
phase is complete, which is where shared libraries have been mapped
in.  AFAIU, for most IRIX ports, that location is the entry point.

For MIPS IRIX however, GDB needs to set a breakpoint earlier, in
__dbx_link, as explained by:

#ifdef SYS_syssgi
  /* On mips-irix, we need to stop the inferior early enough during
     the startup phase in order to be able to load the shared library
     symbols and insert the breakpoints that are located in these shared
     libraries.  Stopping at the program entry point is not good enough
     because the -init code is executed before the execution reaches
     that point.

     So what we need to do is to insert a breakpoint in the runtime
     loader (rld), more precisely in __dbx_link().  This procedure is
     called by rld once all shared libraries have been mapped, but before
     the -init code is executed.  Unfortuantely, this is not straightforward,
     as rld is not part of the executable we are running, and thus we need
     the inferior to run until rld itself has been mapped in memory.

     For this, we trace all syssgi() syscall exit events.  Each time
     we detect such an event, we iterate over each text memory maps,
     get its associated fd, and scan the symbol table for __dbx_link().
     When found, we know that rld has been mapped, and that we can insert
     the breakpoint at the symbol address.  Once the dbx_link() breakpoint
     has been inserted, the syssgi() notifications are no longer necessary,
     so they should be canceled.  */
  proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, FLAG_SET, 0);
#endif

The loop in irix_solib_create_inferior_hook then runs until whichever
breakpoint is hit first, the one set by solib-irix.c or the one set by
procfs.c.

Note the comment in disable_break talks about __dbx_init, but I think
that's a typo for __dbx_link:

 -  /* Note that it is possible that we have stopped at a location that
 -     is different from the location where we inserted our breakpoint.
 -     On mips-irix, we can actually land in __dbx_init(), so we should
 -     not check the PC against our breakpoint address here.  See procfs.c
 -     for more details.  */

This looks very much like referring to the loop in
irix_solib_create_inferior_hook stopping at __dbx_link instead of at
the entry point.

What this patch does is convert these deprecated raw breakpoints to
standard solib_event breakpoints.  When the first solib-event
breakpoint is hit, we delete all solib-event breakpoints.  We do that
in the so_ops->handle_event hook.

This allows getting rid of the loop in irix_solib_create_inferior_hook
completely, which should allow properly handling signals and other
events in the early startup phase, like in SVR4.

Built on x86_64 Fedora 20 with --enable-targets=all (builds
solib-irix.c), but otherwise completely untested.

gdb/ChangeLog:
2014-09-10  Pedro Alves  <palves@redhat.com>

	* procfs.c (dbx_link_bpt_addr, dbx_link_bpt): Delete globals.
	(remove_dbx_link_breakpoint): Delete function.
	(insert_dbx_link_bpt_in_file): Use create_solib_event_breakpoint
	instead of deprecated_insert_raw_breakpoint.  Don't check whether
	we hit __dbx_link here.
	(procfs_mourn_inferior): Don't delete the __dbx_link breakpoint
	here.
	* solib-irix.c (base_breakpoint): Delete global.
	(disable_break): Delete function.
	(enable_break): Use create_solib_event_breakpoint
	instead of deprecated_insert_raw_breakpoint.
	(irix_solib_handle_event): New function.
	(irix_solib_create_inferior_hook): Don't run the target or disable
	the mapping-complete breakpoint here.
	(_initialize_irix_solib): Install irix_solib_handle_event as
	so_ops->handle_event hook.
---
 gdb/procfs.c     |  51 +++++----------------------
 gdb/solib-irix.c | 104 +++++++++++++++----------------------------------------
 2 files changed, 35 insertions(+), 120 deletions(-)

diff --git a/gdb/procfs.c b/gdb/procfs.c
index 3465bc5..37ef05c 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -2902,13 +2902,6 @@ static void do_detach (int signo);
 static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
 				   int entry_or_exit, int mode, int from_tty);
 
-/* On mips-irix, we need to insert a breakpoint at __dbx_link during
-   the startup phase.  The following two variables are used to record
-   the address of the breakpoint, and the code that was replaced by
-   a breakpoint.  */
-static int dbx_link_bpt_addr = 0;
-static void *dbx_link_bpt;
-
 /* Sets up the inferior to be debugged.  Registers to trace signals,
    hardware faults, and syscalls.  Note: does not set RLC flag: caller
    may want to customize that.  Returns zero for success (note!
@@ -3380,23 +3373,6 @@ syscall_is_lwp_create (procinfo *pi, int scall)
   return 0;
 }
 
-/* Remove the breakpoint that we inserted in __dbx_link().
-   Does nothing if the breakpoint hasn't been inserted or has already
-   been removed.  */
-
-static void
-remove_dbx_link_breakpoint (void)
-{
-  if (dbx_link_bpt_addr == 0)
-    return;
-
-  if (deprecated_remove_raw_breakpoint (target_gdbarch (), dbx_link_bpt) != 0)
-    warning (_("Unable to remove __dbx_link breakpoint."));
-
-  dbx_link_bpt_addr = 0;
-  dbx_link_bpt = NULL;
-}
-
 #ifdef SYS_syssgi
 /* Return the address of the __dbx_link() function in the file
    refernced by ABFD by scanning its symbol table.  Return 0 if
@@ -3461,13 +3437,17 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
   sym_addr = dbx_link_addr (abfd);
   if (sym_addr != 0)
     {
+      struct breakpoint *dbx_link_bpt;
+
       /* Insert the breakpoint.  */
-      dbx_link_bpt_addr = sym_addr;
-      dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch (), NULL,
-						       sym_addr);
-      if (dbx_link_bpt == NULL)
+      dbx_link_bpt = create_solib_event_breakpoint (target_gdbarch (), sym_addr);
+
+      if (!breakpoints_always_inserted_mode ())
+	insert_breakpoint_locations ();
+      if (!dbx_link_bpt->loc->inserted)
 	{
 	  warning (_("Failed to insert dbx_link breakpoint."));
+	  delete_breakpoint (dbx_link_bpt);
 	  gdb_bfd_unref (abfd);
 	  return 0;
 	}
@@ -3894,14 +3874,6 @@ wait_again:
 #if (FLTTRACE != FLTBPT)	/* Avoid "duplicate case" error.  */
 		case FLTTRACE:
 #endif
-		  /* If we hit our __dbx_link() internal breakpoint,
-		     then remove it.  See comments in procfs_init_inferior()
-		     for more details.	*/
-		  if (dbx_link_bpt_addr != 0
-		      && dbx_link_bpt_addr
-			 == regcache_read_pc (get_current_regcache ()))
-		    remove_dbx_link_breakpoint ();
-
 		  wstat = (SIGTRAP << 8) | 0177;
 		  break;
 		case FLTSTACK:
@@ -4340,13 +4312,6 @@ procfs_mourn_inferior (struct target_ops *ops)
 
   generic_mourn_inferior ();
 
-  if (dbx_link_bpt != NULL)
-    {
-      deprecated_remove_raw_breakpoint (target_gdbarch (), dbx_link_bpt);
-      dbx_link_bpt_addr = 0;
-      dbx_link_bpt = NULL;
-    }
-
   inf_child_maybe_unpush_target (ops);
 }
 
diff --git a/gdb/solib-irix.c b/gdb/solib-irix.c
index 12ed766..e6fada9 100644
--- a/gdb/solib-irix.c
+++ b/gdb/solib-irix.c
@@ -240,8 +240,6 @@ fetch_lm_info (CORE_ADDR addr)
 /* The symbol which starts off the list of shared libraries.  */
 #define DEBUG_BASE "__rld_obj_head"
 
-static void *base_breakpoint;
-
 static CORE_ADDR debug_base;	/* Base of dynamic linker structures.  */
 
 /* Locate the base address of dynamic linker structs.
@@ -293,34 +291,6 @@ locate_base (void)
   return (address);
 }
 
-/* Remove the "mapping changed" breakpoint.
-
-   Removes the breakpoint that gets hit when the dynamic linker
-   completes a mapping change.  */
-
-static int
-disable_break (void)
-{
-  int status = 1;
-
-  /* Note that breakpoint address and original contents are in our address
-     space, so we just need to write the original contents back.  */
-
-  if (deprecated_remove_raw_breakpoint (target_gdbarch (), base_breakpoint) != 0)
-    {
-      status = 0;
-    }
-
-  base_breakpoint = NULL;
-
-  /* Note that it is possible that we have stopped at a location that
-     is different from the location where we inserted our breakpoint.
-     On mips-irix, we can actually land in __dbx_init(), so we should
-     not check the PC against our breakpoint address here.  See procfs.c
-     for more details.  */
-
-  return (status);
-}
 
 /* Arrange for dynamic linker to hit breakpoint.
 
@@ -332,23 +302,35 @@ enable_break (void)
 {
   if (symfile_objfile != NULL && has_stack_frames ())
     {
-      struct frame_info *frame = get_current_frame ();
-      struct address_space *aspace = get_frame_address_space (frame);
       CORE_ADDR entry_point;
 
-      if (!entry_point_address_query (&entry_point))
-	return 0;
-
-      base_breakpoint = deprecated_insert_raw_breakpoint (target_gdbarch (),
-							  aspace, entry_point);
-
-      if (base_breakpoint != NULL)
-	return 1;
+      if (entry_point_address_query (&entry_point))
+	{
+	  create_solib_event_breakpoint (target_gdbarch (), entry_point);
+	  return 1;
+	}
     }
 
   return 0;
 }
 
+/* Implement the "handle_event" target_solib_ops method.  */
+
+static void
+irix_solib_handle_event (void)
+{
+  /* We are now at the "mapping complete" breakpoint, we no longer
+     need it.  Note that it is possible that we have stopped at a
+     location that is different from the location where we inserted
+     our breakpoint: On mips-irix, we can actually land in
+     __dbx_link(), so we should not check the PC against our
+     breakpoint address here.  See procfs.c for more details.  */
+  remove_solib_event_breakpoints ();
+
+  /* The caller calls solib_add, which will add any shared libraries
+     that were mapped in.  */
+}
+
 /* Implement the "create_inferior_hook" target_solib_ops method.
 
    For SunOS executables, this first instruction is typically the
@@ -409,43 +391,10 @@ irix_solib_create_inferior_hook (int from_tty)
       return;
     }
 
-  /* Now run the target.  It will eventually hit the breakpoint, at
-     which point all of the libraries will have been mapped in and we
-     can go groveling around in the dynamic linker structures to find
-     out what we need to know about them.  */
-
-  tp = inferior_thread ();
-
-  clear_proceed_status (0);
-
-  inf->control.stop_soon = STOP_QUIETLY;
-  tp->suspend.stop_signal = GDB_SIGNAL_0;
-
-  do
-    {
-      target_resume (pid_to_ptid (-1), 0, tp->suspend.stop_signal);
-      wait_for_inferior ();
-    }
-  while (tp->suspend.stop_signal != GDB_SIGNAL_TRAP);
-
-  /* We are now either at the "mapping complete" breakpoint (or somewhere
-     else, a condition we aren't prepared to deal with anyway), so adjust
-     the PC as necessary after a breakpoint, disable the breakpoint, and
-     add any shared libraries that were mapped in.  */
-
-  if (!disable_break ())
-    {
-      warning (_("shared library handler failed to disable breakpoint"));
-    }
-
-  /* solib_add will call reinit_frame_cache.
-     But we are stopped in the startup code and we might not have symbols
-     for the startup code, so heuristic_proc_start could be called
-     and will put out an annoying warning.
-     Delaying the resetting of stop_soon until after symbol loading
-     suppresses the warning.  */
-  solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
-  inf->control.stop_soon = NO_STOP_QUIETLY;
+  /* The target will eventually hit the breakpoint, at which point all
+     of the libraries will have been mapped in and we can go groveling
+     around in the dynamic linker structures to find out what we need
+     to know about them.  */
 }
 
 /* Implement the "current_sos" target_so_ops method.  */
@@ -653,4 +602,5 @@ _initialize_irix_solib (void)
   irix_so_ops.open_symbol_file_object = irix_open_symbol_file_object;
   irix_so_ops.in_dynsym_resolve_code = irix_in_dynsym_resolve_code;
   irix_so_ops.bfd_open = solib_bfd_open;
+  irix_so_ops.handle_event = irix_solib_handle_event;
 }
-- 
1.9.3



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]