This is the mail archive of the gdb-patches@sources.redhat.com 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]

Re: [PATCH RFA] solib-svr4.c patch for dynamic executables


On Nov 7,  4:16pm, Jim Blandy wrote:

> The way this patch decides whether or not to relocate the main
> executable seems questionable to me.  It looks like we're basing our
> decision on conditions which are suggestive, but not definitive.
> 
> We should look at the ABI to see what rules `exec' follows to decide
> whether to relocate the main executable, and then make GDB use the
> same rules.

See Ulrich's remark regarding the rules.

> At the very least, the test for the ".interp" section should be
> explained.

Ideally, our test for deciding whether to relocate the main executable
or not would look like this:

   if (bfd_get_start_address (exec_bfd) != pc)
      ... /* do the relocation(s) */

That is to say, if the address at which we are stopped (which we know
is the starting location of the program) is not the same as the start
address from the ELF file, then we need to relocate the sections.

Unfortunately, this won't work because *if* there's an interpreter,
the interpreter gets executed first and will branch to the ELF file
start address after the interpreter runs.  In other words, the start
address (from the executable) isn't the true start address when
there's an interepreter.

Let's explore an alternative.  Ulrich's patch upon which mine is
based had a slightly different test:

  if ((bfd_get_file_flags (exec_bfd) & DYNAMIC) != 0
      && bfd_get_start_address (exec_bfd) != stop_pc)

I have a hunch that this code is *practically* equivalent to my
proposed patch, but I could not convince myself of this fact.  (And I
did spend quite a while trying.)  I was concerned about the case where
the condition regarding the DYNAMIC flag (which is the same as
e_type == ET_DYN) being true in addition to a .interp section being
present.  If this were to happen, I have no idea what the right thing
to do would be, but it would almost certainly not be to relocate
symfile_objfile by the displacement given by the difference between
the address at which gdb is stopped and the start address from the
executable; it seemed safer just to leave it alone.

I really do think that testing for the presence of an interpreter
is the correct way to make the decision about whether to relocate
or not.  Think of the condition as being worded this way:

    If it makes sense to compare the start addresses AND
    the start addresses are different, then ...

The "makes sense to compare the start addresses" condition is
simply the test for the interpreter section being absent.

I agree that I need to explain this better in the code though.  Below
is a new patch which adds a comment explaining the test for the
interpreter section.  I also added a comment which explains that
relocation by a single constant is in fact mandated by the System V
ABI.  I removed my former remark which said that relocating by a
single constant is naive.

I withdraw my former patch in favor of the one below.

	Changes based on a patch from Ulrich Drepper:
	* solib-svr4.c (svr4_relocate_main_executable): New function.
	(svr4_solib_create_inferior_hook):  Call
	svr4_relocate_main_executable.

Index: solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.2
diff -u -p -r1.2 solib-svr4.c
--- solib-svr4.c	2000/10/30 23:31:17	1.2
+++ solib-svr4.c	2000/11/08 00:57:01
@@ -1437,6 +1437,96 @@ svr4_special_symbol_handling (void)
 #endif /* !SVR4_SHARED_LIBS */
 }
 
+/* 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 PC and if they are
+   different, the main executable is relocated by the proper amount. 
+   
+   As written it will only attempt to relocate executables which
+   lack interpreter sections.  It seems likely that only dynamic
+   linker executables will get relocated, though it should work
+   properly for a position-independent static executable as well.  */
+
+static void
+svr4_relocate_main_executable (void)
+{
+  asection *interp_sect;
+  CORE_ADDR pc = read_pc ();
+
+  /* Decide if the objfile needs to be relocated.  As indicated above,
+     we will only be here when execution is stopped at the beginning
+     of the program.  Relocation is necessary if the address at which
+     we are presently stopped differs from the start address stored in
+     the executable AND there's no interpreter section.  The condition
+     regarding the interpreter section is very important because if
+     there *is* an interpreter section, execution will begin there
+     instead.  When there is an interpreter section, the start address
+     is (presumably) used by the interpreter at some point to start
+     execution of the program.
+
+     If there is an interpreter, it is normal for it to be set to an
+     arbitrary address at the outset.  The job of finding it is
+     handled in enable_break().
+
+     So, to summarize, relocations are necessary when there is no
+     interpreter section and the start address obtained from the
+     executable is different from the address at which GDB is
+     currently stopped.  */
+
+  interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
+  if (interp_sect == NULL && bfd_get_start_address (exec_bfd) != pc)
+    {
+      struct cleanup *old_chain;
+      struct section_offsets *new_offsets;
+      int i, changed;
+      CORE_ADDR displacement;
+      
+      /* It is necessary to relocate the objfile.  The amount to
+	 relocate by is simply the address at which we are stopped
+	 minus the starting address from the executable.
+
+	 We relocate all of the sections by the same amount.  This
+	 behavior is mandated by recent editions of the System V ABI. 
+	 According to the System V Application Binary Interface,
+	 Edition 4.1, page 5-5:
+
+	   ...  Though the system chooses virtual addresses for
+	   individual processes, it maintains the segments' relative
+	   positions.  Because position-independent code uses relative
+	   addressesing between segments, the difference between
+	   virtual addresses in memory must match the difference
+	   between virtual addresses in the file.  The difference
+	   between the virtual address of any segment in memory and
+	   the corresponding virtual address in the file is thus a
+	   single constant value for any one executable or shared
+	   object in a given process.  This difference is the base
+	   address.  One use of the base address is to relocate the
+	   memory image of the program during dynamic linking.
+
+	 The same language also appears in Edition 4.0 of the System V
+	 ABI and is left unspecified in some of the earlier editions.  */
+
+      displacement = pc - bfd_get_start_address (exec_bfd);
+      changed = 0;
+
+      new_offsets = xcalloc (sizeof (struct section_offsets),
+			     symfile_objfile->num_sections);
+      old_chain = make_cleanup (free, new_offsets);
+
+      for (i = 0; i < symfile_objfile->num_sections; i++)
+	{
+	  if (displacement != ANOFFSET (symfile_objfile->section_offsets, i))
+	    changed = 1;
+	  new_offsets->offsets[i] = displacement;
+	}
+
+      if (changed)
+	objfile_relocate (symfile_objfile, new_offsets);
+
+      do_cleanups (old_chain);
+    }
+}
+
 /*
 
    GLOBAL FUNCTION
@@ -1489,9 +1579,12 @@ svr4_special_symbol_handling (void)
    Also, what if child has exit()ed?  Must exit loop somehow.
  */
 
-void
+static void
 svr4_solib_create_inferior_hook (void)
 {
+  /* Relocate the main executable if necessary.  */
+  svr4_relocate_main_executable ();
+
   /* If we are using the BKPT_AT_SYMBOL code, then we don't need the base
      yet.  In fact, in the case of a SunOS4 executable being run on
      Solaris, we can't get it yet.  current_sos will get it when it needs



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