diff options
author | Kevin Buettner <kevinb@redhat.com> | 2018-08-23 16:00:49 -0700 |
---|---|---|
committer | Kevin Buettner <kevinb@redhat.com> | 2018-08-23 16:19:43 -0700 |
commit | 59adbf5d03f5d9380f9870e22262c59f5f9beec8 (patch) | |
tree | 7461650eef0247a27b731a8d15cf7a3ebe50272b /gdb/blockframe.c | |
parent | 2b1ffcfd6fe5b88d50b6ad1c2ab3e9623ede5e35 (diff) | |
download | binutils-59adbf5d03f5d9380f9870e22262c59f5f9beec8.zip binutils-59adbf5d03f5d9380f9870e22262c59f5f9beec8.tar.gz binutils-59adbf5d03f5d9380f9870e22262c59f5f9beec8.tar.bz2 |
Introduce find_function_entry_range_from_pc and use it in infrun.c
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.
Diffstat (limited to 'gdb/blockframe.c')
-rw-r--r-- | gdb/blockframe.c | 37 |
1 files changed, 37 insertions, 0 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) { |