aboutsummaryrefslogtreecommitdiff
path: root/gdb/frame.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2023-10-24 07:59:51 -0600
committerTom Tromey <tromey@adacore.com>2023-11-14 08:43:34 -0700
commit19b83d5c9bac1db207dce26859c6ca84135615b0 (patch)
treecde40bf66217cda28eb1b5f2d7f2da55a6296ff1 /gdb/frame.c
parentba707cadae18a7cc8bb47a736d3d0438d44262a9 (diff)
downloadgdb-19b83d5c9bac1db207dce26859c6ca84135615b0.zip
gdb-19b83d5c9bac1db207dce26859c6ca84135615b0.tar.gz
gdb-19b83d5c9bac1db207dce26859c6ca84135615b0.tar.bz2
Move follow_static_link to frame.c
This moves the follow_static_link function to frame.c and exports it for use elsewhere. The API is changed slightly to make it more generically useful.
Diffstat (limited to 'gdb/frame.c')
-rw-r--r--gdb/frame.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/gdb/frame.c b/gdb/frame.c
index 7077016..4a46ccb 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -43,6 +43,7 @@
#include "hashtab.h"
#include "valprint.h"
#include "cli/cli-option.h"
+#include "dwarf2/loc.h"
/* The sentinel frame terminates the innermost end of the frame chain.
If unwound, it returns the information needed to construct an
@@ -3120,6 +3121,45 @@ get_frame_sp (frame_info_ptr this_frame)
return gdbarch_unwind_sp (gdbarch, frame_info_ptr (this_frame->next));
}
+/* See frame.h. */
+
+frame_info_ptr
+frame_follow_static_link (frame_info_ptr frame)
+{
+ const block *frame_block = get_frame_block (frame, nullptr);
+ frame_block = frame_block->function_block ();
+
+ const struct dynamic_prop *static_link = frame_block->static_link ();
+ if (static_link == nullptr)
+ return {};
+
+ CORE_ADDR upper_frame_base;
+
+ if (!dwarf2_evaluate_property (static_link, frame, NULL, &upper_frame_base))
+ return {};
+
+ /* Now climb up the stack frame until we reach the frame we are interested
+ in. */
+ for (; frame != nullptr; frame = get_prev_frame (frame))
+ {
+ struct symbol *framefunc = get_frame_function (frame);
+
+ /* Stacks can be quite deep: give the user a chance to stop this. */
+ QUIT;
+
+ /* If we don't know how to compute FRAME's base address, don't give up:
+ maybe the frame we are looking for is upper in the stack frame. */
+ if (framefunc != NULL
+ && SYMBOL_BLOCK_OPS (framefunc) != NULL
+ && SYMBOL_BLOCK_OPS (framefunc)->get_frame_base != NULL
+ && (SYMBOL_BLOCK_OPS (framefunc)->get_frame_base (framefunc, frame)
+ == upper_frame_base))
+ break;
+ }
+
+ return frame;
+}
+
/* Return the reason why we can't unwind past FRAME. */
enum unwind_stop_reason