public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-jankratochvil-ifunc: more fixes
@ 2010-03-21 19:16 jkratoch
  0 siblings, 0 replies; only message in thread
From: jkratoch @ 2010-03-21 19:16 UTC (permalink / raw)
  To: archer-commits

The branch, archer-jankratochvil-ifunc has been updated
       via  2e6a55fcce3aaac63ecc5cfe0a8639fd9c06e267 (commit)
      from  67f0af148874dfeb8113562513bf71c34e19b5d4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 2e6a55fcce3aaac63ecc5cfe0a8639fd9c06e267
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Sun Mar 21 20:11:42 2010 +0100

    more fixes

-----------------------------------------------------------------------

Summary of changes:
 gdb/blockframe.c |   56 -------------------
 gdb/breakpoint.c |   23 ++++++--
 gdb/elfread.c    |  158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdbtypes.c   |    6 ++
 gdb/gdbtypes.h   |    1 +
 gdb/infcall.c    |   25 ++++++---
 gdb/parse.c      |    4 ++
 gdb/symtab.h     |   12 +++-
 8 files changed, 212 insertions(+), 73 deletions(-)

First 500 lines of diff:
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
index b7d298c..938f56d 100644
--- a/gdb/blockframe.c
+++ b/gdb/blockframe.c
@@ -332,62 +332,6 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address,
 					: FIND_PC_PARTIAL_FUNCTION_NORMAL;
 }
 
-int
-resolve_gnu_ifunc_by_got (struct program_space *pspace,
-			  const char *function_name,
-			  CORE_ADDR *function_addressp)
-{
-  struct objfile *objfile;
-  char *function_name_got_plt;
-
-  function_name_got_plt = alloca (strlen (function_name) + strlen ("@got.plt")
-				  + 1);
-  sprintf (function_name_got_plt, "%s@got.plt", function_name);
-
-  ALL_PSPACE_OBJFILES (pspace, objfile)
-    {
-      bfd *obfd = objfile->obfd;
-      struct minimal_symbol *msym;
-      CORE_ADDR pointer_address, function_address;
-      asection *plt;
-
-      msym = lookup_minimal_symbol (function_name_got_plt, NULL, objfile);
-      if (msym == NULL)
-	continue;
-      if (MSYMBOL_TYPE (msym) != mst_slot_got_plt)
-	continue;
-      pointer_address = SYMBOL_VALUE_ADDRESS (msym);
-
-      plt = bfd_get_section_by_name (obfd, ".plt");
-      if (plt == NULL)
-	continue;
-
-      {
-	struct gdbarch *gdbarch = objfile->gdbarch;
-	struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
-	size_t ptr_size = TYPE_LENGTH (ptr_type);
-	gdb_byte *buf = alloca (ptr_size);
-
-	if (MSYMBOL_SIZE (msym) != ptr_size)
-	  continue;
-	if (target_read_memory (pointer_address, buf, ptr_size) != 0)
-	  continue;
-	function_address = extract_typed_address (buf, ptr_type);
-      }
-
-      /* If .plt jumps back to .plt the symbol is still deferred for later
-	 resolution and it has no use for GDB.  */
-      if (bfd_get_section_vma (obfd, plt) <= function_address
-	  && function_address < bfd_get_section_vma (obfd, plt)
-				+ bfd_get_section_size (plt))
-	continue;
-
-      *function_addressp = function_address;
-      return 1;
-    }
-  return 0;
-}
-
 /* Return the innermost stack frame executing inside of BLOCK,
    or NULL if there is no such frame.  If BLOCK is NULL, just return NULL.  */
 
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 382197e..f6c0770 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5179,11 +5179,21 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc)
 	{
 	  struct breakpoint *b = loc->owner;
 
-	  if (!resolve_gnu_ifunc_by_got (loc->pspace, loc->function_name,
-					 &loc->address)
-	      && b->type == bp_breakpoint && b->loc == loc && loc->next == NULL
-	      && b->related_breakpoint == b)
-	    b->type = bp_gnu_ifunc_resolver;
+	  gdb_assert (loc->pspace == current_program_space);
+	  if (resolve_gnu_ifunc (loc->function_name, &loc->requested_address))
+	    {
+	      /* Recalculate ADDRESS based on new REQUESTED_ADDRESS.  */
+	      loc->address = adjust_breakpoint_address (loc->gdbarch,
+							loc->requested_address,
+							b->type);
+	    }
+	  else if (b->type == bp_breakpoint && b->loc == loc
+	           && loc->next == NULL && b->related_breakpoint == b)
+	    {
+	      /* Create only the whole new breakpoint of this type but do not
+		 mess more complicated breakpoints with multiple locations.  */
+	      b->type = bp_gnu_ifunc_resolver;
+	    }
 	}
 
       if (loc->function_name)
