diff --git a/gdb/frame-id.h b/gdb/frame-id.h index 5978d99bba8..8ddf7d11408 100644 --- a/gdb/frame-id.h +++ b/gdb/frame-id.h @@ -128,12 +128,16 @@ struct frame_id /* For convenience. All fields are zero. This means "there is no frame". */ extern const struct frame_id null_frame_id; -/* Sentinel frame. */ -extern const struct frame_id sentinel_frame_id; - /* This means "there is no frame ID, but there is a frame". It should be replaced by best-effort frame IDs for the outermost frame, somehow. The implementation is only special_addr_p set. */ extern const struct frame_id outer_frame_id; +/* Return true if ID represents a sentinel frame. */ +static inline bool +is_sentinel_frame_id (frame_id id) +{ + return id.stack_status == FID_STACK_SENTINEL; +} + #endif /* ifdef GDB_FRAME_ID_H */ diff --git a/gdb/frame.c b/gdb/frame.c index fed961b2a8d..9235a2ceb38 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -49,7 +49,10 @@ innermost frame. The current frame, which is the innermost frame, can be found at - sentinel_frame->prev. */ + sentinel_frame->prev. + + This is an optimization to be able to find the sentinel frame quickly, + it could otherwise be found in the frame cache. */ static frame_info *sentinel_frame; @@ -294,8 +297,8 @@ frame_stash_create (void) static bool frame_stash_add (frame_info *frame) { - /* Do not try to stash the sentinel frame. */ - gdb_assert (frame->level >= 0); + /* Valid frame levels are -1 (sentinel frames) and above. */ + gdb_assert (frame->level >= -1); frame_info **slot = (frame_info **) htab_find_slot (frame_stash, frame, INSERT); @@ -681,7 +684,6 @@ frame_unwind_caller_id (frame_info_ptr next_frame) } const struct frame_id null_frame_id = { 0 }; /* All zeros. */ -const struct frame_id sentinel_frame_id = { 0, 0, 0, FID_STACK_SENTINEL, 0, 1, 0 }; const struct frame_id outer_frame_id = { 0, 0, 0, FID_STACK_OUTER, 0, 1, 0 }; struct frame_id @@ -750,6 +752,29 @@ frame_id_build_wild (CORE_ADDR stack_addr) return id; } +/* See frame.h. */ + +frame_id +frame_id_build_sentinel (CORE_ADDR stack_addr, CORE_ADDR code_addr) +{ + frame_id id = null_frame_id; + + id.stack_status = FID_STACK_SENTINEL; + id.special_addr_p = 1; + + if (stack_addr != 0 || code_addr != 0) + { + /* The purpose of saving these in the sentinel frame ID is to be able to + differentiate the IDs of several sentinel frames that could exist + simultaneously in the frame cache. */ + id.stack_addr = stack_addr; + id.code_addr = code_addr; + id.code_addr_p = 1; + } + + return id; +} + bool frame_id_p (frame_id l) { @@ -896,7 +921,7 @@ frame_find_by_id (struct frame_id id) return NULL; /* Check for the sentinel frame. */ - if (id == sentinel_frame_id) + if (id == frame_id_build_sentinel (0, 0)) return frame_info_ptr (sentinel_frame); /* Try using the frame stash first. Finding it there removes the need @@ -1587,10 +1612,14 @@ put_frame_register_bytes (frame_info_ptr frame, int regnum, } } -/* Create a sentinel frame. */ +/* Create a sentinel frame. -static frame_info * -create_sentinel_frame (struct program_space *pspace, struct regcache *regcache) + See frame_id_build_sentinel for the description of STACK_ADDR and + CODE_ADDR. */ + +static frame_info_ptr +create_sentinel_frame (struct program_space *pspace, struct regcache *regcache, + CORE_ADDR stack_addr, CORE_ADDR code_addr) { frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info); @@ -1608,11 +1637,14 @@ create_sentinel_frame (struct program_space *pspace, struct regcache *regcache) frame->next = frame; /* The sentinel frame has a special ID. */ frame->this_id.p = frame_id_status::COMPUTED; - frame->this_id.value = sentinel_frame_id; + frame->this_id.value = frame_id_build_sentinel (stack_addr, code_addr); + + bool added = frame_stash_add (frame); + gdb_assert (added); frame_debug_printf (" -> %s", frame->to_string ().c_str ()); - return frame; + return frame_info_ptr (frame); } /* Cache for frame addresses already read by gdb. Valid only while @@ -1654,7 +1686,8 @@ get_current_frame (void) if (sentinel_frame == NULL) sentinel_frame = - create_sentinel_frame (current_program_space, get_current_regcache ()); + create_sentinel_frame (current_program_space, get_current_regcache (), + 0, 0).get (); /* Set the current frame before computing the frame id, to avoid recursion inside compute_frame_id, in case the frame's @@ -1980,7 +2013,8 @@ create_new_frame (frame_id id) frame_info *fi = FRAME_OBSTACK_ZALLOC (struct frame_info); fi->next = create_sentinel_frame (current_program_space, - get_current_regcache ()); + get_current_regcache (), + id.stack_addr, id.code_addr).get (); /* Set/update this frame's cached PC value, found in the next frame. Do this before looking for this frame's unwinder. A sniffer is @@ -2044,7 +2078,8 @@ get_next_frame_sentinel_okay (frame_info_ptr this_frame) is the sentinel frame. But we disallow it here anyway because calling get_next_frame_sentinel_okay() on the sentinel frame is likely a coding error. */ - gdb_assert (this_frame != sentinel_frame); + if (this_frame->this_id.p == frame_id_status::COMPUTED) + gdb_assert (!is_sentinel_frame_id (this_frame->this_id.value)); return frame_info_ptr (this_frame->next); } @@ -2064,7 +2099,7 @@ reinit_frame_cache (void) { ++frame_cache_generation; - if (sentinel_frame != NULL) + if (htab_elements (frame_stash) > 0) annotate_frames_invalid (); invalidate_selected_frame (); diff --git a/gdb/frame.h b/gdb/frame.h index c4f7c121391..4a99bd660df 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -159,6 +159,16 @@ extern struct frame_id as the special identifier address are set to indicate wild cards. */ extern struct frame_id frame_id_build_wild (CORE_ADDR stack_addr); +/* Construct a frame ID for a sentinel frame. + + If either STACK_ADDR or CODE_ADDR is not 0, the ID represents a sentinel + frame for a user-created frame. STACK_ADDR and CODE_ADDR are the addresses + used to create the frame. + + If STACK_ADDR and CODE_ADDR are both 0, the ID represents a regular sentinel + frame (i.e. the "next" frame of the target's current frame). */ +extern frame_id frame_id_build_sentinel (CORE_ADDR stack_addr, CORE_ADDR code_addr); + /* Returns true when L is a valid frame. */ extern bool frame_id_p (frame_id l); diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c index f323de3bb5d..3e5b9be2edf 100644 --- a/gdb/sentinel-frame.c +++ b/gdb/sentinel-frame.c @@ -50,8 +50,11 @@ sentinel_frame_prev_register (frame_info_ptr this_frame, = (struct frame_unwind_cache *) *this_prologue_cache; struct value *value; + frame_id this_frame_id = get_frame_id (this_frame); + gdb_assert (is_sentinel_frame_id (this_frame_id)); + value = cache->regcache->cooked_read_value (regnum); - VALUE_NEXT_FRAME_ID (value) = sentinel_frame_id; + VALUE_NEXT_FRAME_ID (value) = this_frame_id; return value; }