diff options
author | Pedro Alves <palves@redhat.com> | 2018-04-26 13:01:26 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2018-04-26 13:06:21 +0100 |
commit | 3467ec66bc1f30cf3ed7f9fe75234c96fc9c92d5 (patch) | |
tree | 53e1794b06b1caf1108ab3c4ee90fc39637b2ce2 /gdb/breakpoint.c | |
parent | 28f4fa4d0540ac6a23930202f39782167667e373 (diff) | |
download | fsf-binutils-gdb-3467ec66bc1f30cf3ed7f9fe75234c96fc9c92d5.zip fsf-binutils-gdb-3467ec66bc1f30cf3ed7f9fe75234c96fc9c92d5.tar.gz fsf-binutils-gdb-3467ec66bc1f30cf3ed7f9fe75234c96fc9c92d5.tar.bz2 |
Fix setting breakpoints on ifunc functions after they're already resolved
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:
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.
Diffstat (limited to 'gdb/breakpoint.c')
-rw-r--r-- | gdb/breakpoint.c | 30 |
1 files changed, 12 insertions, 18 deletions
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); |