diff options
Diffstat (limited to 'gdb/frame.c')
-rw-r--r-- | gdb/frame.c | 546 |
1 files changed, 369 insertions, 177 deletions
diff --git a/gdb/frame.c b/gdb/frame.c index 8e42f589000..18c62f4618f 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -48,21 +48,75 @@ static int frame_debug; static int backtrace_below_main; -/* Utility to print a frame ID. */ static void fprint_frame_id (struct ui_file *file, struct frame_id id) { - fprintf_unfiltered (file, "stack=0x%s func=0x%s", - paddr (id.stack_addr), - paddr (id.func_addr)); + fprintf_unfiltered (file, "{stack=0x%s,code=0x%s}", + paddr_nz (id.stack_addr), + paddr_nz (id.code_addr)); +} + +static void +fprint_frame_type (struct ui_file *file, enum frame_type type) +{ + switch (type) + { + case UNKNOWN_FRAME: + fprintf_unfiltered (file, "UNKNOWN_FRAME"); + return; + case NORMAL_FRAME: + fprintf_unfiltered (file, "NORMAL_FRAME"); + return; + case DUMMY_FRAME: + fprintf_unfiltered (file, "DUMMY_FRAME"); + return; + case SIGTRAMP_FRAME: + fprintf_unfiltered (file, "SIGTRAMP_FRAME"); + return; + default: + fprintf_unfiltered (file, "<unknown type>"); + return; + }; } static void fprint_frame (struct ui_file *file, struct frame_info *fi) { - fprintf_unfiltered (gdb_stdlog, "frame %d @0x%s: ID ", - fi->level, paddr (get_frame_pc (fi))); - fprint_frame_id (gdb_stdlog, fi->id); + if (fi == NULL) + { + fprintf_unfiltered (file, "<NULL frame>"); + return; + } + fprintf_unfiltered (file, "{"); + fprintf_unfiltered (file, "level=%d", fi->level); + fprintf_unfiltered (file, ","); + fprintf_unfiltered (file, "type="); + fprint_frame_type (file, fi->type); + fprintf_unfiltered (file, ","); + fprintf_unfiltered (file, "unwind="); + if (fi->unwind != NULL) + gdb_print_host_address (fi->unwind, file); + else + fprintf_unfiltered (file, "<unknown>"); + fprintf_unfiltered (file, ","); + fprintf_unfiltered (file, "pc="); + if (fi->next != NULL && fi->next->prev_pc.p) + fprintf_unfiltered (file, "0x%s", paddr_nz (fi->next->prev_pc.value)); + else + fprintf_unfiltered (file, "<unknown>"); + fprintf_unfiltered (file, ","); + fprintf_unfiltered (file, "id="); + if (fi->this_id.p) + fprint_frame_id (file, fi->this_id.value); + else + fprintf_unfiltered (file, "<unknown>"); + fprintf_unfiltered (file, ","); + fprintf_unfiltered (file, "func="); + if (fi->next != NULL && fi->next->prev_func.p) + fprintf_unfiltered (file, "0x%s", paddr_nz (fi->next->prev_func.addr)); + else + fprintf_unfiltered (file, "<unknown>"); + fprintf_unfiltered (file, "}"); } /* Return a frame uniq ID that can be used to, later, re-find the @@ -75,29 +129,33 @@ get_frame_id (struct frame_info *fi) { return null_frame_id; } - if (!fi->id_p) + if (!fi->this_id.p) { gdb_assert (!legacy_frame_p (current_gdbarch)); + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, "{ get_frame_id (fi=%d) ", + fi->level); /* Find THIS frame's ID. */ - fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->id); - fi->id_p = 1; + fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->this_id.value); + fi->this_id.p = 1; if (frame_debug) { - fprint_frame (gdb_stdlog, fi); - fprintf_unfiltered (gdb_stdlog, "\n"); + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame_id (gdb_stdlog, fi->this_id.value); + fprintf_unfiltered (gdb_stdlog, " }\n"); } } - return fi->id; + return fi->this_id.value; } const struct frame_id null_frame_id; /* All zeros. */ struct frame_id -frame_id_build (CORE_ADDR stack_addr, CORE_ADDR func_addr) +frame_id_build (CORE_ADDR stack_addr, CORE_ADDR code_addr) { struct frame_id id; id.stack_addr = stack_addr; - id.func_addr = func_addr; + id.code_addr = code_addr; return id; } @@ -105,17 +163,13 @@ int frame_id_p (struct frame_id l) { int p; - /* The .func can be NULL but the .base cannot. */ + /* The .code can be NULL but the .stack cannot. */ p = (l.stack_addr != 0); if (frame_debug) { - fprintf_unfiltered (gdb_stdlog, "ID "); + fprintf_unfiltered (gdb_stdlog, "{ frame_id_p (l="); fprint_frame_id (gdb_stdlog, l); - if (p) - fprintf_unfiltered (gdb_stdlog, " .OK"); - else - fprintf_unfiltered (gdb_stdlog, " !OK"); - fprintf_unfiltered (gdb_stdlog, "\n"); + fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", p); } return p; } @@ -124,33 +178,29 @@ int frame_id_eq (struct frame_id l, struct frame_id r) { int eq; - /* Compare stacks. The stack addresses must always match and can - never be zero. */ if (l.stack_addr == 0 || r.stack_addr == 0) + /* Like a NaN, if either ID is invalid, the result is false. */ eq = 0; else if (l.stack_addr != r.stack_addr) + /* If .stack addresses are different, the frames are different. */ eq = 0; - /* Compare functions. A zero function address acts like a wild - card, otherwize a perfect match is expected. */ - else if (l.func_addr == 0 || r.func_addr == 0) + else if (l.code_addr == 0 || r.code_addr == 0) + /* A zero code addr is a wild card, always succeed. */ eq = 1; - else if (l.func_addr == r.func_addr) + else if (l.code_addr == r.code_addr) + /* The .stack and .code are identical, the ID's are identical. */ eq = 1; else /* No luck. */ eq = 0; if (frame_debug) { - fprintf_unfiltered (gdb_stdlog, "ID "); + fprintf_unfiltered (gdb_stdlog, "{ frame_id_eq (l="); fprint_frame_id (gdb_stdlog, l); - if (eq) - fprintf_unfiltered (gdb_stdlog, " .EQ "); - else - fprintf_unfiltered (gdb_stdlog, " !EQ "); - fprintf_unfiltered (gdb_stdlog, "ID "); - fprint_frame_id (gdb_stdlog, r) ; - fprintf_unfiltered (gdb_stdlog, "\n"); - } + fprintf_unfiltered (gdb_stdlog, ",r="); + fprint_frame_id (gdb_stdlog, r); + fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", eq); + } return eq; } @@ -158,20 +208,22 @@ int frame_id_inner (struct frame_id l, struct frame_id r) { int inner; - /* Only return non-zero when strictly inner than. Note that, per - comment in "frame.h", there is some fuzz here. Frameless - functions are not strictly inner than (same .base but different - .func). */ - inner = gdbarch_inner_than (current_gdbarch, l.stack_addr, r.stack_addr); + if (l.stack_addr == 0 || r.stack_addr == 0) + /* Like NaN, any operation involving an invalid ID always fails. */ + inner = 0; + else + /* Only return non-zero when strictly inner than. Note that, per + comment in "frame.h", there is some fuzz here. Frameless + functions are not strictly inner than (same .stack but + different .code). */ + inner = INNER_THAN (l.stack_addr, r.stack_addr); if (frame_debug) { + fprintf_unfiltered (gdb_stdlog, "{ frame_id_inner (l="); fprint_frame_id (gdb_stdlog, l); - if (inner) - fprintf_unfiltered (gdb_stdlog, " .INNER "); - else - fprintf_unfiltered (gdb_stdlog, " !INNER "); + fprintf_unfiltered (gdb_stdlog, ",r="); fprint_frame_id (gdb_stdlog, r); - fprintf_unfiltered (gdb_stdlog, "\n"); + fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", inner); } return inner; } @@ -208,7 +260,7 @@ frame_find_by_id (struct frame_id id) CORE_ADDR frame_pc_unwind (struct frame_info *this_frame) { - if (!this_frame->pc_unwind_cache_p) + if (!this_frame->prev_pc.p) { CORE_ADDR pc; if (gdbarch_unwind_pc_p (current_gdbarch)) @@ -250,30 +302,38 @@ frame_pc_unwind (struct frame_info *this_frame) } else internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method"); - this_frame->pc_unwind_cache = pc; - this_frame->pc_unwind_cache_p = 1; + this_frame->prev_pc.value = pc; + this_frame->prev_pc.p = 1; + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_pc_unwind (this_frame=%d) -> 0x%s }\n", + this_frame->level, + paddr_nz (this_frame->prev_pc.value)); } - return this_frame->pc_unwind_cache; + return this_frame->prev_pc.value; } CORE_ADDR -frame_func_unwind (struct frame_info *this_frame) +frame_func_unwind (struct frame_info *fi) { - if (!this_frame->func.p) + if (!fi->prev_func.p) { - CORE_ADDR pc = frame_pc_unwind (this_frame); - this_frame->func.cache = get_pc_function_start (pc); + fi->prev_func.p = 1; + fi->prev_func.addr = get_pc_function_start (frame_pc_unwind (fi)); + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_func_unwind (fi=%d) -> 0x%s }\n", + fi->level, paddr_nz (fi->prev_func.addr)); } - return this_frame->func.cache; + return fi->prev_func.addr; } CORE_ADDR -get_frame_func (struct frame_info *this_frame) +get_frame_func (struct frame_info *fi) { - return frame_func_unwind (this_frame->next); + return frame_func_unwind (fi->next); } - static int do_frame_unwind_register (void *src, int regnum, void *buf) { @@ -329,6 +389,13 @@ frame_register_unwind (struct frame_info *frame, int regnum, { struct frame_unwind_cache *cache; + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, + "{ frame_register_unwind (frame=%d,regnum=\"%s\",...) ", + frame->level, frame_map_regnum_to_name (regnum)); + } + /* Require all but BUFFERP to be valid. A NULL BUFFERP indicates that the value proper does not need to be fetched. */ gdb_assert (optimizedp != NULL); @@ -349,6 +416,26 @@ frame_register_unwind (struct frame_info *frame, int regnum, frame->unwind->prev_register (frame->next, &frame->prologue_cache, regnum, optimizedp, lvalp, addrp, realnump, bufferp); + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "->"); + fprintf_unfiltered (gdb_stdlog, " *optimizedp=%d", (*optimizedp)); + fprintf_unfiltered (gdb_stdlog, " *lvalp=%d", (int) (*lvalp)); + fprintf_unfiltered (gdb_stdlog, " *addrp=0x%s", paddr_nz ((*addrp))); + fprintf_unfiltered (gdb_stdlog, " *bufferp="); + if (bufferp == NULL) + fprintf_unfiltered (gdb_stdlog, "<NULL>"); + else + { + int i; + const char *buf = bufferp; + fprintf_unfiltered (gdb_stdlog, "["); + for (i = 0; i < register_size (current_gdbarch, regnum); i++) + fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]); + fprintf_unfiltered (gdb_stdlog, "]"); + } + fprintf_unfiltered (gdb_stdlog, " }\n"); + } } void @@ -585,15 +672,19 @@ create_sentinel_frame (struct regcache *regcache) frame->prologue_cache = sentinel_frame_cache (regcache); /* For the moment there is only one sentinel frame implementation. */ frame->unwind = sentinel_frame_unwind; - /* Give it a really large frame ID. */ - frame->id_p = 1; - if (INNER_THAN (1, 2)) - frame->id = frame_id_build (0, 0); - else - frame->id = frame_id_build (-1, 0); /* Link this frame back to itself. The frame is self referential (the unwound PC is the same as the pc), so make it so. */ frame->next = frame; + /* Make the sentinel frame's ID valid, but invalid. That way all + comparisons with it should fail. */ + frame->this_id.p = 1; + frame->this_id.value = null_frame_id; + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "{ create_sentinel_frame (...) -> "); + fprint_frame (gdb_stdlog, frame); + fprintf_unfiltered (gdb_stdlog, " }\n"); + } return frame; } @@ -667,10 +758,6 @@ get_current_frame (void) if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame, NULL, RETURN_MASK_ERROR) != 0) { - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "Oops!\n"); - } /* Oops! Fake a current frame? Is this useful? It has a PC of zero, for instance. */ current_frame = sentinel_frame; @@ -842,7 +929,7 @@ legacy_saved_regs_this_id (struct frame_info *next_frame, unwinding a sentinel frame, the PC of which is pointing at a stack dummy. Fake up the dummy frame's ID using the same sequence as is found a traditional unwinder. */ - (*id) = frame_id_build (read_fp (), 0 /*read_pc ()*/); + (*id) = frame_id_build (read_fp (), 0); return; } @@ -886,7 +973,7 @@ legacy_saved_regs_this_id (struct frame_info *next_frame, gdb_assert (DEPRECATED_FRAME_CHAIN_P ()); base = DEPRECATED_FRAME_CHAIN (next_frame); - if (!frame_chain_valid (base, next_frame)) + if (!legacy_frame_chain_valid (base, next_frame)) return; } if (base == 0) @@ -899,6 +986,8 @@ legacy_saved_regs_this_id (struct frame_info *next_frame, } const struct frame_unwind legacy_saved_regs_unwinder = { + /* Not really. It gets overridden by legacy_get_prev_frame. */ + UNKNOWN_FRAME, legacy_saved_regs_this_id, legacy_saved_regs_prev_register }; @@ -1037,27 +1126,42 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) { struct frame_info *fi; + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, + "{ create_new_frame (addr=0x%s, pc=0x%s) ", + paddr_nz (addr), paddr_nz (pc)); + } + fi = frame_obstack_zalloc (sizeof (struct frame_info)); /* FIXME: cagney/2003-04-02: Should this instead try to map that pc onto a function. */ - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, "create new frame\n"); - - fi->id = frame_id_build (addr, pc); - fi->id_p = 1; + fi->this_id.p = 1; + fi->this_id.value = frame_id_build (addr, pc); fi->next = create_sentinel_frame (current_regcache); - fi->next->pc_unwind_cache = pc; - fi->next->pc_unwind_cache_p = 1; - fi->type = frame_type_from_pc (pc); + /* Select/initialize both the unwind function and the frame's type + based on the PC. */ + fi->unwind = frame_unwind_find_by_pc (current_gdbarch, pc); + if (fi->unwind->type != UNKNOWN_FRAME) + fi->type = fi->unwind->type; + else + fi->type = frame_type_from_pc (pc); + + deprecated_update_frame_base_hack (fi, addr); + deprecated_update_frame_pc_hack (fi, pc); if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()) DEPRECATED_INIT_EXTRA_FRAME_INFO (0, fi); - /* Select/initialize an unwind function. */ - fi->unwind = frame_unwind_find_by_pc (current_gdbarch, get_frame_pc (fi)); + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, fi); + fprintf_unfiltered (gdb_stdlog, " }\n"); + } return fi; } @@ -1087,6 +1191,8 @@ flush_cached_frames (void) current_frame = NULL; /* Invalidate cache */ select_frame (NULL); annotate_frames_invalid (); + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, "{ flush_cached_frames () }\n"); } /* Flush the frame cache, and start a new one if necessary. */ @@ -1113,10 +1219,10 @@ legacy_get_prev_frame (struct frame_info *this_frame) struct frame_info *prev; int fromleaf; - /* Allocate the new frame but do not wire it in to the frame chain. - Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along - frame->next to pull some fancy tricks (of course such code is, by - definition, recursive). Try to prevent it. + /* Don't frame_debug print legacy_get_prev_frame() here, just + confuses the output. */ + + /* Allocate the new frame. There is no reason to worry about memory leaks, should the remainder of the function fail. The allocated memory will be @@ -1126,11 +1232,15 @@ legacy_get_prev_frame (struct frame_info *this_frame) prev = FRAME_OBSTACK_ZALLOC (struct frame_info); prev->level = this_frame->level + 1; - /* Link prev to this. This ensures that functions such as - get_frame_pc(), called by all the deprecated init functions - below, and implemented using frame_pc_unwind (prev->next) work. - Don't link this to prev as this stops functions walking up the - frame chain to this partially initialized method. */ + /* Do not completly wire it in to the frame chain. Some (bad) code + in INIT_FRAME_EXTRA_INFO tries to look along frame->prev to pull + some fancy tricks (of course such code is, by definition, + recursive). + + On the other hand, methods, such as get_frame_pc() and + get_frame_base() rely on being able to walk along the frame + chain. Make certain that at least they work by providing that + link. Of course things manipulating prev can't go back. */ prev->next = this_frame; /* NOTE: cagney/2002-11-18: Should have been correctly setting the @@ -1143,10 +1253,10 @@ legacy_get_prev_frame (struct frame_info *this_frame) Unfortunatly those same work-arounds rely on the type defaulting to NORMAL_FRAME. Ulgh! The new frame code does not have this problem. */ - prev->type = NORMAL_FRAME; + prev->type = UNKNOWN_FRAME; /* A legacy frame's ID is always computed here. Mark it as valid. */ - prev->id_p = 1; + prev->this_id.p = 1; /* Handle sentinel frame unwind as a special case. */ if (this_frame->level < 0) @@ -1169,20 +1279,29 @@ legacy_get_prev_frame (struct frame_info *this_frame) because (well ignoring the PPC) a dummy frame can be located using THIS_FRAME's frame ID. */ - if (frame_pc_unwind (this_frame) == 0) + deprecated_update_frame_pc_hack (prev, frame_pc_unwind (this_frame)); + if (get_frame_pc (prev) == 0) { /* The allocated PREV_FRAME will be reclaimed when the frame obstack is next purged. */ if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "Outermost frame - unwound PC zero\n"); + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, + " // unwound legacy PC zero }\n"); + } return NULL; } - prev->type = frame_type_from_pc (frame_pc_unwind (this_frame)); - /* Set the unwind functions based on that identified PC. */ + /* Set the unwind functions based on that identified PC. Ditto + for the "type" but strongly prefer the unwinder's frame type. */ prev->unwind = frame_unwind_find_by_pc (current_gdbarch, - frame_pc_unwind (this_frame)); + get_frame_pc (prev)); + if (prev->unwind->type == UNKNOWN_FRAME) + prev->type = frame_type_from_pc (get_frame_pc (prev)); + else + prev->type = prev->unwind->type; /* Find the prev's frame's ID. */ if (prev->type == DUMMY_FRAME @@ -1204,7 +1323,8 @@ legacy_get_prev_frame (struct frame_info *this_frame) dummy ID from the next frame. Note that this method uses frame_register_unwind to obtain the register values needed to determine the dummy frame's ID. */ - prev->id = gdbarch_unwind_dummy_id (current_gdbarch, this_frame); + prev->this_id.value = gdbarch_unwind_dummy_id (current_gdbarch, + this_frame); } else { @@ -1213,15 +1333,19 @@ legacy_get_prev_frame (struct frame_info *this_frame) using the same sequence as is found a traditional unwinder. Once all architectures supply the unwind_dummy_id method, this code can go away. */ - prev->id = frame_id_build (read_fp (), read_pc ()); + prev->this_id.value = frame_id_build (read_fp (), read_pc ()); } /* Check that the unwound ID is valid. */ - if (!frame_id_p (prev->id)) + if (!frame_id_p (prev->this_id.value)) { if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "Outermost legacy sentinel frame - unwound frame ID invalid\n"); + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, + " // unwound legacy ID invalid }\n"); + } return NULL; } @@ -1251,14 +1375,15 @@ legacy_get_prev_frame (struct frame_info *this_frame) } if (prev->type == NORMAL_FRAME) - prev->id.func_addr = get_pc_function_start (prev->id.func_addr); + prev->this_id.value.code_addr + = get_pc_function_start (prev->this_id.value.code_addr); if (frame_debug) { + fprintf_unfiltered (gdb_stdlog, "-> "); fprint_frame (gdb_stdlog, prev); - fprintf_unfiltered (gdb_stdlog, "\n"); + fprintf_unfiltered (gdb_stdlog, " } // legacy innermost frame\n"); } - return prev; } @@ -1312,15 +1437,32 @@ legacy_get_prev_frame (struct frame_info *this_frame) gdb_assert (DEPRECATED_FRAME_CHAIN_P ()); address = DEPRECATED_FRAME_CHAIN (this_frame); - if (!frame_chain_valid (address, this_frame)) - return 0; + if (!legacy_frame_chain_valid (address, this_frame)) + { + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, + " // legacy frame chain invalid }\n"); + } + return NULL; + } } if (address == 0) - return 0; + { + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, + " // legacy frame chain NULL }\n"); + } + return NULL; + } /* Link in the already allocated prev frame. */ this_frame->prev = prev; - prev->next = this_frame; deprecated_update_frame_base_hack (prev, address); /* This change should not be needed, FIXME! We should determine @@ -1397,8 +1539,9 @@ legacy_get_prev_frame (struct frame_info *this_frame) that PC value. */ if (DEPRECATED_INIT_FRAME_PC_FIRST_P ()) - deprecated_update_frame_pc_hack - (prev, DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, prev)); + deprecated_update_frame_pc_hack (prev, + DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, + prev)); if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()) DEPRECATED_INIT_EXTRA_FRAME_INFO (fromleaf, prev); @@ -1407,21 +1550,27 @@ legacy_get_prev_frame (struct frame_info *this_frame) FRAME_SAVED_PC may use that queue to figure out its value (see tm-sparc.h). We want the pc saved in the inferior frame. */ if (DEPRECATED_INIT_FRAME_PC_P ()) - deprecated_update_frame_pc_hack - (prev, DEPRECATED_INIT_FRAME_PC (fromleaf, prev)); + deprecated_update_frame_pc_hack (prev, + DEPRECATED_INIT_FRAME_PC (fromleaf, + prev)); /* If ->frame and ->pc are unchanged, we are in the process of getting ourselves into an infinite backtrace. Some architectures check this in DEPRECATED_FRAME_CHAIN or thereabouts, but it seems like there is no reason this can't be an architecture-independent check. */ - /* NOTE: cagney/2003-04-04: Don't convert this to frame_id_eq. At - this stage the ID's address is not valid, so need to use the pc. */ - if (prev->id.stack_addr == this_frame->id.stack_addr + if (get_frame_base (prev) == get_frame_base (this_frame) && get_frame_pc (prev) == get_frame_pc (this_frame)) { this_frame->prev = NULL; obstack_free (&frame_cache_obstack, prev); + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, + " // legacy this.id == prev.id }\n"); + } return NULL; } @@ -1432,6 +1581,23 @@ legacy_get_prev_frame (struct frame_info *this_frame) prev->unwind = frame_unwind_find_by_pc (current_gdbarch, get_frame_pc (prev)); + /* If the unwinder provides a frame type, use it. Otherwize + continue on to that heuristic mess. */ + if (prev->unwind->type != UNKNOWN_FRAME) + { + prev->type = prev->unwind->type; + if (prev->type == NORMAL_FRAME) + prev->this_id.value.code_addr + = get_pc_function_start (prev->this_id.value.code_addr); + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, prev); + fprintf_unfiltered (gdb_stdlog, " } // legacy with unwound type\n"); + } + return prev; + } + /* NOTE: cagney/2002-11-18: The code segments, found in create_new_frame and get_prev_frame(), that initializes the frames type is subtly different. The latter only updates ->type @@ -1454,8 +1620,7 @@ legacy_get_prev_frame (struct frame_info *this_frame) Unforunatly, its the INIT code that sets the PC (Hmm, catch 22). */ char *name; - find_pc_partial_function (get_frame_pc (prev), - &name, NULL, NULL); + find_pc_partial_function (get_frame_pc (prev), &name, NULL, NULL); if (PC_IN_SIGTRAMP (get_frame_pc (prev), name)) prev->type = SIGTRAMP_FRAME; /* FIXME: cagney/2002-11-11: Leave prev->type alone. Some @@ -1466,17 +1631,17 @@ legacy_get_prev_frame (struct frame_info *this_frame) go away. */ } + if (prev->type == NORMAL_FRAME) + prev->this_id.value.code_addr + = get_pc_function_start (prev->this_id.value.code_addr); + if (frame_debug) { - fprintf_unfiltered (gdb_stdlog, "frame %d @0x%s: ID ", - prev->level, paddr (get_frame_pc (prev))); - fprint_frame_id (gdb_stdlog, prev->id); - fprintf_unfiltered (gdb_stdlog, "\n"); + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, prev); + fprintf_unfiltered (gdb_stdlog, " } // legacy with confused type\n"); } - if (prev->type == NORMAL_FRAME) - prev->id.func_addr = get_pc_function_start (prev->id.func_addr); - return prev; } @@ -1489,6 +1654,16 @@ get_prev_frame (struct frame_info *this_frame) { struct frame_info *prev_frame; + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame (this_frame="); + if (this_frame != NULL) + fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level); + else + fprintf_unfiltered (gdb_stdlog, "<NULL>"); + fprintf_unfiltered (gdb_stdlog, ") "); + } + /* Return the inner-most frame, when the caller passes in NULL. */ /* NOTE: cagney/2002-11-09: Not sure how this would happen. The caller should have previously obtained a valid frame using @@ -1538,14 +1713,21 @@ get_prev_frame (struct frame_info *this_frame) allow unwinds past main(), that just happens. */ { if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "Outermost frame - inside main func.\n"); + fprintf_unfiltered (gdb_stdlog, "-> NULL // inside main func }\n"); return NULL; } /* Only try to do the unwind once. */ if (this_frame->prev_p) - return this_frame->prev; + { + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, this_frame->prev); + fprintf_unfiltered (gdb_stdlog, " // cached \n"); + } + return this_frame->prev; + } this_frame->prev_p = 1; #if 0 @@ -1573,8 +1755,11 @@ get_prev_frame (struct frame_info *this_frame) && inside_entry_file (get_frame_pc (this_frame))) { if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "Outermost frame - inside entry file\n"); + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, " // inside entry file }\n"); + } return NULL; } #endif @@ -1591,8 +1776,11 @@ get_prev_frame (struct frame_info *this_frame) && inside_entry_func (get_frame_pc (this_frame))) { if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "Outermost frame - inside entry func\n"); + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, "// inside entry func }\n"); + } return NULL; } @@ -1601,9 +1789,6 @@ get_prev_frame (struct frame_info *this_frame) if (legacy_frame_p (current_gdbarch)) { prev_frame = legacy_get_prev_frame (this_frame); - if (frame_debug && prev_frame == NULL) - fprintf_unfiltered (gdb_stdlog, - "Outermost frame - legacy_get_prev_frame NULL.\n"); return prev_frame; } @@ -1613,8 +1798,11 @@ get_prev_frame (struct frame_info *this_frame) if (this_frame->level >= 0 && !frame_id_p (get_frame_id (this_frame))) { if (frame_debug) - fprintf_filtered (gdb_stdlog, - "Outermost frame - this ID is NULL\n"); + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, " // this ID is NULL }\n"); + } return NULL; } @@ -1675,16 +1863,29 @@ get_prev_frame (struct frame_info *this_frame) /* The allocated PREV_FRAME will be reclaimed when the frame obstack is next purged. */ if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "Outermost frame - unwound PC zero\n"); + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, " // unwound PC zero }\n"); + } return NULL; } - prev_frame->type = frame_type_from_pc (frame_pc_unwind (this_frame)); /* Set the unwind functions based on that identified PC. */ prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch, frame_pc_unwind (this_frame)); + /* FIXME: cagney/2003-04-02: Rather than storing the frame's type in + the frame, the unwinder's type should be returned directly. + Unfortunatly, legacy code, called by legacy_get_prev_frame, + explicitly set the frames type using the method + deprecated_set_frame_type(). */ + gdb_assert (prev_frame->unwind->type != UNKNOWN_FRAME); + prev_frame->type = prev_frame->unwind->type; + + /* Can the frame's type and unwinder be computed on demand? That + would make a frame's creation really really lite! */ + /* The prev's frame's ID is computed by demand in get_frame_id(). */ /* The unwound frame ID is validate at the start of this function, @@ -1703,12 +1904,20 @@ get_prev_frame (struct frame_info *this_frame) this_frame->prev = prev_frame; prev_frame->next = this_frame; + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, prev_frame); + fprintf_unfiltered (gdb_stdlog, " }\n"); + } + return prev_frame; } CORE_ADDR get_frame_pc (struct frame_info *frame) { + gdb_assert (frame->next != NULL); return frame_pc_unwind (frame->next); } @@ -1748,7 +1957,7 @@ get_frame_base (struct frame_info *fi) CORE_ADDR get_frame_base_address (struct frame_info *fi) { - if (fi->type != NORMAL_FRAME) + if (get_frame_type (fi) != NORMAL_FRAME) return 0; if (fi->base == NULL) fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi)); @@ -1763,7 +1972,7 @@ CORE_ADDR get_frame_locals_address (struct frame_info *fi) { void **cache; - if (fi->type != NORMAL_FRAME) + if (get_frame_type (fi) != NORMAL_FRAME) return 0; /* If there isn't a frame address method, find it. */ if (fi->base == NULL) @@ -1781,7 +1990,7 @@ CORE_ADDR get_frame_args_address (struct frame_info *fi) { void **cache; - if (fi->type != NORMAL_FRAME) + if (get_frame_type (fi) != NORMAL_FRAME) return 0; /* If there isn't a frame address method, find it. */ if (fi->base == NULL) @@ -1815,7 +2024,10 @@ get_frame_type (struct frame_info *frame) if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES && deprecated_frame_in_dummy (frame)) return DUMMY_FRAME; - return frame->type; + if (frame->type == UNKNOWN_FRAME) + return NORMAL_FRAME; + else + return frame->type; } void @@ -1825,34 +2037,6 @@ deprecated_set_frame_type (struct frame_info *frame, enum frame_type type) frame->type = type; } -#ifdef FRAME_FIND_SAVED_REGS -/* XXX - deprecated. This is a compatibility function for targets - that do not yet implement DEPRECATED_FRAME_INIT_SAVED_REGS. */ -/* Find the addresses in which registers are saved in FRAME. */ - -void -deprecated_get_frame_saved_regs (struct frame_info *frame, - struct frame_saved_regs *saved_regs_addr) -{ - if (frame->saved_regs == NULL) - { - frame->saved_regs = (CORE_ADDR *) - frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS); - } - if (saved_regs_addr == NULL) - { - struct frame_saved_regs saved_regs; - FRAME_FIND_SAVED_REGS (frame, saved_regs); - memcpy (frame->saved_regs, &saved_regs, SIZEOF_FRAME_SAVED_REGS); - } - else - { - FRAME_FIND_SAVED_REGS (frame, *saved_regs_addr); - memcpy (frame->saved_regs, saved_regs_addr, SIZEOF_FRAME_SAVED_REGS); - } -} -#endif - struct frame_extra_info * get_frame_extra_info (struct frame_info *fi) { @@ -1869,6 +2053,10 @@ frame_extra_info_zalloc (struct frame_info *fi, long size) void deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc) { + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ deprecated_update_frame_pc_hack (frame=%d,pc=0x%s) }\n", + frame->level, paddr_nz (pc)); /* NOTE: cagney/2003-03-11: Some architectures (e.g., Arm) are maintaining a locally allocated frame object. Since such frame's are not in the frame chain, it isn't possible to assume that the @@ -1878,16 +2066,20 @@ deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc) /* While we're at it, update this frame's cached PC value, found in the next frame. Oh for the day when "struct frame_info" is opaque and this hack on hack can just go away. */ - frame->next->pc_unwind_cache = pc; - frame->next->pc_unwind_cache_p = 1; + frame->next->prev_pc.value = pc; + frame->next->prev_pc.p = 1; } } void deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base) { - frame->id_p = 1; - frame->id.stack_addr = base; + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ deprecated_update_frame_base_hack (frame=%d,base=0x%s) }\n", + frame->level, paddr_nz (base)); + /* See comment in "frame.h". */ + frame->this_id.value.stack_addr = base; } void |