Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: gdb-patches@sourceware.org
Subject: [PATCH v2 06/15] Fix setting breakpoints on ifunc functions after they're already resolved
Date: Sun, 25 Mar 2018 19:29:00 -0000	[thread overview]
Message-ID: <20180325191943.8246-7-palves@redhat.com> (raw)
In-Reply-To: <20180325191943.8246-1-palves@redhat.com>

This fixes setting breakpoints on ifunc functions by name after the
ifunc has already been resolved.

In that case, if you have debug info for the ifunc resolver, without
the fix, then gdb puts a breakpoint past the prologue of the resolver,
instead of setting a breakpoint at the ifunc target:

  break gnu_ifunc
  Breakpoint 4 at 0x7ffff7bd36f2: file src/gdb/testsuite/gdb.base/gnu-ifunc-lib.c, line 34.
  (gdb) continue
  Continuing.
  [Inferior 1 (process 13300) exited normally]
  (gdb)

above we should have stopped at "final", but didn't because we never
resolved the ifunc to the final location.

If you don't have debug info for the resolver, GDB manages to resolve
the ifunc target, but, it should be setting a breakpoint after the
prologue of the final function, and instead what you get is that GDB
sets a breakpoint on the first address of the target function.  With
the gnu-ifunc.exp tests added by a later patch, we get, without the
fix:

  (gdb) break gnu_ifunc
  Breakpoint 4 at 0x400753
  (gdb) continue
  Continuing.

  Breakpoint 4, final (arg=1) at src/gdb/testsuite/gdb.base/gnu-ifunc-final.c:20
  20	{

vs, fixed:

  (gdb) break gnu_ifunc
  Breakpoint 4 at 0x40075a: file src/gdb/testsuite/gdb.base/gnu-ifunc-final.c, line 21.
  (gdb) continue
  Continuing.

  Breakpoint 4, final (arg=2) at src/gdb/testsuite/gdb.base/gnu-ifunc-final.c:21
  21	  return arg + 1;
  (gdb)

Fix the problems above by moving the ifunc target resolving to
linespec.c, before we skip a function's prologue.  We need to save
something in the sal, so that set_breakpoint_location_function knows
that it needs to create a bp_gnu_ifunc_resolver bp_location.  Might as
well just save a pointer to the minsym.

gdb/ChangeLog:
yyyy-mm-dd  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.
	(add_location_to_breakpoint): Store the minsym and the objfile in
	the breakpoint location.
	* breakpoint.h (bp_location) <msymbol, objfile>: New fields.
	* linespec.c (minsym_found): Resolve GNU ifunc targets here.
	Record the minsym in the sal.
	* symtab.h (symtab_and_line) <msymbol>: New field.
---
 gdb/breakpoint.c | 30 ++++++++++++------------------
 gdb/breakpoint.h |  8 ++++++++
 gdb/linespec.c   | 26 +++++++++++++++++++++++---
 gdb/symtab.h     |  1 +
 4 files changed, 44 insertions(+), 21 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 9de0e6330c5..6840a200183 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -7180,37 +7180,29 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc)
       || loc->owner->type == bp_hardware_breakpoint
       || is_tracepoint (loc->owner))
     {
-      int is_gnu_ifunc;
       const char *function_name;
-      CORE_ADDR func_addr;
 
-      find_pc_partial_function_gnu_ifunc (loc->address, &function_name,
-					  &func_addr, NULL, &is_gnu_ifunc);
-
-      if (is_gnu_ifunc && !explicit_loc)
+      if (loc->msymbol != NULL
+	  && MSYMBOL_TYPE (loc->msymbol) == mst_text_gnu_ifunc
+	  && !explicit_loc)
 	{
 	  struct breakpoint *b = loc->owner;
 
-	  gdb_assert (loc->pspace == current_program_space);
-	  if (gnu_ifunc_resolve_name (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)
+	  function_name = MSYMBOL_LINKAGE_NAME (loc->msymbol);
+
+	  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;
 	      /* Remember the resolver's address for use by the return
 	         breakpoint.  */
-	      loc->related_address = func_addr;
+	      loc->related_address = loc->address;
 	    }
 	}
+      else
+	find_pc_partial_function (loc->address, &function_name, NULL, NULL);
 
       if (function_name)
 	loc->function_name = xstrdup (function_name);
@@ -8674,6 +8666,8 @@ add_location_to_breakpoint (struct breakpoint *b,
   loc->line_number = sal->line;
   loc->symtab = sal->symtab;
   loc->symbol = sal->symbol;
+  loc->msymbol = sal->msymbol;
+  loc->objfile = sal->objfile;
 
   set_breakpoint_location_function (loc,
 				    sal->explicit_pc || sal->explicit_line);
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index d8e2b73edc9..692a553cef1 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -491,6 +491,14 @@ public:
      ascertain when an event location was set at a different location than
      the one originally selected by parsing, e.g., inlined symbols.  */
   const struct symbol *symbol = NULL;
+
+  /* Similarly, the minimal symbol found by the location parser, if
+     any.  This may be used to ascertain if the location was
+     originally set on a GNU ifunc symbol.  */
+  const minimal_symbol *msymbol = NULL;
+
+  /* The objfile the symbol or minimal symbol were found in.  */
+  const struct objfile *objfile = NULL;
 };
 
 /* The possible return values for print_bpstat, print_it_normal,
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 7ff8dcf3a5b..c549ba09349 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -4334,10 +4334,24 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
 	      struct minimal_symbol *msymbol,
 	      std::vector<symtab_and_line> *result)
 {
-  struct symtab_and_line sal;
+  bool want_start_sal;
 
   CORE_ADDR func_addr;
-  if (msymbol_is_function (objfile, msymbol, &func_addr))
+  bool is_function = msymbol_is_function (objfile, msymbol, &func_addr);
+
+  if (is_function)
+    {
+      const char *msym_name = MSYMBOL_LINKAGE_NAME (msymbol);
+
+      if (MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc)
+	want_start_sal = gnu_ifunc_resolve_name (msym_name, &func_addr);
+      else
+	want_start_sal = true;
+    }
+
+  symtab_and_line sal;
+
+  if (is_function && want_start_sal)
     {
       sal = find_pc_sect_line (func_addr, NULL, 0);
 
@@ -4360,7 +4374,13 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
   else
     {
       sal.objfile = objfile;
-      sal.pc = MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
+      sal.msymbol = msymbol;
+      /* Store func_addr, not the minsym's address in case this was an
+	 ifunc that hasn't been resolved yet.  */
+      if (is_function)
+	sal.pc = func_addr;
+      else
+	sal.pc = MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
       sal.pspace = current_program_space;
     }
 
