diff options
-rw-r--r-- | gdb/ChangeLog | 12 | ||||
-rw-r--r-- | gdb/breakpoint.c | 30 | ||||
-rw-r--r-- | gdb/breakpoint.h | 8 | ||||
-rw-r--r-- | gdb/linespec.c | 26 | ||||
-rw-r--r-- | gdb/symtab.h | 1 |
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. */ |