@@ -10627,6 +10637,9 @@ gnu_ifunc_resolver_return_stop (struct breakpoint *b)
     }
   gdb_assert (b->type == bp_gnu_ifunc_resolver);
 
+  gdb_assert (current_program_space == b->pspace);
+  gnu_ifunc_record_cache (gdbarch, b->addr_string, resolved_pc);
+
   sal = find_pc_line (resolved_pc, 0);
   sals.nelts = 1;
   sals.sals = &sal;
diff --git a/gdb/elfread.c b/gdb/elfread.c
index fa374cd..182dd40 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -660,6 +660,164 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table)
   do_cleanups (back_to);
 }
 
+/* Function does not check for possibly created duplicities in the cache.
+   Check it by resolve_gnu_ifunc_by_cache first.  */
+
+static struct minimal_symbol *
+gnu_ifunc_record_cache_unchecked (const char *function_name,
+				  CORE_ADDR function_address)
+{
+  struct minimal_symbol *msym, *msym_new;
+  asection *sect;
+  struct objfile *objfile;
+  char *function_name_gnu_ifunc_tgt;
+
+  msym = lookup_minimal_symbol_by_pc (function_address);
+  if (msym == NULL)
+    return NULL;
+  if (SYMBOL_VALUE_ADDRESS (msym) != function_address)
+    return NULL;
+  /* minimal symbols have always SYMBOL_OBJ_SECTION non-NULL.  */
+  sect = SYMBOL_OBJ_SECTION (msym)->the_bfd_section;
+  objfile = SYMBOL_OBJ_SECTION (msym)->objfile;
+
+  /* If .plt jumps back to .plt the symbol is still deferred for later
+     resolution and it has no use for GDB.  Besides ".text" this symbol can
+     reside also in ".opd" for ppc64 function descriptor.  */
+  if (strcmp (bfd_get_section_name (objfile->obfd, sect), ".plt") == 0)
+    return NULL;
+
+  function_name_gnu_ifunc_tgt = alloca (strlen (function_name)
+					+ strlen ("@gnu-ifunc-tgt") + 1);
+  sprintf (function_name_gnu_ifunc_tgt, "%s@gnu-ifunc-tgt", function_name);
+
+  /* Create new alias "@gnu-ifunc-tgt" for MSYM.  */
+  msym_new = record_minimal_symbol (function_name_gnu_ifunc_tgt,
+				    strlen (function_name_gnu_ifunc_tgt), 1,
+				    SYMBOL_VALUE_ADDRESS (msym),
+				    MSYMBOL_TYPE (msym), sect, objfile);
+  /* Should not happen.  */
+  if (msym_new == NULL)
+    return 0;
+
+  /* objfile->msymbols array is already allocated on obstack and it cannot be
+     easily extended.  Therefore <tab>-completion on symbol names will never
+     show the @gnu-ifunc-tgt symbol.  Link it at least to the hash table so
+     that resolve_gnu_ifunc_by_cache can find it.  */
+  add_minsym_to_hash_table (msym_new, objfile->msymbol_hash);
+    
+  MSYMBOL_SIZE (msym_new) = MSYMBOL_SIZE (msym);
+  return msym_new;
+}
+
+/* Check first the cache if it - unlikely - has not been populated since
+   bp_gnu_ifunc_resolver has been created.  gnu_ifunc_record_cache_unchecked
+   could create a duplicate symbol otherwise.  */
+
+void
+gnu_ifunc_record_cache (struct gdbarch *gdbarch, const char *function_name,
+			CORE_ADDR function_address)
+{
+  struct minimal_symbol *msym;
+
+  msym = resolve_gnu_ifunc_by_cache (function_name);
+  if (msym == NULL)
+    gnu_ifunc_record_cache_unchecked (function_name, function_address);
+  else if (SYMBOL_VALUE_ADDRESS (msym) != function_address)
+    {
+      /* This case indicates buggy inferior program.  GDB would need to update
+	 its MSYM cache symbol for function_address.  Anyway FUNCTION_NAME is
+	 never normally found in the case as in such case no
+	 bp_gnu_ifunc_resolver would be created in the first place.  */
+
+      warning (_("gnu-indirect-function \"%s\" has changed its resolved "
+		 "function_address from %s to %s; GDB is using the former one"),
+	       function_name, paddress (gdbarch, SYMBOL_VALUE_ADDRESS (msym)),
+	       paddress (gdbarch, function_address));
+    }
+}
+
+static struct minimal_symbol *
+resolve_gnu_ifunc_by_got (const char *function_name)
+{
+  char *function_name_got_plt;
+  struct objfile *objfile;
+
+  function_name_got_plt = alloca (strlen (function_name) + strlen ("@got.plt")
+				  + 1);
+  sprintf (function_name_got_plt, "%s@got.plt", function_name);
+
+  ALL_PSPACE_OBJFILES (current_program_space, objfile)
+    {
+      bfd *obfd = objfile->obfd;
+      struct gdbarch *gdbarch = objfile->gdbarch;
+      struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
+      size_t ptr_size = TYPE_LENGTH (ptr_type);
+      CORE_ADDR pointer_address, function_address;
+      asection *plt;
+      gdb_byte *buf = alloca (ptr_size);
+      struct minimal_symbol *msym;
+
+      msym = lookup_minimal_symbol (function_name_got_plt, NULL, objfile);
+      if (msym == NULL)
+	continue;
+      if (MSYMBOL_TYPE (msym) != mst_slot_got_plt)
+	continue;
+      pointer_address = SYMBOL_VALUE_ADDRESS (msym);
+
+      plt = bfd_get_section_by_name (obfd, ".plt");
+      if (plt == NULL)
+	continue;
+
+      if (MSYMBOL_SIZE (msym) != ptr_size)
+	continue;
+      if (target_read_memory (pointer_address, buf, ptr_size) != 0)
+	continue;
+      function_address = extract_typed_address (buf, ptr_type);
+
+      msym = gnu_ifunc_record_cache_unchecked (function_name, function_address);
+      if (msym == NULL)
+	continue;
+      return msym;
+    }
+
+  return NULL;
+}
+
+struct minimal_symbol *
+resolve_gnu_ifunc_by_cache (const char *function_name)
+{
+  char *function_name_gnu_ifunc_tgt;
+
+  function_name_gnu_ifunc_tgt = alloca (strlen (function_name)
+					+ strlen ("@gnu-ifunc-tgt") + 1);
+  sprintf (function_name_gnu_ifunc_tgt, "%s@gnu-ifunc-tgt", function_name);
+
+  return lookup_minimal_symbol (function_name_gnu_ifunc_tgt, NULL, NULL);
+}
+
+int
+resolve_gnu_ifunc (const char *function_name, CORE_ADDR *function_addressp)
+{
+  struct minimal_symbol *msym;
+
+  msym = resolve_gnu_ifunc_by_cache (function_name);
+  if (msym != NULL)
+    {
+      *function_addressp = SYMBOL_VALUE_ADDRESS (msym);
+      return 1;
+    }
+
+  msym = resolve_gnu_ifunc_by_got (function_name);
+  if (msym != NULL)
+    {
+      *function_addressp = SYMBOL_VALUE_ADDRESS (msym);
+      return 1;
+    }
+
+  return 0;
+}
+
 struct build_id
   {
     size_t size;
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 00e33b1..1329e0b 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -3602,6 +3602,12 @@ objfile_type (struct objfile *objfile)
 		 objfile);
   TYPE_TARGET_TYPE (objfile_type->nodebug_text_gnu_ifunc_symbol)
     = objfile_type->nodebug_text_symbol;
