From patchwork Fri Mar 9 21:16:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 26270 Received: (qmail 80449 invoked by alias); 9 Mar 2018 21:25:10 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 80438 invoked by uid 89); 9 Mar 2018 21:25:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-23.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=ascertain X-HELO: mx1.redhat.com Received: from mx3-rdu2.redhat.com (HELO mx1.redhat.com) (66.187.233.73) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 09 Mar 2018 21:25:08 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 90F1A406E8B3 for ; Fri, 9 Mar 2018 21:16:17 +0000 (UTC) Received: from localhost.localdomain (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id 423D32026DFD for ; Fri, 9 Mar 2018 21:16:17 +0000 (UTC) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 06/11] Fix setting breakpoints on ifunc functions after they're already resolved Date: Fri, 9 Mar 2018 21:16:07 +0000 Message-Id: <20180309211612.12941-7-palves@redhat.com> In-Reply-To: <20180309211612.12941-1-palves@redhat.com> References: <20180309211612.12941-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-resd.c:20 20 { vs, fixed: (gdb) break gnu_ifunc Breakpoint 4 at 0x40075a: file src/gdb/testsuite/gdb.base/gnu-ifunc-resd.c, line 21. (gdb) continue Continuing. Breakpoint 4, final (arg=2) at src/gdb/testsuite/gdb.base/gnu-ifunc-resd.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 * 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) : New fields. * linespec.c (minsym_found): Resolve GNU ifunc targets here. Record the minsym in the sal. * symtab.h (symtab_and_line) : New field. --- gdb/breakpoint.c | 31 +++++++++++++------------------ gdb/breakpoint.h | 8 ++++++++ gdb/linespec.c | 14 +++++++++++--- gdb/symtab.h | 1 + 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 454fda7684a..928411149e4 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -7180,37 +7180,30 @@ 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 + = MSYMBOL_VALUE_ADDRESS (loc->objfile, loc->msymbol); } } + else + find_pc_partial_function (loc->address, &function_name, NULL, NULL); if (function_name) loc->function_name = xstrdup (function_name); @@ -8674,6 +8667,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 8bb81d8d17e..0aeca3b7f95 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 1236b3f4754..1f1fb695c14 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -4334,10 +4334,17 @@ minsym_found (struct linespec_state *self, struct objfile *objfile, struct minimal_symbol *msymbol, std::vector *result) { - struct symtab_and_line sal; - + symtab_and_line sal; CORE_ADDR func_addr; - if (msymbol_is_function (objfile, msymbol, &func_addr)) + bool is_function; + + if (MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc) + is_function = gnu_ifunc_resolve_name (MSYMBOL_LINKAGE_NAME (msymbol), + &func_addr); + else + is_function = msymbol_is_function (objfile, msymbol, &func_addr); + + if (is_function) { sal = find_pc_sect_line (func_addr, NULL, 0); @@ -4360,6 +4367,7 @@ minsym_found (struct linespec_state *self, struct objfile *objfile, else { sal.objfile = objfile; + sal.msymbol = msymbol; sal.pc = MSYMBOL_VALUE_ADDRESS (objfile, msymbol); sal.pspace = current_program_space; } diff --git a/gdb/symtab.h b/gdb/symtab.h index 5dc52c58e0e..52ab1357300 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1761,6 +1761,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. */