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]

crash/regression with ia64 targets (was: "Re: [PATCH] use gdbarch_addr_bits_remove for entry point address")


> 2012-11-24  Daniel Jacobowitz  <dan@codesourcery.com>
> 	    Kazu Hirata  <kazu@codesourcery.com>
> 	    Yao Qi  <yao@codesourcery.com>
> 
> 	* objfiles.c (entry_point_address_query): Move some code ...
> 	(init_entry_point_info): ... here.
> 	* solib-svr4.c (exec_entry_point): Likewise.
> 	* symfile.c (generic_load): Call gdbarch_addr_bits_remove on
> 	the entry address.

Unfortunately, this patch breaks GDB on ia64 (linux and hpux) :-(.
Take any program, and try loading it in GDB:

    (gdb) file hello
    Reading symbols from /[...]/hello...
    zsh: 9462 segmentation fault  /[...]/gdb

What happens is that we've now added a call to
gdbarch_convert_from_func_ptr_addr inside init_entry_point_info,
which is called from syms_from_objfile *before* the objfile's
section_offsets array is allocated.

On ia64, gdbarch_convert_from_func_ptr_addr resolves to
ia64_convert_from_func_ptr_addr, which calls find_pc_section.
This, in turns calls update_section_map, which does a sort
on all sections, where qsort_cmp uses the obj_section_addr
macro:

#define obj_section_addr(s)                                             \
  (bfd_get_section_vma ((s)->objfile->obfd, s->the_bfd_section)         \
   + obj_section_offset (s))

... and obj_section_offset is defined as:

#define obj_section_offset(s)                                           \
  (((s)->objfile->section_offsets)->offsets[(s)->the_bfd_section->index])
                  ^^^^^^^^^^^^^^^^^^

Basically, to resolve whether our pointer is pointing to a descriptor
or not, we need to find its associated section. But to find the section,
we need the section_offsets to be defined.

So, to me, it looks like the attempt at resolving the entry point
is performed too early. And to make things even more fun, there
are cases where we do not allocated section_offsets at all:

  if (objfile->sf == NULL)
    return;     /* No symbols.  */

But the other worrisome element is that most calls to
init_entry_point_info are made from routines used as
the "sym_init" struct sym_fns hook, and this hook is
in fact called, in syms_from_objfile, before the section_offsets
table is allocated.

Since syms_from_objfile is calling init_entry_point_info,
it seems to me that the call to init_entry_point_info in
the "sym_init" hooks are redundant, and could be removed,
clearing one hurdle.

The other hurdle is making sure that init_entry_point_info
is called *after* the section offsets have been allocated.
Which means we need to make sure that we always allocate
some, including in the case where no symbols are found.
This must also become a documented invariant.

Attached is a prototype that seems to work on ia64-linux.
I've only tested it against our testsuite for now, but it will
need to be tested with the official testsuite on GNU/Linux,
as well as on Darwin, AiX, and maybe Windows (although,
I think the changes removing the calls to init_entry_point_info
should be fine).

Note that there is a second call to init_entry_point_info,
this time inside reread_symbols, but this one should be fine.

This patch also begs the question whether we might want to
move init_entry_point_info to objfiles.c and make it static.

Thoughts?

-- 
Joel
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 3789995..186c8d2 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -468,8 +468,6 @@ coff_symfile_init (struct objfile *objfile)
      find this causes a significant slowdown in gdb then we could
      set it in the debug symbol readers only when necessary.  */
   objfile->flags |= OBJF_REORDERED;
-
-  init_entry_point_info (objfile);
 }
 
 /* This function is called for every section; it finds the outer
diff --git a/gdb/machoread.c b/gdb/machoread.c
index 6a6eaa1..c0e6d90 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -79,7 +79,6 @@ static void
 macho_symfile_init (struct objfile *objfile)
 {
   objfile->flags |= OBJF_REORDERED;
-  init_entry_point_info (objfile);
 }
 
 /*  Add a new OSO to the vector of OSO to load.  */
diff --git a/gdb/symfile.c b/gdb/symfile.c
index bc4f40a..f182617 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -929,8 +929,8 @@ read_symbols (struct objfile *objfile, int add_flags)
    an extra symbol file such as dynamically loaded code, and wether
    breakpoint reset should be deferred.  */
 
-void
-syms_from_objfile (struct objfile *objfile,
+static void
+syms_from_objfile_1 (struct objfile *objfile,
                    struct section_addr_info *addrs,
                    struct section_offsets *offsets,
                    int num_offsets,
@@ -943,11 +943,19 @@ syms_from_objfile (struct objfile *objfile,
   gdb_assert (! (addrs && offsets));
 
   clear_ada_sym_cache ();
-  init_entry_point_info (objfile);
   objfile->sf = find_sym_fns (objfile->obfd);
 
   if (objfile->sf == NULL)
-    return;	/* No symbols.  */
+    {
+      int num_sections = bfd_count_sections (objfile->obfd);
+      size_t size = SIZEOF_N_SECTION_OFFSETS (num_offsets);
+
+      objfile->num_sections = num_sections;
+      objfile->section_offsets
+        = obstack_alloc (&objfile->objfile_obstack, size);
+      memset (objfile->section_offsets, 0, size);
+      return;	/* No symbols.  */
+    }
 
   /* Make sure that partially constructed symbol tables will be cleaned up
      if an error occurs during symbol reading.  */
@@ -1028,6 +1036,17 @@ syms_from_objfile (struct objfile *objfile,
   xfree (local_addr);
 }
 
+void
+syms_from_objfile (struct objfile *objfile,
+                   struct section_addr_info *addrs,
+                   struct section_offsets *offsets,
+                   int num_offsets,
+		   int add_flags)
+{
+  syms_from_objfile_1 (objfile, addrs, offsets, num_offsets, add_flags);
+  init_entry_point_info (objfile);
+}
+
 /* Perform required actions after either reading in the initial
    symbols for a new objfile, or mapping in the symbols from a reusable
    objfile.  ADD_FLAGS is a bitmask of enum symfile_add_flags.  */
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 2e562ed..e340b39 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -1927,8 +1927,6 @@ xcoff_symfile_init (struct objfile *objfile)
      find this causes a significant slowdown in gdb then we could
      set it in the debug symbol readers only when necessary.  */
   objfile->flags |= OBJF_REORDERED;
-
-  init_entry_point_info (objfile);
 }
 
 /* Perform any local cleanups required when we are done with a particular

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