diff options
author | Andrew Cagney <cagney@redhat.com> | 2003-03-05 05:00:04 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2003-03-05 05:00:04 +0000 |
commit | fdd93b8b10a297196af99279086ddc214f3d9bb6 (patch) | |
tree | 3fc2944b974ec1b30ea675176c158f67b0a8821e | |
parent | fc34faedba1aacec97bca094627e9c322049e68d (diff) | |
download | fsf-binutils-gdb-fdd93b8b10a297196af99279086ddc214f3d9bb6.zip fsf-binutils-gdb-fdd93b8b10a297196af99279086ddc214f3d9bb6.tar.gz fsf-binutils-gdb-fdd93b8b10a297196af99279086ddc214f3d9bb6.tar.bz2 |
2003-03-04 Andrew Cagney <cagney@redhat.com>
* d10v-tdep.c (struct d10v_unwind_cache): Add field "r11_addr",
change type of "next_addr" to LONGEST. Delete member "frameless".
(prologue_find_regs): Parse "st rn, @r11", save r11's offset.
(d10v_frame_unwind_cache): Compute both the frame base and the
previous stack pointer. Store the previous SP's value in the
saved_regs array.
(d10v_frame_id_unwind): Remove commented out code. Check for
circular stack.
(saved_regs_unwinder): When SP_REGNUM, extract the value from the
saved_regs array.
(d10v_unwind_dummy_id): New function.
(d10v_gdbarch_init): Initialize d10v_unwind_dummy_id and
save_dummy_frame_tos.
(struct frame_extra_info): Delete.
(saved_regs_unwind): New function.
(d10v_frame_pop): Update to match current code.
(d10v_frame_register_unwind): Don't unwind LR_REGNUM. Unwind the
PC_REGNUM by returning the saved LR_REGNUM.
* frame.c (get_prev_frame): Store this frame's ID in the next
frame's unwound ID cache.
(deprecated_update_frame_pc_hack): Update the cached value in NEXT
as well.
2003-02-27 Andrew Cagney <cagney@redhat.com>
* frame.c (get_prev_frame): Rewrite the frame ID unwind code to
use unwind_dummy_id when available.
* gdbarch.sh (get_dummy_frame_id): New multi-arch method with
predicate.
* gdbarch.h, gdbarch.c: Regneerate.
-rw-r--r-- | gdb/ChangeLog | 32 | ||||
-rw-r--r-- | gdb/d10v-tdep.c | 222 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/doc/gdbint.texinfo | 17 | ||||
-rw-r--r-- | gdb/frame.c | 109 | ||||
-rw-r--r-- | gdb/gdbarch.c | 37 | ||||
-rw-r--r-- | gdb/gdbarch.h | 6 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 1 |
8 files changed, 314 insertions, 117 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 32b7990..8ac3ae9 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,37 @@ 2003-03-04 Andrew Cagney <cagney@redhat.com> + * d10v-tdep.c (struct d10v_unwind_cache): Add field "r11_addr", + change type of "next_addr" to LONGEST. Delete member "frameless". + (prologue_find_regs): Parse "st rn, @r11", save r11's offset. + (d10v_frame_unwind_cache): Compute both the frame base and the + previous stack pointer. Store the previous SP's value in the + saved_regs array. + (d10v_frame_id_unwind): Remove commented out code. Check for + circular stack. + (saved_regs_unwinder): When SP_REGNUM, extract the value from the + saved_regs array. + (d10v_unwind_dummy_id): New function. + (d10v_gdbarch_init): Initialize d10v_unwind_dummy_id and + save_dummy_frame_tos. + (struct frame_extra_info): Delete. + (saved_regs_unwind): New function. + (d10v_frame_pop): Update to match current code. + (d10v_frame_register_unwind): Don't unwind LR_REGNUM. Unwind the + PC_REGNUM by returning the saved LR_REGNUM. + * frame.c (get_prev_frame): Store this frame's ID in the next + frame's unwound ID cache. + (deprecated_update_frame_pc_hack): Update the cached value in NEXT + as well. + + 2003-02-27 Andrew Cagney <cagney@redhat.com> + * frame.c (get_prev_frame): Rewrite the frame ID unwind code to + use unwind_dummy_id when available. + * gdbarch.sh (get_dummy_frame_id): New multi-arch method with + predicate. + * gdbarch.h, gdbarch.c: Regneerate. + +2003-03-04 Andrew Cagney <cagney@redhat.com> + * d10v-tdep.c (d10v_frame_unwind_cache): Update to work with NEXT_FRAME and THIS_CACHE. (d10v_frame_pc_unwind): Ditto. diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index 9111aa3..5cbdddc 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -45,20 +45,9 @@ #include "gdb_assert.h" -static void d10v_frame_register_unwind (struct frame_info *next_frame, - void **this_cache, - int prev_regnum, int *optimizedp, - enum lval_type *lvalp, - CORE_ADDR *addrp, - int *realnump, void *bufferp); - - -struct frame_extra_info - { - CORE_ADDR return_pc; - int frameless; - int size; - }; +static void saved_regs_unwind (struct frame_info *next_frame, + CORE_ADDR *saved_regs, int prev_regnum, + void *bufferp); struct gdbarch_tdep { @@ -625,10 +614,10 @@ d10v_skip_prologue (CORE_ADDR pc) struct d10v_unwind_cache { CORE_ADDR base; - int frameless; int size; CORE_ADDR *saved_regs; - CORE_ADDR next_addr; + LONGEST next_addr; + LONGEST r11_addr; int uses_frame; void **regs; }; @@ -672,6 +661,15 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, if (op == 0x417E) { info->uses_frame = 1; + info->r11_addr = info->next_addr; + return 1; + } + + /* st rn, @r11 */ + if ((op & 0x7E1F) == 0x6816) + { + n = (op & 0x1E0) >> 5; + info->saved_regs[n] = info->r11_addr; return 1; } @@ -724,7 +722,6 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, (*this_cache) = info; info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS); - info->frameless = 0; info->size = 0; info->next_addr = 0; @@ -784,40 +781,51 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, info->size = -info->next_addr; - /* Start out with the frame's stack top. */ - frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp); - sp = d10v_make_daddr (sp); - - for (i = 0; i < NUM_REGS - 1; i++) - if (info->saved_regs[i]) - { - info->saved_regs[i] = sp - (info->next_addr - info->saved_regs[i]); - } - /* Compute the frame's base. */ - if (info->saved_regs[FP_REGNUM]) + if (info->uses_frame) { - /* The FP was saved, which means that the current FP is live. - Unwind its value from the NEXT frame. */ + /* The SP was moved into the FP. This indicates that a new + frame was created. Get THIS frame's FP value by unwinding it + from the next frame. */ frame_unwind_unsigned_register (next_frame, FP_REGNUM, &base); + /* The FP points at the last saved register. Adjust the FP back + to before the first saved register giving the SP. */ + sp = base + info->size; } else if (info->saved_regs[SP_REGNUM]) { - /* The SP was saved (this is very unusual), the frame base is + /* The SP was saved (which is very unusual), the frame base is just the PREV's frame's TOP-OF-STACK. */ base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM], register_size (current_gdbarch, SP_REGNUM)); - info->frameless = 1; + sp = base; } else { /* Assume that the FP is this frame's SP but with that pushed stack space added back. */ frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); - base += info->size; + sp = base + info->size; } + info->base = d10v_make_daddr (base); + sp = d10v_make_daddr (sp); + + /* Adjust all the saved registers so that they contain addresses and + not offsets. */ + for (i = 0; i < NUM_REGS - 1; i++) + { + if (info->saved_regs[i]) + { + info->saved_regs[i] = (sp + info->saved_regs[i]); + } + } + + /* The SP_REGNUM is special. Instead of the address of the SP, the + previous frame's SP value is saved. */ + info->saved_regs[SP_REGNUM] = sp; + return info; } @@ -1429,17 +1437,13 @@ static CORE_ADDR d10v_frame_pc_unwind (struct frame_info *next_frame, void **this_cache) { - /* FIXME: This shouldn't be needed. Instead a per-architecture - method should be called. */ - int optimized; - enum lval_type lval; - CORE_ADDR addr; - int realnum; - ULONGEST lr; + /* FIXME: This shouldn't be needed. Instead single per-architecture + method should be called for all frames. */ + CORE_ADDR lr; + struct d10v_unwind_cache *info + = d10v_frame_unwind_cache (next_frame, this_cache); void *buffer = alloca (max_register_size (current_gdbarch)); - d10v_frame_register_unwind (next_frame, this_cache, LR_REGNUM, - &optimized, &lval, &addr, &realnum, - buffer); + saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, buffer); lr = extract_unsigned_integer (buffer, register_size (current_gdbarch, LR_REGNUM)); return d10v_make_iaddr (lr); @@ -1472,26 +1476,24 @@ d10v_frame_id_unwind (struct frame_info *next_frame, return; } -#if 0 - if (!info->saved_regs[FP_REGNUM]) - { - if (!info->saved_regs[SP_REGNUM] - || info->saved_regs[SP_REGNUM] == STACK_START) - return; - - this_id->base = info->saved_regs[SP_REGNUM]; - this_id->pc = info->return_pc; - } + /* Hopefully the prologue analysis either correctly determined the + frame's base (which is the SP from the previous frame), or set + that base to "NULL". */ + base = info->base; + if (base == STACK_START || base == 0) + return; - addr = read_memory_unsigned_integer (info->saved_regs[FP_REGNUM], - register_size (current_gdbarch, FP_REGNUM)); - if (addr == 0) + /* Check that we're not going round in circles on the same frame ID. + Be careful to avoid applying the test to sentinel frames (which + do go round in circles). Can't use ID_EQ as that doesn't yet + compare PC values. */ + if (frame_relative_level (next_frame) >= 0 + && get_frame_type (next_frame) != DUMMY_FRAME + && get_frame_id (next_frame).pc == pc + && get_frame_id (next_frame).base == base) return; -#endif - /* Hopefully the prolog analysis has correctly determined the - frame's base. */ - this_id->base = info->base; + this_id->base = base; this_id->pc = pc; } @@ -1504,15 +1506,30 @@ saved_regs_unwinder (struct frame_info *next_frame, { if (saved_regs[prev_regnum] != 0) { - *optimizedp = 0; - *lvalp = lval_memory; - *addrp = saved_regs[prev_regnum]; - *realnump = -1; - if (bufferp != NULL) + if (prev_regnum == SP_REGNUM) + { + /* SP register treated specially. */ + *optimizedp = 0; + *lvalp = not_lval; + *addrp = 0; + *realnump = -1; + if (bufferp != NULL) + store_address (bufferp, + register_size (current_gdbarch, SP_REGNUM), + saved_regs[SP_REGNUM]); + } + else { - /* Read the value in from memory. */ - read_memory (saved_regs[prev_regnum], bufferp, - register_size (current_gdbarch, prev_regnum)); + *optimizedp = 0; + *lvalp = lval_memory; + *addrp = saved_regs[prev_regnum]; + *realnump = -1; + if (bufferp != NULL) + { + /* Read the value in from memory. */ + read_memory (saved_regs[prev_regnum], bufferp, + register_size (current_gdbarch, prev_regnum)); + } } return; } @@ -1525,6 +1542,20 @@ saved_regs_unwinder (struct frame_info *next_frame, realnump, bufferp); } +/* Wrapper so that local code can unwind register values. */ + +static void +saved_regs_unwind (struct frame_info *next_frame, CORE_ADDR *saved_regs, + int prev_regnum, void *bufferp) +{ + int optimized; + enum lval_type lval; + CORE_ADDR addr; + int realnum; + saved_regs_unwinder (next_frame, saved_regs, prev_regnum, + &optimized, &lval, &addr, &realnum, bufferp); +} + static void d10v_frame_register_unwind (struct frame_info *next_frame, @@ -1535,44 +1566,67 @@ d10v_frame_register_unwind (struct frame_info *next_frame, { struct d10v_unwind_cache *info = d10v_frame_unwind_cache (next_frame, this_cache); - if (prev_regnum == PC_REGNUM) - prev_regnum = LR_REGNUM; - saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp, - lvalp, addrp, realnump, bufferp); + if (prev_regnum == LR_REGNUM) + /* Unwinding the LR isn't possible. It's value is trashed by the + call instruction. Mark the value as optimized away. */ + { + *optimizedp = 1; + *lvalp = lval_register; + *addrp = 0; + *realnump = LR_REGNUM; + if (bufferp != NULL) + memset (bufferp, 0, register_size (current_gdbarch, LR_REGNUM)); + } + else if (prev_regnum == PC_REGNUM) + /* The caller's PC is saved in LR_REGNUM. Find/return the + LR_REGNUM. */ + saved_regs_unwinder (next_frame, info->saved_regs, LR_REGNUM, optimizedp, + lvalp, addrp, realnump, bufferp); + else + saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp, + lvalp, addrp, realnump, bufferp); } +static struct frame_id +d10v_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + ULONGEST base; + struct frame_id id; + id.pc = frame_pc_unwind (next_frame); + frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); + id.base = d10v_make_daddr (base); + return id; +} + static void -d10v_frame_pop (struct frame_info *fi, void **unwind_cache, +d10v_frame_pop (struct frame_info *next_frame, void **this_cache, struct regcache *regcache) { - struct d10v_unwind_cache *info = d10v_frame_unwind_cache (fi, unwind_cache); + struct d10v_unwind_cache *info + = d10v_frame_unwind_cache (next_frame, this_cache); CORE_ADDR fp; int regnum; char raw_buffer[8]; - fp = get_frame_base (fi); - /* now update the current registers with the old values */ for (regnum = A0_REGNUM; regnum < A0_REGNUM + NR_A_REGS; regnum++) { - frame_unwind_register (fi, regnum, raw_buffer); + saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer); regcache_cooked_write (regcache, regnum, raw_buffer); } for (regnum = 0; regnum < SP_REGNUM; regnum++) { - frame_unwind_register (fi, regnum, raw_buffer); + saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer); regcache_cooked_write (regcache, regnum, raw_buffer); } - frame_unwind_register (fi, PSW_REGNUM, raw_buffer); + saved_regs_unwind (next_frame, info->saved_regs, PSW_REGNUM, raw_buffer); regcache_cooked_write (regcache, PSW_REGNUM, raw_buffer); - frame_unwind_register (fi, LR_REGNUM, raw_buffer); + saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, raw_buffer); regcache_cooked_write (regcache, PC_REGNUM, raw_buffer); - store_unsigned_integer (raw_buffer, - register_size (current_gdbarch, SP_REGNUM), - fp + info->size); + saved_regs_unwind (next_frame, info->saved_regs, SP_REGNUM, raw_buffer); regcache_cooked_write (regcache, SP_REGNUM, raw_buffer); target_store_registers (-1); @@ -1728,6 +1782,8 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_print_registers_info (gdbarch, d10v_print_registers_info); frame_unwind_append_predicate (gdbarch, d10v_frame_p); + set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id); + set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos); return gdbarch; } diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 013e8ca..c1f5206 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2003-03-04 Andrew Cagney <cagney@redhat.com> + + 2003-02-27 Andrew Cagney <cagney@redhat.com> + * gdbint.texinfo (Target Architecture Definition): Document + unwind_dummy_id. Cross reference unwind_dummy_id and + SAVE_DUMMY_FRAME_TOS. + 2003-03-02 Daniel Jacobowitz <drow@mvista.com> * Makefile.in (distclean): Remove config.log. diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 35acd14..eba00ca 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -3691,10 +3691,11 @@ rather than directly. @item SAVE_DUMMY_FRAME_TOS (@var{sp}) @findex SAVE_DUMMY_FRAME_TOS -Used in @samp{call_function_by_hand} to notify the target dependent code -of the top-of-stack value that will be passed to the the inferior code. -This is the value of the @code{SP} after both the dummy frame and space -for parameters/results have been allocated on the stack. +@anchor{SAVE_DUMMY_FRAME_TOS} Used in @samp{call_function_by_hand} to +notify the target dependent code of the top-of-stack value that will be +passed to the the inferior code. This is the value of the @code{SP} +after both the dummy frame and space for parameters/results have been +allocated on the stack. @xref{unwind_dummy_id}. @item SDB_REG_TO_REGNUM @findex SDB_REG_TO_REGNUM @@ -3878,6 +3879,14 @@ Libraries, ,Opcodes}). @var{info} is a structure (of type @code{disassemble_info}) defined in @file{include/dis-asm.h} used to pass information to the instruction decoding routine. +@item struct frame_id unwind_dummy_id (struct frame_info *@var{frame}) +@findex unwind_dummy_id +@anchor{unwind_dummy_id} Given @var{frame} return a @code{struct +frame_id} that uniquely identifies an inferior function call's dummy +frame. The value returned must match the dummy frame stack value +previously saved using @code{SAVE_DUMMY_FRAME_TOS}. +@xref{SAVE_DUMMY_FRAME_TOS}. + @item USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type}) @findex USE_STRUCT_CONVENTION If defined, this must be an expression that is nonzero if a value of the diff --git a/gdb/frame.c b/gdb/frame.c index d70ac96..dd3cd68 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1345,39 +1345,83 @@ get_prev_frame (struct frame_info *next_frame) prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch, prev_frame->pc); - /* FIXME: cagney/2003-01-13: A dummy frame doesn't need to unwind - the frame ID because the frame ID comes from the previous frame. - The other frames do though. True? */ + /* Find the prev's frame's ID. */ { - /* FIXME: cagney/2002-12-18: Instead of this hack, should just - save the frame ID directly. */ - struct frame_id id; - prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache, &id); - /* Check that the unwound ID is valid. As of 2003-02-24 the - x86-64 was returning an invalid frame ID when trying to do an - unwind a sentinel frame that belonged to a frame dummy. */ - if (!frame_id_p (id)) + switch (prev_frame->type) { - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "Outermost frame - unwound frame ID invalid\n"); - return NULL; + case DUMMY_FRAME: + /* A dummy doesn't have anything resembling either a sane + frame or PC. The PC is sitting in the entry code and the + stack, which has nothing to do with that entry address, is + a down right mess. Trying to use the standard frame ID + unwind code to get the previous frame ID is just asking for + trouble. */ + if (gdbarch_unwind_dummy_id_p (current_gdbarch)) + { + /* Assume hand_function_call(), via SAVE_DUMMY_FRAME_TOS, + previously saved the dummy ID that is being obtained + here. Things only work if the two match. */ + gdb_assert (SAVE_DUMMY_FRAME_TOS_P ()); + /* Use an architecture specific method to extract the + prev's dummy ID from the next frame. Note that this + method typically uses frame_register_unwind to obtain + register values needed to determine the dummy ID. */ + next_frame->id_unwind_cache = + gdbarch_unwind_dummy_id (current_gdbarch, next_frame); + } + else if (next_frame->level == 0) + { + /* We're `unwinding' the sentinel frame. Just fake up the + ID the same way that the traditional hacks did it. */ + next_frame->id_unwind_cache.pc = read_pc (); + next_frame->id_unwind_cache.pc = read_fp (); + } + else + { + /* Outch! We're not on the innermost frame yet we're + trying to unwind to a dummy. The architecture must + provide the unwind_dummy_id() method. */ + internal_error (__FILE__, __LINE__, + "Missing unwind_dummy_id architecture method"); + } + break; + case NORMAL_FRAME: + case SIGTRAMP_FRAME: + prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache, + &next_frame->id_unwind_cache); + /* Check that the unwound ID is valid. */ + if (!frame_id_p (next_frame->id_unwind_cache)) + { + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "Outermost frame - unwound frame ID invalid\n"); + return NULL; + } + /* Check that the new frame isn't inner to (younger, below, + next) the old frame. If that happens the frame unwind is + going backwards. */ + /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since + that doesn't have a valid frame ID. Should instead set the + sentinel frame's frame ID to a `sentinel'. Leave it until + after the switch to storing the frame ID, instead of the + frame base, in the frame object. */ + if (next_frame->level >= 0 + && frame_id_inner (next_frame->id_unwind_cache, + get_frame_id (next_frame))) + error ("Unwound frame inner-to selected frame (corrupt stack?)"); + /* Note that, due to frameless functions, the stronger test of + the new frame being outer to the old frame can't be used - + frameless functions differ by only their PC value. */ + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); } - /* Check that the new frame isn't inner to (younger, below, next) - the old frame. If that happens the frame unwind is going - backwards. */ - /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since that - doesn't have a valid frame ID. Should instead set the sentinel - frame's frame ID to a `sentinel'. Leave it until after the - switch to storing the frame ID, instead of the frame base, in - the frame object. */ - if (next_frame->level >= 0 - && frame_id_inner (id, get_frame_id (next_frame))) - error ("Unwound frame inner-to selected frame (corrupt stack?)"); - /* Note that, due to frameless functions, the stronger test of the - new frame being outer to the old frame can't be used - - frameless functions differ by only their PC value. */ - prev_frame->frame = id.base; + /* FIXME: cagney/2002-12-18: Instead of this hack, the frame ID + should be directly stored in the `struct frame_info'. + Unfortunatly, GDB isn't quite ready for this, need to get HP/UX + multi-arch and make 'struct frame_info' opaque. */ + next_frame->id_unwind_cache_p = 1; + prev_frame->frame = next_frame->id_unwind_cache.base; } /* Link it in. */ @@ -1514,7 +1558,12 @@ deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc) { /* See comment in "frame.h". */ gdb_assert (frame->next != NULL); + /* Fix up this PC's value. */ frame->pc = pc; + /* While we're at it, also update the cache, in NEXT, that also + contains that value. */ + frame->next->pc_unwind_cache = pc; + frame->next->pc_unwind_cache_p = 1; } void diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 68247d6..636349c 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -251,6 +251,7 @@ struct gdbarch int extra_stack_alignment_needed; gdbarch_reg_struct_has_addr_ftype *reg_struct_has_addr; gdbarch_save_dummy_frame_tos_ftype *save_dummy_frame_tos; + gdbarch_unwind_dummy_id_ftype *unwind_dummy_id; int parm_boundary; const struct floatformat * float_format; const struct floatformat * double_format; @@ -431,6 +432,7 @@ struct gdbarch startup_gdbarch = 0, 0, 0, + 0, generic_in_function_epilogue_p, construct_inferior_arguments, 0, @@ -770,6 +772,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of extra_stack_alignment_needed, invalid_p == 0 */ /* Skip verify of reg_struct_has_addr, has predicate */ /* Skip verify of save_dummy_frame_tos, has predicate */ + /* Skip verify of unwind_dummy_id, has predicate */ if (gdbarch->float_format == 0) gdbarch->float_format = default_float_format (gdbarch); if (gdbarch->double_format == 0) @@ -2567,6 +2570,14 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) (long) current_gdbarch->write_sp /*TARGET_WRITE_SP ()*/); #endif + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_unwind_dummy_id_p() = %d\n", + gdbarch_unwind_dummy_id_p (current_gdbarch)); + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: unwind_dummy_id = 0x%08lx\n", + (long) current_gdbarch->unwind_dummy_id); #ifdef USE_STRUCT_CONVENTION fprintf_unfiltered (file, "gdbarch_dump: %s # %s\n", @@ -5032,6 +5043,32 @@ set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch, } int +gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->unwind_dummy_id != 0; +} + +struct frame_id +gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info) +{ + gdb_assert (gdbarch != NULL); + if (gdbarch->unwind_dummy_id == 0) + internal_error (__FILE__, __LINE__, + "gdbarch: gdbarch_unwind_dummy_id invalid"); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_dummy_id called\n"); + return gdbarch->unwind_dummy_id (gdbarch, info); +} + +void +set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, + gdbarch_unwind_dummy_id_ftype unwind_dummy_id) +{ + gdbarch->unwind_dummy_id = unwind_dummy_id; +} + +int gdbarch_parm_boundary (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 59dd3d6..b1cb72b 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -2458,6 +2458,12 @@ extern void set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch, gdbarch_s #endif #endif +extern int gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch); + +typedef struct frame_id (gdbarch_unwind_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *info); +extern struct frame_id gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info); +extern void set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, gdbarch_unwind_dummy_id_ftype *unwind_dummy_id); + extern int gdbarch_parm_boundary (struct gdbarch *gdbarch); extern void set_gdbarch_parm_boundary (struct gdbarch *gdbarch, int parm_boundary); #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (PARM_BOUNDARY) diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 12953c2..b367fda 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -602,6 +602,7 @@ M:::CORE_ADDR:frame_align:CORE_ADDR address:address v:2:EXTRA_STACK_ALIGNMENT_NEEDED:int:extra_stack_alignment_needed::::0:1::0::: F:2:REG_STRUCT_HAS_ADDR:int:reg_struct_has_addr:int gcc_p, struct type *type:gcc_p, type::0:0 F:2:SAVE_DUMMY_FRAME_TOS:void:save_dummy_frame_tos:CORE_ADDR sp:sp::0:0 +M::UNWIND_DUMMY_ID:struct frame_id:unwind_dummy_id:struct frame_info *info:info::0:0 v:2:PARM_BOUNDARY:int:parm_boundary # v:2:TARGET_FLOAT_FORMAT:const struct floatformat *:float_format::::::default_float_format (gdbarch)::%s:(TARGET_FLOAT_FORMAT)->name |