+  objfile_type->nodebug_got_plt_symbol
+    = init_type (TYPE_CODE_PTR, gdbarch_addr_bit (gdbarch) / 8, 0,
+		 "<text from jump slot in .got.plt, no debug info>",
+		 objfile);
+  TYPE_TARGET_TYPE (objfile_type->nodebug_got_plt_symbol)
+    = objfile_type->nodebug_text_symbol;
   objfile_type->nodebug_data_symbol
     = init_type (TYPE_CODE_INT,
 		 gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0,
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 95c9dd6..773f7a7 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1169,6 +1169,7 @@ struct objfile_type
   /* Types used for symbols with no debug information.  */
   struct type *nodebug_text_symbol;
   struct type *nodebug_text_gnu_ifunc_symbol;
+  struct type *nodebug_got_plt_symbol;
   struct type *nodebug_data_symbol;
   struct type *nodebug_unknown_symbol;
   struct type *nodebug_tls_symbol;
diff --git a/gdb/infcall.c b/gdb/infcall.c
index d72a64f..a9b0724 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -236,24 +236,31 @@ static CORE_ADDR
 gnu_ifunc_resolve (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   char *name_at_pc;
-  CORE_ADDR start_at_pc, retval;
+  CORE_ADDR start_at_pc, address;
   struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func;
-  struct value *function, *address;
+  struct value *function, *address_val;
 
   if (find_pc_partial_function (pc, &name_at_pc, &start_at_pc, NULL)
-      && start_at_pc == pc
-      && resolve_gnu_ifunc_by_got (current_program_space, name_at_pc, &retval))
-    return retval;
+      && start_at_pc == pc)
+    {
+      if (resolve_gnu_ifunc (name_at_pc, &address))
+	return address;
+    }
+  else
+    name_at_pc = NULL;
 
   function = allocate_value (func_func_type);
   set_value_address (function, pc);
 
   /* gnu-ifuncs have no arguments.  FUNCTION is the function entry address
      while ADDRESS is a possible function descriptor..  */
-  address = call_function_by_hand (function, 0, NULL);
-  return gdbarch_convert_from_func_ptr_addr (gdbarch,
-					     value_as_address (address),
-					     &current_target);
+  address_val = call_function_by_hand (function, 0, NULL);
+  address = value_as_address (address_val);
+
+  if (name_at_pc)
+    gnu_ifunc_record_cache (gdbarch, name_at_pc, address);
+
+  return gdbarch_convert_from_func_ptr_addr (gdbarch, address, &current_target);
 }
 
 static struct type *
