aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2018-04-26 13:01:27 +0100
committerPedro Alves <palves@redhat.com>2018-04-26 13:08:47 +0100
commit20944a6e20324cd897bf6c4c5fd20ef7224dacaa (patch)
tree968bead0171a67545a55be23811d7ba0ee8d5439
parent1adeb822668d3bd7182ca9b8cf42a7261deb3c7f (diff)
downloadgdb-20944a6e20324cd897bf6c4c5fd20ef7224dacaa.zip
gdb-20944a6e20324cd897bf6c4c5fd20ef7224dacaa.tar.gz
gdb-20944a6e20324cd897bf6c4c5fd20ef7224dacaa.tar.bz2
Fix stepping past GNU ifunc resolvers (introduce lookup_msym_prefer)
When we're stepping (with "step"), we want to skip trampoline-like functions automatically, including GNU ifunc resolvers. That is done by infrun.c calling into: in_solib_dynsym_resolve_code -> svr4_in_dynsym_resolve_code -> in_gnu_ifunc_stub A problem here is that if there's a regular text symbol at the same address as the ifunc symbol, the minimal symbol lookup in in_gnu_ifunc_stub may miss the GNU ifunc symbol: (...) 41: 000000000000071a 53 FUNC GLOBAL DEFAULT 11 gnu_ifunc_resolver (...) 50: 000000000000071a 53 IFUNC GLOBAL DEFAULT 11 gnu_ifunc (...) This causes this FAIL in the tests added later in the series: (gdb) PASS: gdb.base/gnu-ifunc.exp: resolver_attr=1: resolver_debug=0: final_debug=0: resolver received HWCAP set step-mode on (gdb) PASS: gdb.base/gnu-ifunc.exp: resolver_attr=1: resolver_debug=0: final_debug=0: set step-mode on step 0x00007ffff7bd371a in gnu_ifunc_resolver () from build/gdb/testsuite/outputs/gdb.base/gnu-ifunc/gnu-ifunc-lib-1-0-0.so (gdb) FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=1: resolver_debug=0: final_debug=0: step Above, GDB simply thought that it stepped into a regular function, so it stopped stepping, while it should have continued stepping past the resolver. The fix is to teach minimal symbol lookup to prefer GNU ifunc symbols if desired. gdb/ChangeLog: 2018-04-26 Pedro Alves <palves@redhat.com> * minsyms.c (lookup_minimal_symbol_by_pc_section_1): Rename to ... (lookup_minimal_symbol_by_pc_section): ... this. Replace 'want_trampoline' parameter by a lookup_msym_prefer parameter. Handle it. (lookup_minimal_symbol_by_pc_section): Delete old implementation. (lookup_minimal_symbol_by_pc): Adjust. (in_gnu_ifunc_stub): Prefer GNU ifunc symbols. (lookup_solib_trampoline_symbol_by_pc): Adjust. * minsyms.h (lookup_msym_prefer): New enum. (lookup_minimal_symbol_by_pc_section): Replace 'want_trampoline' parameter by a lookup_msym_prefer parameter.
-rw-r--r--gdb/ChangeLog14
-rw-r--r--gdb/minsyms.c77
-rw-r--r--gdb/minsyms.h26
3 files changed, 68 insertions, 49 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4fa5bbc..b2b2191 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,19 @@
2018-04-26 Pedro Alves <palves@redhat.com>
+ * minsyms.c (lookup_minimal_symbol_by_pc_section_1): Rename to ...
+ (lookup_minimal_symbol_by_pc_section): ... this. Replace
+ 'want_trampoline' parameter by a lookup_msym_prefer parameter.
+ Handle it.
+ (lookup_minimal_symbol_by_pc_section): Delete old implementation.
+ (lookup_minimal_symbol_by_pc): Adjust.
+ (in_gnu_ifunc_stub): Prefer GNU ifunc symbols.
+ (lookup_solib_trampoline_symbol_by_pc): Adjust.
+ * minsyms.h (lookup_msym_prefer): New enum.
+ (lookup_minimal_symbol_by_pc_section): Replace 'want_trampoline'
+ parameter by a lookup_msym_prefer parameter.
+
+2018-04-26 Pedro Alves <palves@redhat.com>
+
* elfread.c (elf_gnu_ifunc_record_cache): Check if the symbol name
ends in "@plt" instead of looking at the symbol's section.
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 7ca3fcc..601baee 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -669,10 +669,9 @@ frob_address (struct objfile *objfile, CORE_ADDR *pc)
there are text and trampoline symbols at the same address.
Otherwise prefer mst_text symbols. */
-static struct bound_minimal_symbol
-lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc_in,
- struct obj_section *section,
- int want_trampoline)
+bound_minimal_symbol
+lookup_minimal_symbol_by_pc_section (CORE_ADDR pc_in, struct obj_section *section,
+ lookup_msym_prefer prefer)
{
int lo;
int hi;
@@ -682,10 +681,27 @@ lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc_in,
struct minimal_symbol *best_symbol = NULL;
struct objfile *best_objfile = NULL;
struct bound_minimal_symbol result;
- enum minimal_symbol_type want_type, other_type;
+ enum minimal_symbol_type want_type;
- want_type = want_trampoline ? mst_solib_trampoline : mst_text;
- other_type = want_trampoline ? mst_text : mst_solib_trampoline;
+ if (section == NULL)
+ {
+ section = find_pc_section (pc_in);
+ if (section == NULL)
+ return {};
+ }
+
+ switch (prefer)
+ {
+ case lookup_msym_prefer::TEXT:
+ want_type = mst_text;
+ break;
+ case lookup_msym_prefer::TRAMPOLINE:
+ want_type = mst_solib_trampoline;
+ break;
+ case lookup_msym_prefer::GNU_IFUNC:
+ want_type = mst_text_gnu_ifunc;
+ break;
+ }
/* We can not require the symbol found to be in section, because
e.g. IRIX 6.5 mdebug relies on this code returning an absolute
@@ -804,7 +820,7 @@ lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc_in,
preceding symbol too. If they are otherwise
identical prefer that one. */
if (hi > 0
- && MSYMBOL_TYPE (&msymbol[hi]) == other_type
+ && MSYMBOL_TYPE (&msymbol[hi]) != want_type
&& MSYMBOL_TYPE (&msymbol[hi - 1]) == want_type
&& (MSYMBOL_SIZE (&msymbol[hi])
== MSYMBOL_SIZE (&msymbol[hi - 1]))
@@ -901,41 +917,12 @@ lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc_in,
return result;
}
-struct bound_minimal_symbol
-lookup_minimal_symbol_by_pc_section (CORE_ADDR pc, struct obj_section *section)
-{
- if (section == NULL)
- {
- /* NOTE: cagney/2004-01-27: This was using find_pc_mapped_section to
- force the section but that (well unless you're doing overlay
- debugging) always returns NULL making the call somewhat useless. */
- section = find_pc_section (pc);
- if (section == NULL)
- {
- struct bound_minimal_symbol result;
-
- memset (&result, 0, sizeof (result));
- return result;
- }
- }
- return lookup_minimal_symbol_by_pc_section_1 (pc, section, 0);
-}
-
/* See minsyms.h. */
struct bound_minimal_symbol
lookup_minimal_symbol_by_pc (CORE_ADDR pc)
{
- struct obj_section *section = find_pc_section (pc);
-
- if (section == NULL)
- {
- struct bound_minimal_symbol result;
-
- memset (&result, 0, sizeof (result));
- return result;
- }
- return lookup_minimal_symbol_by_pc_section_1 (pc, section, 0);
+ return lookup_minimal_symbol_by_pc_section (pc, NULL);
}
/* Return non-zero iff PC is in an STT_GNU_IFUNC function resolver. */
@@ -943,8 +930,9 @@ lookup_minimal_symbol_by_pc (CORE_ADDR pc)
int
in_gnu_ifunc_stub (CORE_ADDR pc)
{
- struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
-
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol_by_pc_section (pc, NULL,
+ lookup_msym_prefer::GNU_IFUNC);
return msymbol.minsym && MSYMBOL_TYPE (msymbol.minsym) == mst_text_gnu_ifunc;
}
@@ -1453,12 +1441,9 @@ terminate_minimal_symbol_table (struct objfile *objfile)
static struct minimal_symbol *
lookup_solib_trampoline_symbol_by_pc (CORE_ADDR pc)
{
- struct obj_section *section = find_pc_section (pc);
- struct bound_minimal_symbol msymbol;
-
- if (section == NULL)
- return NULL;
- msymbol = lookup_minimal_symbol_by_pc_section_1 (pc, section, 1);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol_by_pc_section (pc, NULL,
+ lookup_msym_prefer::TRAMPOLINE);
if (msymbol.minsym != NULL
&& MSYMBOL_TYPE (msymbol.minsym) == mst_solib_trampoline)
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index 29d8283..40e69ae 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -238,6 +238,22 @@ struct bound_minimal_symbol lookup_minimal_symbol_solib_trampoline
struct minimal_symbol *lookup_minimal_symbol_by_pc_name
(CORE_ADDR, const char *, struct objfile *);
+enum class lookup_msym_prefer
+{
+ /* Prefer mst_text symbols. */
+ TEXT,
+
+ /* Prefer mst_solib_trampoline symbols when there are text and
+ trampoline symbols at the same address. Otherwise prefer
+ mst_text symbols. */
+ TRAMPOLINE,
+
+ /* Prefer mst_text_gnu_ifunc symbols when there are text and ifunc
+ symbols at the same address. Otherwise prefer mst_text
+ symbols. */
+ GNU_IFUNC,
+};
+
/* Search through the minimal symbol table for each objfile and find
the symbol whose address is the largest address that is still less
than or equal to PC, and which matches SECTION.
@@ -246,11 +262,15 @@ struct minimal_symbol *lookup_minimal_symbol_by_pc_name
instead.
The result has a non-NULL 'minsym' member if such a symbol is
- found, or NULL if PC is not in a suitable range. */
+ found, or NULL if PC is not in a suitable range.
+
+ See definition of lookup_msym_prefer for description of PREFER. By
+ default mst_text symbols are preferred. */
struct bound_minimal_symbol lookup_minimal_symbol_by_pc_section
- (CORE_ADDR,
- struct obj_section *);
+ (CORE_ADDR,
+ struct obj_section *,
+ lookup_msym_prefer prefer = lookup_msym_prefer::TEXT);
/* Backward compatibility: search through the minimal symbol table
for a matching PC (no section given).