diff options
-rw-r--r-- | gdb/blockframe.c | 37 | ||||
-rw-r--r-- | gdb/infrun.c | 7 | ||||
-rw-r--r-- | 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. */ |