aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/breakpoint.c30
-rw-r--r--gdb/breakpoint.h8
-rw-r--r--gdb/linespec.c26
-rw-r--r--gdb/symtab.h1
5 files changed, 56 insertions, 21 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9de1b10..5901a15 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
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.
+ (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.
+
+2018-04-26 Pedro Alves <palves@redhat.com>
+
* elfread.c (elf_gnu_ifunc_resolve_by_got): Don't write to *ADDR_P
unless we actually resolved the ifunc.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 11b89bc..4e514d2 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -7156,37 +7156,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);
@@ -8650,6 +8642,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 062e390..1b045ae 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -490,6 +490,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 8951c1e..8a52f5e 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -4244,10 +4244,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);
@@ -4270,7 +4284,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 94b6b24..017a690 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1765,6 +1765,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. */