Reset PIE displacement on every run.

Change-Id: I3ee39bfc92357db827225ac7a04b7cd0ca23f517
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index bfbdcb8..75aa2ee 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2016-12-16  Doug Evans  <dje@google.com>
+
+	* fuchsia-tdep.c (fuchsia_solib_create_inferior_hook): New function.
+	(fuchsia_init_abi): Provide solib_create_inferior_hook.
+	* solib-svr4.c (svr4_apply_exec_displacement): New function.
+	(svr4_relocate_main_executable): Call it.
+	(svr4_solib_create_inferior_hook): Make non-static.
+	* solib-svr4.h (svr4_solib_create_inferior_hook): Declare.
+	(svr4_apply_exec_displacement): Declare.
+
 2016-12-15  Doug Evans  <dje@google.com>
 
 	* system-gdbinit/fuchsia.py: New file.
diff --git a/gdb/fuchsia-tdep.c b/gdb/fuchsia-tdep.c
index 5eef0af..48b38f2 100644
--- a/gdb/fuchsia-tdep.c
+++ b/gdb/fuchsia-tdep.c
@@ -600,6 +600,22 @@
   return addr;
 }
 
+/* For Fuchsia we need to reset the PIE exec displacement before we do
+   anything else.  In between the time the inferior starts and when the main
+   executable is loaded the old displacements are wrong and things like
+   re-setting breakpoints can get into worse trouble than normal (typically
+   the PIE addresses are low enough that memory reads/writes fail, but with
+   the previous run's displacement they might errantly work).  A better fix
+   would of course be to not even try to access memory until it exists but
+   that's a wee bit of work.  */
+
+static void
+fuchsia_solib_create_inferior_hook (int from_tty)
+{
+  svr4_apply_exec_displacement (0);
+  svr4_solib_create_inferior_hook (from_tty);
+}
+
 /* For Fuchsia we can't relocate the main executable until after we get
    to the shlib event breakpoint: The main executable is not loaded until
    the dynamic linker loads it.  */
@@ -653,13 +669,15 @@
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_lp64_fetch_link_map_offsets);
 
-  /* But we need to use our own so_ops vtable to handle exec displacement
-     computation.
+  /* We need to use our own so_ops vtable to handle exec displacement
+     computation. We also need to reset the exec displacement on each run.
      Initialize this lazily, to avoid an initialization order
      dependency on solib-svr4.c's _initialize routine.  */
   if (fuchsia_so_ops.handle_event == NULL)
     {
       fuchsia_so_ops = svr4_so_ops;
+      fuchsia_so_ops.solib_create_inferior_hook
+	= fuchsia_solib_create_inferior_hook;
       fuchsia_so_ops.handle_event = fuchsia_handle_solib_event;
     }
   set_solib_ops (gdbarch, &fuchsia_so_ops);
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 735fa18..f9446b0 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -2990,6 +2990,35 @@
 /* See solib-svr4.h.  */
 
 void
+svr4_apply_exec_displacement (CORE_ADDR displacement)
+{
+  if (symfile_objfile)
+    {
+      struct section_offsets *new_offsets;
+      int i;
+
+      new_offsets = XALLOCAVEC (struct section_offsets,
+				symfile_objfile->num_sections);
+
+      for (i = 0; i < symfile_objfile->num_sections; i++)
+	new_offsets->offsets[i] = displacement;
+
+      objfile_relocate (symfile_objfile, new_offsets);
+    }
+  else if (exec_bfd)
+    {
+      asection *asect;
+
+      for (asect = exec_bfd->sections; asect != NULL; asect = asect->next)
+	exec_set_section_address (bfd_get_filename (exec_bfd), asect->index,
+				  (bfd_section_vma (exec_bfd, asect)
+				   + displacement));
+    }
+}
+
+/* See solib-svr4.h.  */
+
+void
 svr4_relocate_main_executable (void)
 {
   CORE_ADDR displacement;
@@ -3025,29 +3054,7 @@
 
   /* Even DISPLACEMENT 0 is a valid new difference of in-memory vs. in-file
      addresses.  */
-
-  if (symfile_objfile)
-    {
-      struct section_offsets *new_offsets;
-      int i;
-
-      new_offsets = XALLOCAVEC (struct section_offsets,
-				symfile_objfile->num_sections);
-
-      for (i = 0; i < symfile_objfile->num_sections; i++)
-	new_offsets->offsets[i] = displacement;
-
-      objfile_relocate (symfile_objfile, new_offsets);
-    }
-  else if (exec_bfd)
-    {
-      asection *asect;
-
-      for (asect = exec_bfd->sections; asect != NULL; asect = asect->next)
-	exec_set_section_address (bfd_get_filename (exec_bfd), asect->index,
-				  (bfd_section_vma (exec_bfd, asect)
-				   + displacement));
-    }
+  svr4_apply_exec_displacement (displacement);
 }
 
 /* Implement the "create_inferior_hook" target_solib_ops method.
@@ -3069,7 +3076,7 @@
    addresses, and saving sufficient information about them to allow
    their symbols to be read at a later time.  */
 
-static void
+void
 svr4_solib_create_inferior_hook (int from_tty)
 {
   struct svr4_info *info;
diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
index 996d4aa..ed9c30f 100644
--- a/gdb/solib-svr4.h
+++ b/gdb/solib-svr4.h
@@ -84,10 +84,16 @@
    SVR4 run time loader.  */
 int svr4_in_dynsym_resolve_code (CORE_ADDR pc);
 
+/* Implement the "create_inferior_hook" target_solib_ops method.  */
+extern void svr4_solib_create_inferior_hook (int from_tty);
+
 /* Relocate the main executable.  This function should be called upon
    stopping the inferior process at the entry point to the program.
    The entry point from BFD is compared to the AT_ENTRY of AUXV and if they are
    different, the main executable is relocated by the proper amount.  */
 extern void svr4_relocate_main_executable (void);
 
+/* Apply the PIE displacement DISPLACEMENT to the main executable.  */
+extern void svr4_apply_exec_displacement (CORE_ADDR displacement);
+
 #endif /* solib-svr4.h */