diff --git a/gdb/parse.c b/gdb/parse.c
index cc90199..80bed03 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -547,6 +547,10 @@ write_exp_msymbol (struct minimal_symbol *msymbol)
       write_exp_elt_type (objfile_type (objfile)->nodebug_data_symbol);
       break;
 
+    case mst_slot_got_plt:
+      write_exp_elt_type (objfile_type (objfile)->nodebug_got_plt_symbol);
+      break;
+
     default:
       write_exp_elt_type (objfile_type (objfile)->nodebug_unknown_symbol);
       break;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index d01e3da..5da72c6 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -922,9 +922,15 @@ extern enum find_pc_partial_function_type
 
 extern void clear_pc_function_cache (void);
 
-extern int resolve_gnu_ifunc_by_got (struct program_space *pspace,
-				     const char *function_name,
-				     CORE_ADDR *function_addressp);
+extern int resolve_gnu_ifunc (const char *function_name,
+			      CORE_ADDR *function_addressp);
+
+extern struct minimal_symbol *resolve_gnu_ifunc_by_cache
+  (const char *function_name);
+
+extern void gnu_ifunc_record_cache (struct gdbarch *gdbarch,
+				    const char *function_name,
+				    CORE_ADDR function_address);
 
 /* lookup partial symbol table by address and section */
 


hooks/post-receive
--
Repository for Project Archer.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2010-03-21 19:16 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-21 19:16 [SCM] archer-jankratochvil-ifunc: more fixes jkratoch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).