2002-12-10 Andrew Cagney * frame.c (frame_type_from_pc): New function. (create_new_frame): Use frame_type_from_pc instead of custom code. (get_prev_frame): When neither DEPRECATED_INIT_FRAME_PC_P nor DEPRECATED_INIT_FRAME_PC_FIRST_P use frame_type_from_pc and frame_pc_unwind to set the frame's type at the point of frame creation. Index: frame.c =================================================================== RCS file: /cvs/src/src/gdb/frame.c,v retrieving revision 1.40 diff -u -r1.40 frame.c --- frame.c 11 Dec 2002 02:26:35 -0000 1.40 +++ frame.c 11 Dec 2002 02:33:57 -0000 @@ -767,6 +767,29 @@ } } +/* Determine the frame's type based on its PC. */ + +static enum frame_type +frame_type_from_pc (CORE_ADDR pc) +{ + /* FIXME: cagney/2002-11-24: Can't yet directly call + pc_in_dummy_frame() as some architectures don't set + PC_IN_CALL_DUMMY() to generic_pc_in_call_dummy() (remember the + latter is implemented by simply calling pc_in_dummy_frame). */ + if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES + && PC_IN_CALL_DUMMY (pc, 0, 0)) + return DUMMY_FRAME; + else + { + char *name; + find_pc_partial_function (pc, &name, NULL, NULL); + if (PC_IN_SIGTRAMP (pc, name)) + return SIGTRAMP_FRAME; + else + return NORMAL_FRAME; + } +} + /* Create an arbitrary (i.e. address specified by user) or innermost frame. Always returns a non-NULL value. */ @@ -785,30 +808,7 @@ fi->frame = addr; fi->pc = pc; - /* 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 - when it encounters a SIGTRAMP_FRAME or DUMMY_FRAME. This stops - get_prev_frame() overriding the frame's type when the INIT code - has previously set it. This is really somewhat bogus. The - initialization, as seen in create_new_frame(), should occur - before the INIT function has been called. */ - if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES - && (DEPRECATED_PC_IN_CALL_DUMMY_P () - ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0) - : pc_in_dummy_frame (pc))) - /* NOTE: cagney/2002-11-11: Does this even occure? */ - type = DUMMY_FRAME; - else - { - char *name; - find_pc_partial_function (pc, &name, NULL, NULL); - if (PC_IN_SIGTRAMP (fi->pc, name)) - type = SIGTRAMP_FRAME; - else - type = NORMAL_FRAME; - } - fi->type = type; + fi->type = frame_type_from_pc (pc); if (INIT_EXTRA_FRAME_INFO_P ()) INIT_EXTRA_FRAME_INFO (0, fi); @@ -867,6 +867,8 @@ CORE_ADDR address = 0; struct frame_info *prev; int fromleaf; + CORE_ADDR pc; + enum frame_type type; /* Return the inner-most frame, when the caller passes in NULL. */ /* NOTE: cagney/2002-11-09: Not sure how this would happen. The @@ -895,6 +897,41 @@ return next_frame->prev; next_frame->prev_p = 1; + /* Try to unwind the PC. If that doesn't work, assume we've reached + the oldest frame and simply return. Is there a better sentinal + value? The unwound PC value is then used to initialize the new + previous frame's type. + + Note that the pc-unwind is intentionally performed before the + frame chain. This is (well should be ok) since, for old targets, + both frame_pc_unwind (nee, FRAME_SAVED_PC) and FRAME_CHAIN()) + assume NEXT_FRAME's data structures have already been initialized + (using INIT_EXTRA_FRAME_INFO) and hence the call order doesn't + matter. + + By unwinding the PC first, it becomes possible to, in the case of + a dummy frame, avoid also unwinding the frame ID. This is + because (well ignoring the PPC) a dummy frame can be located + using NEXT_FRAME's frame ID. + + For the moment this is only done conditionally. Some targets + (e.g., rs6000) appear to break when this change is enabled. */ + if (DEPRECATED_INIT_FRAME_PC_P () + || DEPRECATED_INIT_FRAME_PC_FIRST_P ()) + { + /* Ulgh, old style target that still uses one of the + INIT_FRAME_PC methods. */ + pc = 0; + type = 0; + } + else + { + pc = frame_pc_unwind (next_frame); + if (pc == 0) + return NULL; + type = frame_type_from_pc (pc); + } + /* On some machines it is possible to call a function without setting up a stack frame for it. On these machines, we define this macro to take two args; a frameinfo pointer @@ -1080,12 +1117,15 @@ has previously set it. This is really somewhat bogus. The initialization, as seen in create_new_frame(), should occur before the INIT function has been called. */ - if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES + if ((DEPRECATED_INIT_FRAME_PC_P () + || DEPRECATED_INIT_FRAME_PC_FIRST_P ()) + && DEPRECATED_USE_GENERIC_DUMMY_FRAMES && (DEPRECATED_PC_IN_CALL_DUMMY_P () ? DEPRECATED_PC_IN_CALL_DUMMY (prev->pc, 0, 0) : pc_in_dummy_frame (prev->pc))) prev->type = DUMMY_FRAME; - else + else if (DEPRECATED_INIT_FRAME_PC_P () + || DEPRECATED_INIT_FRAME_PC_FIRST_P ()) { /* FIXME: cagney/2002-11-10: This should be moved to before the INIT code above so that the INIT code knows what the frame's