diff --git a/gdb/symtab.h b/gdb/symtab.h
index ddf4cb2e310..c6c643a93bf 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1760,6 +1760,7 @@ struct symtab_and_line
   struct symtab *symtab = NULL;
   struct symbol *symbol = NULL;
   struct obj_section *section = NULL;
+  struct minimal_symbol *msymbol = NULL;
   /* Line number.  Line numbers start at 1 and proceed through symtab->nlines.
      0 is never a valid line number; it is used to indicate that line number
      information is not available.  */
-- 
2.14.3


  parent reply	other threads:[~2018-03-25 19:29 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-25 19:19 [PATCH v2 00/15] Fixing GNU ifunc support Pedro Alves
2018-03-25 19:19 ` [PATCH v2 01/15] Fix breakpoints in ifunc after inferior resolved it (@got.plt symbol creation) Pedro Alves
2018-04-01  3:35   ` Simon Marchi
2018-04-10 21:20     ` Pedro Alves
2018-04-14 16:36       ` Simon Marchi
2018-03-25 19:19 ` [PATCH v2 11/15] Fix stepping past GNU ifunc resolvers (introduce lookup_msym_prefer) Pedro Alves
2018-06-18 20:26   ` [PATCH] Silence GCC "uninitialized" warning on minsyms.c:lookup_minimal_symbol_by_pc_section Sergio Durigan Junior
2018-06-19 15:22     ` Pedro Alves
2018-06-19 16:55       ` Sergio Durigan Junior
2018-06-19 18:47       ` Tom Tromey
2018-03-25 19:19 ` [PATCH v2 03/15] Calling ifunc functions when target has no debug info but resolver has Pedro Alves
2018-04-01  4:22   ` Simon Marchi
2018-04-10 21:48     ` Pedro Alves
2018-04-10 21:54       ` Pedro Alves
2018-03-25 19:19 ` [PATCH v2 05/15] Fix elf_gnu_ifunc_resolve_by_got buglet Pedro Alves
2018-04-01  4:32   ` Simon Marchi
2018-04-10 21:52     ` Pedro Alves
2018-03-25 19:19 ` [PATCH v2 02/15] Fix calling ifunc functions when resolver has debug info and different name Pedro Alves
2018-04-01  3:44   ` Simon Marchi
2018-04-10 21:20     ` Pedro Alves
2018-03-25 19:19 ` [PATCH v2 08/15] Eliminate find_pc_partial_function_gnu_ifunc Pedro Alves
2018-03-25 19:19 ` [PATCH v2 07/15] Breakpoints, don't skip prologue of ifunc resolvers with debug info Pedro Alves
2018-03-25 19:19 ` [PATCH v2 12/15] For PPC64/ELFv1: Introduce mst_data_gnu_ifunc Pedro Alves
2018-03-25 19:19 ` [PATCH v2 15/15] Fix resolving GNU ifunc bp locations when inferior runs resolver Pedro Alves
2018-03-25 19:25 ` [PATCH v2 09/15] Factor out minsym_found/find_function_start_sal overload Pedro Alves
2018-03-25 19:25 ` [PATCH v2 04/15] Calling ifunc functions when resolver has debug info, user symbol same name Pedro Alves
2018-03-25 19:28 ` [PATCH v2 14/15] Extend GNU ifunc testcases Pedro Alves
2018-03-25 19:29 ` [PATCH v2 10/15] For PPC64: elf_gnu_ifunc_record_cache: handle plt symbols in .text section Pedro Alves
2018-03-25 19:29 ` [PATCH v2 13/15] PPC64: always make synthetic .text symbols for GNU ifunc symbols Pedro Alves
2018-03-25 19:33   ` Pedro Alves
2018-03-26  7:54   ` Alan Modra
2018-03-25 19:29 ` Pedro Alves [this message]
2018-04-26 12:23 ` [PATCH v2 00/15] Fixing GNU ifunc support Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180325191943.8246-7-palves@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox