This is the mail archive of the gdb-cvs@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]

[binutils-gdb] Breakpoints, don't skip prologue of ifunc resolvers with debug info


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=76af0f26356580771a18c37de4ebccdfbc449356

commit 76af0f26356580771a18c37de4ebccdfbc449356
Author: Pedro Alves <palves@redhat.com>
Date:   Thu Apr 26 13:01:26 2018 +0100

    Breakpoints, don't skip prologue of ifunc resolvers with debug info
    
    Without this patch, some of the tests added to gdb.base/gnu-ifunc.exp
    by a following patch fail like so:
    
      FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=0: resolver_debug=1: resolved_debug=0: set-break: before resolving: break gnu_ifunc
      FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=0: resolver_debug=1: resolved_debug=0: set-break: before resolving: info breakpoints
      FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=0: resolver_debug=1: resolved_debug=0: set-break: after resolving: break gnu_ifunc
      FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=0: resolver_debug=1: resolved_debug=0: set-break: after resolving: info breakpoints
      FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=0: resolver_debug=1: resolved_debug=1: set-break: before resolving: break gnu_ifunc
      FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=0: resolver_debug=1: resolved_debug=1: set-break: before resolving: info breakpoints
      FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=0: resolver_debug=1: resolved_debug=1: set-break: after resolving: break gnu_ifunc
      FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=0: resolver_debug=1: resolved_debug=1: set-break: after resolving: info breakpoints
    
    All of them trigger iff:
    
     - you have debug info for the ifunc resolver.
     - the resolver and the user-visible symbol have the same name.
    
    If you have an ifunc that has a resolver with the same name as the
    user visible symbol, debug info for the resolver masks out the ifunc
    minsym.  When you set a breakpoint by name on the user visible symbol,
    GDB finds the DWARF symbol for the resolver, and thinking that it's a
    regular function, sets a breakpoint location past its prologue.
    
    Like so, location 1.2, before the ifunc is resolved by the inferior:
    
      (gdb) break gnu_ifunc
      Breakpoint 2 at 0x7ffff7bd36ea (2 locations)
      (gdb) info breakpoints
      Num     Type           Disp Enb Address            What
      1       breakpoint     keep y   <MULTIPLE>
      1.1                         y     0x00007ffff7bd36ea <gnu_ifunc>
      1.2                         y     0x00007ffff7bd36f2 in gnu_ifunc at src/gdb/testsuite/gdb.base/gnu-ifunc-lib.c:34
      (gdb)
    
    And like so, location 2.2, if you set the breakpoint after the ifunc
    is resolved by the inferior (to "final"):
    
      (gdb) break gnu_ifunc
      Breakpoint 5 at 0x400757 (2 locations)
      (gdb) info breakpoints
      Num     Type           Disp Enb Address            What
      2       breakpoint     keep y   <MULTIPLE>
      2.1                         y     0x000000000040075a in final at src/gdb/testsuite/gdb.base/gnu-ifunc-resd.c:21
      2.2                         y     0x00007ffff7bd36f2 in gnu_ifunc at src/gdb/testsuite/gdb.base/gnu-ifunc-lib.c:34
      (gdb)
    
    I don't think this is right because when users set a breakpoint at an
    ifunc, they don't care about debugging the resolver.  Instead what you
    should is a single location for the ifunc in the first case, and a
    single location of the ifunc target in the second case.
    
    gdb/ChangeLog:
    2018-04-26  Pedro Alves  <palves@redhat.com>
    
    	* linespec.c (struct bound_minimal_symbol_search_key): New.
    	(convert_linespec_to_sals): Sort minimal symbols earlier.  Don't
    	skip first line if we found a GNU ifunc minimal symbol by name.
    	(compare_msymbols): Change parameters to work with a destructured
    	lhs minsym.
    	(compare_msymbols_for_qsort, compare_msymbols_for_bsearch): New
    	functions.

Diff:
---
 gdb/ChangeLog  | 10 ++++++++++
 gdb/linespec.c | 60 +++++++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5901a15..6a94e75 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,15 @@
 2018-04-26  Pedro Alves  <palves@redhat.com>
 
