| From 7944750e435100e72913f01aa0a43b7d7cffd421 Mon Sep 17 00:00:00 2001 |
| From: nagaraju <nmekala@xilix.com> |
| 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 <nmekala@xilix.com> |
| 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 |
| |