From patchwork Wed Aug 22 17:18:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 29021 Received: (qmail 32270 invoked by alias); 22 Aug 2018 17:18: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 32258 invoked by uid 89); 22 Aug 2018 17:18:09 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 22 Aug 2018 17:18:08 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0832EC05D3E6 for ; Wed, 22 Aug 2018 17:18:07 +0000 (UTC) Received: from pinnacle.lan (ovpn-116-27.phx2.redhat.com [10.3.116.27]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D62007A41D for ; Wed, 22 Aug 2018 17:18:06 +0000 (UTC) Date: Wed, 22 Aug 2018 10:18:05 -0700 From: Kevin Buettner To: gdb-patches@sourceware.org Subject: [PATCH v4 6/8] Introduce find_function_entry_range_from_pc and use it in infrun.c Message-ID: <20180822101805.19fc734e@pinnacle.lan> In-Reply-To: <20180822095721.3e298051@pinnacle.lan> References: <20180822095721.3e298051@pinnacle.lan> MIME-Version: 1.0 X-IsSubscribed: yes An earlier version of this patch used the returned block in conjunction with BLOCK_ENTRY_PC to set stop_func_start in fill_in_stop_func() in infrun.c. While I think this was the correct thing to do, changes to find_inferior_partial_function could potentially end up with stop_func_end < stop_func_start, which is definitely wrong. For this case, we want to set both stop_func_start and stop_func_end to the start and end of the range containing the function's entry pc. I think that this functionality will be useful in many other places too - it probably ought to be used in all of the various prologue analyzers in GDB. The change to infrun.c was simple: the call to find_pc_partial_function was replaced with a call to find_function_entry_range_from_pc. The difference between these two functions is that find_pc_partial_entry_function will (potentially) return the start and end address corresponding to the range in which PC is found, but find_function_entry_range_from_pc will (again, potentially) return the start and end address of the range containing the entry pc. find_pc_partial_function has the property that *ADDRESS <= PC < *ENDADDR. This condition does not necessarily hold for the outputs of find_function_entry_range_from_pc. It should be noted that for functions which contain only a single range, the outputs of find_pc_partial_function and find_function_entry_range_from_pc are identical. I think it might happen that find_function_entry_range_from_pc will come to be used in place of many of the calls to find_pc_partial_function within GDB. Care must be taken in making this change, however, since some of this code depends on the *ADDRESS <= PC < *ENDADDR property. Finally, a note regarding the name: I had initially chosen a different name with a find_pc_partial_ prefix, but Simon suggested the current name citing the goal of eventually making naming consistent using the form find_X_from_Y. In this case X is "function_entry_range" and Y is "pc". Both the name and rationale made sense to me, so that's how it came to be. gdb/ChangeLog: * infrun.c (fill_in_stop_func): Use find_function_entry_range_from_pc in place of find_pc_partial_function. * blockframe.c (find_function_entry_range_from_pc): New function. * symtab.h (find_function_entry_range_from_pc): Declare and document. --- gdb/blockframe.c | 37 +++++++++++++++++++++++++++++++++++++ gdb/infrun.c | 7 ++++--- gdb/symtab.h | 21 ++++++++++++++++++++- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 6ea0965..f6dd861 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -377,6 +377,43 @@ find_pc_partial_function (CORE_ADDR pc, const char **name, CORE_ADDR *address, /* See symtab.h. */ +bool +find_function_entry_range_from_pc (CORE_ADDR pc, const char **name, + CORE_ADDR *address, CORE_ADDR *endaddr) +{ + const struct block *block; + bool status = find_pc_partial_function (pc, name, address, endaddr, &block); + + if (status && block != nullptr && !BLOCK_CONTIGUOUS_P (block)) + { + CORE_ADDR entry_pc = BLOCK_ENTRY_PC (block); + + for (int i = 0; i < BLOCK_NRANGES (block); i++) + { + if (BLOCK_RANGE_START (block, i) <= entry_pc + && entry_pc < BLOCK_RANGE_END (block, i)) + { + if (address != nullptr) + *address = BLOCK_RANGE_START (block, i); + + if (endaddr != nullptr) + *endaddr = BLOCK_RANGE_END (block, i); + + return status; + } + } + + /* It's an internal error if we exit the above loop without finding + the range. */ + internal_error (__FILE__, __LINE__, + _("Entry block not found in find_function_entry_range_from_pc")); + } + + return status; +} + +/* See symtab.h. */ + struct type * find_function_type (CORE_ADDR pc) { diff --git a/gdb/infrun.c b/gdb/infrun.c index b25d745..7731ccd 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -4287,9 +4287,10 @@ fill_in_stop_func (struct gdbarch *gdbarch, { /* Don't care about return value; stop_func_start and stop_func_name will both be 0 if it doesn't work. */ - find_pc_partial_function (ecs->event_thread->suspend.stop_pc, - &ecs->stop_func_name, - &ecs->stop_func_start, &ecs->stop_func_end); + find_function_entry_range_from_pc (ecs->event_thread->suspend.stop_pc, + &ecs->stop_func_name, + &ecs->stop_func_start, + &ecs->stop_func_end); ecs->stop_func_start += gdbarch_deprecated_function_start_offset (gdbarch); diff --git a/gdb/symtab.h b/gdb/symtab.h index 746b5e6..eb14f34 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1725,12 +1725,31 @@ extern struct symbol *find_symbol_at_address (CORE_ADDR); This might suggest that *ADDRESS and *ENDADDR ought to be set to the limits of the entry pc range, but that will cause the *ADDRESS <= PC < *ENDADDR condition to be violated; many of the - callers of find_pc_partial_function expect this condition to hold. */ + callers of find_pc_partial_function expect this condition to hold. + + Callers which require the start and/or end addresses for the range + containing the entry pc should instead call + find_function_entry_range_from_pc. */ extern int find_pc_partial_function (CORE_ADDR pc, const char **name, CORE_ADDR *address, CORE_ADDR *endaddr, const struct block **block = nullptr); +/* Like find_pc_partial_function, above, but *ADDRESS and *ENDADDR are + set to start and end addresses of the range containing the entry pc. + + Note that it is not necessarily the case that (for non-NULL ADDRESS + and ENDADDR arguments) the *ADDRESS <= PC < *ENDADDR condition will + hold. + + See comment for find_pc_partial_function, above, for further + explanation. */ + +extern bool find_function_entry_range_from_pc (CORE_ADDR pc, + const char **name, + CORE_ADDR *address, + CORE_ADDR *endaddr); + /* Return the type of a function with its first instruction exactly at the PC address. Return NULL otherwise. */