+	* linespec.c (struct bound_minimal_symbol_search_key): New.
+	(convert_linespec_to_sals): Sort minimal symbols earlier.  Don't
+	skip first line if we found a GNU ifunc minimal symbol by name.
+	(compare_msymbols): Change parameters to work with a destructured
+	lhs minsym.
+	(compare_msymbols_for_qsort, compare_msymbols_for_bsearch): New
+	functions.
+
+2018-04-26  Pedro Alves  <palves@redhat.com>
+
 	* breakpoint.c (set_breakpoint_location_function): Don't resolve
 	ifunc targets here.  Instead, if we have an ifunc minsym, use its
 	address/name.
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 8a52f5e..b2deabe 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -2258,12 +2258,6 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
   else if (ls->function_symbols != NULL || ls->minimal_symbols != NULL)
     {
       /* We have just a bunch of functions and/or methods.  */
-      int i;
-      struct symtab_and_line sal;
-      struct symbol *sym;
-      bound_minimal_symbol_d *elem;
-      struct program_space *pspace;
-
       if (ls->function_symbols != NULL)
 	{
 	  /* Sort symbols so that symbols with the same program space are next
@@ -2272,30 +2266,66 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 		 VEC_length (symbolp, ls->function_symbols),
 		 sizeof (symbolp), compare_symbols);
 
-	  for (i = 0; VEC_iterate (symbolp, ls->function_symbols, i, sym); ++i)
+	  struct symbol *sym;
+	  for (int i = 0; VEC_iterate (symbolp, ls->function_symbols, i, sym); ++i)
 	    {
-	      pspace = SYMTAB_PSPACE (symbol_symtab (sym));
+	      program_space *pspace = SYMTAB_PSPACE (symbol_symtab (sym));
 	      set_current_program_space (pspace);
-	      if (symbol_to_sal (&sal, state->funfirstline, sym)
-		  && maybe_add_address (state->addr_set, pspace, sal.pc))
-		add_sal_to_sals (state, &sals, &sal,
-				 SYMBOL_NATURAL_NAME (sym), 0);
+
+	      /* Don't skip to the first line of the function if we
+		 had found an ifunc minimal symbol for this function,
+		 because that means that this function is an ifunc
+		 resolver with the same name as the ifunc itself.  */
+	      bool found_ifunc = false;
+
+	      if (state->funfirstline
+		   && ls->minimal_symbols != NULL
+		   && SYMBOL_CLASS (sym) == LOC_BLOCK)
+		{
+		  const CORE_ADDR addr
+		    = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+
+		  bound_minimal_symbol_d *elem;
+		  for (int m = 0;
+		       VEC_iterate (bound_minimal_symbol_d, ls->minimal_symbols,
+				    m, elem);
+		       ++m)
+		    {
+		      if (MSYMBOL_TYPE (elem->minsym) == mst_text_gnu_ifunc
+			  && BMSYMBOL_VALUE_ADDRESS (*elem) == addr)
+			{
+			  found_ifunc = true;
+			  break;
+			}
+		    }
+		}
+
+	      if (!found_ifunc)
+		{
+		  symtab_and_line sal;
+		  if (symbol_to_sal (&sal, state->funfirstline, sym)
+		      && maybe_add_address (state->addr_set, pspace, sal.pc))
+		    add_sal_to_sals (state, &sals, &sal,
+				     SYMBOL_NATURAL_NAME (sym), 0);
+		}
 	    }
 	}
 
       if (ls->minimal_symbols != NULL)
 	{
-	  /* Sort minimal symbols by program space, too.  */
+	  /* Sort minimal symbols by program space, too  */
 	  qsort (VEC_address (bound_minimal_symbol_d, ls->minimal_symbols),
 		 VEC_length (bound_minimal_symbol_d, ls->minimal_symbols),
 		 sizeof (bound_minimal_symbol_d), compare_msymbols);
 
-	  for (i = 0;
+	  bound_minimal_symbol_d *elem;
+
+	  for (int i = 0;
 	       VEC_iterate (bound_minimal_symbol_d, ls->minimal_symbols,
 			    i, elem);
 	       ++i)
 	    {
-	      pspace = elem->objfile->pspace;
+	      program_space *pspace = elem->objfile->pspace;
 	      set_current_program_space (pspace);
 	      minsym_found (state, elem->objfile, elem->minsym, &sals);
 	    }


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