From 7944750e435100e72913f01aa0a43b7d7cffd421 Mon Sep 17 00:00:00 2001 From: nagaraju Date: Tue, 3 Sep 2013 12:09:47 +0530 Subject: [PATCH 08/16] [Patch, microblaze]: Added Backtrace support to GDB Added backtrace support without debugging information. Earlier backtrace used to work only when debug information is available. Previous pc & sp values are calculated incorrectly due to which backtrace was failing. In this patch, previous frame sp & pc values are calculated correctly in microblaze_frame_cache function and supplied them to microblaze_frame_prev_register function Signed-off-by:nagaraju Upstream-Status: Pending --- gdb/microblaze-tdep.c | 42 ++++++++++++++++++++++++++++++++++-------- gdb/microblaze-tdep.h | 5 +++-- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c index 0ce4947..247740e 100644 --- a/gdb/microblaze-tdep.c +++ b/gdb/microblaze-tdep.c @@ -225,6 +225,7 @@ microblaze_alloc_frame_cache (void) /* Base address. */ cache->base = 0; cache->pc = 0; + cache->saved_sp = 0; /* Frameless until proven otherwise. */ cache->frameless_p = 1; @@ -347,6 +348,7 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, cache->frameless_p = 0; /* Frame found. */ save_hidden_pointer_found = 0; non_stack_instruction_found = 0; + cache->register_offsets[rd] = -imm; continue; } else if (IS_SPILL_SP(op, rd, ra)) @@ -508,6 +510,7 @@ microblaze_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) return start_pc; } +enum { REG_UNAVAIL = (CORE_ADDR) -1 }; /* Normal frames. */ static struct microblaze_frame_cache * @@ -515,7 +518,7 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache) { struct microblaze_frame_cache *cache; struct gdbarch *gdbarch = get_frame_arch (next_frame); - CORE_ADDR func; + CORE_ADDR current_pc; int rn; if (*this_cache) @@ -529,10 +532,18 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache) for (rn = 0; rn < gdbarch_num_regs (gdbarch); rn++) cache->register_offsets[rn] = -1; - func = get_frame_func (next_frame); + cache->pc = get_frame_func (next_frame); + current_pc = get_frame_pc (next_frame); + + if (cache->pc) + microblaze_analyze_prologue (gdbarch, cache->pc, current_pc, + cache); cache->base = get_frame_register_unsigned (next_frame, gdbarch_sp_regnum (gdbarch)); - cache->pc = get_frame_address_in_block (next_frame); + cache->saved_sp = cache->base + cache->framesize; + + cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM] = cache->base; + cache->register_offsets[MICROBLAZE_SP_REGNUM] = cache->saved_sp; return cache; } @@ -548,7 +559,7 @@ microblaze_frame_this_id (struct frame_info *next_frame, void **this_cache, if (cache->base == 0) return; - (*this_id) = frame_id_build (cache->base, get_frame_pc (next_frame)); + (*this_id) = frame_id_build (cache->base, cache->pc); } static struct value * @@ -558,6 +569,14 @@ microblaze_frame_prev_register (struct frame_info *this_frame, struct microblaze_frame_cache *cache = microblaze_frame_cache (this_frame, this_cache); + if ((regnum == MICROBLAZE_SP_REGNUM && + cache->register_offsets[MICROBLAZE_SP_REGNUM]) + || (regnum == MICROBLAZE_FP_REGNUM && + cache->register_offsets[MICROBLAZE_SP_REGNUM])) + + return frame_unwind_got_constant (this_frame, regnum, + cache->register_offsets[MICROBLAZE_SP_REGNUM]); + if (cache->frameless_p) { if (regnum == MICROBLAZE_PC_REGNUM) @@ -565,11 +584,18 @@ microblaze_frame_prev_register (struct frame_info *this_frame, if (regnum == MICROBLAZE_SP_REGNUM) regnum = 1; return trad_frame_get_prev_register (this_frame, - cache->saved_regs, regnum); + cache->saved_regs, regnum); } - else - return trad_frame_get_prev_register (this_frame, cache->saved_regs, - regnum); + + if (regnum == MICROBLAZE_PC_REGNUM) + { + regnum = 15; + return frame_unwind_got_memory (this_frame, regnum, + cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM]); + } + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, + regnum); } diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h index cd32e9f..14eb3ab 100644 --- a/gdb/microblaze-tdep.h +++ b/gdb/microblaze-tdep.h @@ -57,6 +57,7 @@ struct microblaze_frame_cache /* Offsets to saved registers. */ int register_offsets[59]; /* Must match MICROBLAZE_NUM_REGS. */ + CORE_ADDR saved_sp; /* Table of saved registers. */ struct trad_frame_saved_reg *saved_regs; @@ -80,11 +81,11 @@ enum microblaze_regnum MICROBLAZE_R12_REGNUM, MICROBLAZE_R13_REGNUM, MICROBLAZE_R14_REGNUM, - MICROBLAZE_R15_REGNUM, + MICROBLAZE_R15_REGNUM, MICROBLAZE_PREV_PC_REGNUM = MICROBLAZE_R15_REGNUM, MICROBLAZE_R16_REGNUM, MICROBLAZE_R17_REGNUM, MICROBLAZE_R18_REGNUM, - MICROBLAZE_R19_REGNUM, + MICROBLAZE_R19_REGNUM, MICROBLAZE_FP_REGNUM = MICROBLAZE_R19_REGNUM, MICROBLAZE_R20_REGNUM, MICROBLAZE_R21_REGNUM, MICROBLAZE_R22_REGNUM, -- 1.9.0