From 8db7f0221e6282c217b6d420a674c76f7ca6191c Mon Sep 17 00:00:00 2001 From: Ajit Kumar Agarwal Date: Tue, 20 May 2014 13:29:46 +0530 Subject: [PATCH] [Patch, Microblaze]: Added support of shr and slr regs, little endian breakpoints, backtrace support and communicate with larger blocks. This patch added the support of shr and slr regs and little endian breakpoints, backtrace support without debug information and communicate larger blocks with debugging agent. ChangeLog: 2014-05-20 Ajit Agarwal * gdb/gdbserver/Makefile.in (microblaze-linux.c) : New target * gdb/microblaze-tdep.c (microblaze_register_names): Added the rshr and rslr register names. (microblaze_breakpoint_from_pc): Added Declaration of byte_order and break_insn_le. Check of byte order by BFD_ENDIAN_BIG (microblaze_alloc_frame_cache): Initialize saved_sp (microblaze_analyze_prologue): Do a block read to minimize the transaction with debug agent. Use of target_read_memory. Freeing the block read. (microblaze_frame_cache): use of microblaze_analyze_prologue and assigning the register_offsets. (microblaze_frame_prev_register): Use of frame_unwind_got_constant. Check of regnum with MICROBLAZE_SP_REGNUM ,MICROBLAZE_R19_REGNUM, MICROBLAZE_PC_REGNUM. * gdb/microblaze-tdep.h (microblaze_frame_cache): Addition of fields saved_sp,modification of register_offsets. (microblaze_reg_num): Addition of fields MICROBLAZE_SLR_REGNUM and MICROBLAZE_SHR_REGNUM. (MICROBLAZE_BREAKPOINT_LE): New Macro. * gdb/regformats/reg-microblaze.dat: New Register Data files for Microblaze. Signed-off-by:Ajit Agarwal --- gdb/gdbserver/Makefile.in | 5 ++- gdb/microblaze-tdep.c | 69 +++++++++++++++++++++++++++++++----- gdb/microblaze-tdep.h | 9 ++++- gdb/regformats/reg-microblaze.dat | 41 ++++++++++++++++++++++ 4 files changed, 111 insertions(+), 13 deletions(-) create mode 100644 gdb/regformats/reg-microblaze.dat diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index f773fa2..b2eb562 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -348,7 +348,8 @@ clean: rm -f amd64-avx.c amd64-avx-linux.c rm -f amd64-mpx.c amd64-mpx-linux.c rm -f amd64-avx512.c amd64-avx512-linux.c - rm -f i386-mmx.c i386-mmx-linux.c + rm -f i386-mmx.c i386-mmx-linux.c + rm -f microblaze-linux.c rm -f x32.c x32-linux.c rm -f x32-avx.c x32-avx-linux.c rm -f x32-avx512.c x32-avx512-linux.c @@ -614,6 +615,8 @@ reg-cf.c : $(srcdir)/../regformats/reg-cf.dat $(regdat_sh) $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-cf.dat reg-cf.c mips-linux.c : $(srcdir)/../regformats/mips-linux.dat $(regdat_sh) $(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-linux.dat mips-linux.c +microblaze-linux.c : $(srcdir)/../regformats/reg-microblaze.dat $(regdat_sh) + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-microblaze.dat mips-linux.c mips-dsp-linux.c : $(srcdir)/../regformats/mips-dsp-linux.dat $(regdat_sh) $(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-dsp-linux.dat mips-dsp-linux.c mips64-linux.c : $(srcdir)/../regformats/mips64-linux.dat $(regdat_sh) diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c index 14c1b52..bbb9061 100644 --- a/gdb/microblaze-tdep.c +++ b/gdb/microblaze-tdep.c @@ -73,7 +73,8 @@ static const char *microblaze_register_names[] = "rpc", "rmsr", "rear", "resr", "rfsr", "rbtr", "rpvr0", "rpvr1", "rpvr2", "rpvr3", "rpvr4", "rpvr5", "rpvr6", "rpvr7", "rpvr8", "rpvr9", "rpvr10", "rpvr11", - "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi" + "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi", + "rslr", "rshr" }; #define MICROBLAZE_NUM_REGS ARRAY_SIZE (microblaze_register_names) @@ -160,10 +161,15 @@ static const gdb_byte * microblaze_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, int *len) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); static gdb_byte break_insn[] = MICROBLAZE_BREAKPOINT; + static gdb_byte break_insn_le[] = MICROBLAZE_BREAKPOINT_LE; *len = sizeof (break_insn); - return break_insn; + if (byte_order == BFD_ENDIAN_BIG) + return break_insn; + else + return break_insn_le; } /* Allocate and initialize a frame cache. */ @@ -178,6 +184,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; @@ -234,6 +241,10 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, int flags = 0; int save_hidden_pointer_found = 0; int non_stack_instruction_found = 0; + int n_insns; + unsigned long *insn_block; + gdb_byte *buf_block; + int ti, tj; /* Find the start of this function. */ find_pc_partial_function (pc, &name, &func_addr, &func_end); @@ -273,9 +284,24 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, name, paddress (gdbarch, func_addr), paddress (gdbarch, stop)); + /* Do a block read to minimize the transaction with the Debug Agent */ + n_insns = (stop == func_addr) ? 1 : ((stop - func_addr) / INST_WORD_SIZE); + insn_block = (unsigned long *)calloc(n_insns, sizeof(unsigned long)); + buf_block = (gdb_byte *)calloc(n_insns * INST_WORD_SIZE, sizeof(gdb_byte)); + + target_read_memory (func_addr, buf_block, n_insns * INST_WORD_SIZE ); + + for (ti = 0; ti < n_insns; ti++) + { + insn_block[ti] = 0; + for (tj = ti * INST_WORD_SIZE; tj < (ti + 1) * INST_WORD_SIZE; tj++) + insn_block[ti] = (insn_block[ti] << 8) | buf_block[tj]; + } + + for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE) { - insn = microblaze_fetch_instruction (addr); + insn = insn_block[(addr - func_addr) / INST_WORD_SIZE]; op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); microblaze_debug ("%s %08lx\n", paddress (gdbarch, pc), insn); @@ -290,7 +316,8 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, cache->framesize = -imm; /* stack grows towards low memory. */ cache->frameless_p = 0; /* Frame found. */ save_hidden_pointer_found = 0; - non_stack_instruction_found = 0; + non_stack_instruction_found = 0; + cache->register_offsets[rd] = -imm; continue; } else if (IS_SPILL_SP(op, rd, ra)) @@ -401,7 +428,8 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, part of the prologue. */ if (save_hidden_pointer_found) prologue_end_addr -= INST_WORD_SIZE; - + free (insn_block); + free (buf_block); return prologue_end_addr; } @@ -451,7 +479,7 @@ microblaze_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) return ostart_pc; return start_pc; } - +enum { REG_UNAVAIL = (CORE_ADDR) -1 }; /* Normal frames. */ static struct microblaze_frame_cache * @@ -460,6 +488,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) @@ -474,8 +503,18 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache) cache->register_offsets[rn] = -1; func = get_frame_func (next_frame); + current_pc = get_frame_pc (next_frame); + + if (func) + microblaze_analyze_prologue (gdbarch, cache->pc, current_pc, + cache); + cache->pc = get_frame_address_in_block (next_frame); + cache->saved_sp = cache->base + cache->framesize; + cache->register_offsets[MICROBLAZE_R15_REGNUM] = cache->base; + cache->register_offsets[MICROBLAZE_SP_REGNUM] = cache->saved_sp; + return cache; } @@ -500,7 +539,7 @@ microblaze_frame_prev_register (struct frame_info *this_frame, { struct microblaze_frame_cache *cache = microblaze_frame_cache (this_frame, this_cache); - + if (cache->frameless_p) { if (regnum == MICROBLAZE_PC_REGNUM) @@ -510,10 +549,20 @@ microblaze_frame_prev_register (struct frame_info *this_frame, return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); } - else - return trad_frame_get_prev_register (this_frame, cache->saved_regs, + if ((regnum == MICROBLAZE_SP_REGNUM && + cache->register_offsets[MICROBLAZE_SP_REGNUM]) + || (regnum == MICROBLAZE_R19_REGNUM && + cache->register_offsets[MICROBLAZE_SP_REGNUM])) + return frame_unwind_got_constant (this_frame, regnum, + cache->register_offsets[MICROBLAZE_SP_REGNUM]); + if (regnum == MICROBLAZE_PC_REGNUM){ + regnum = 15; + return frame_unwind_got_memory (this_frame, regnum, + cache->register_offsets[MICROBLAZE_R15_REGNUM]); + } + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); - } static const struct frame_unwind microblaze_frame_unwind = diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h index a532092..fdf4ca4 100644 --- a/gdb/microblaze-tdep.h +++ b/gdb/microblaze-tdep.h @@ -32,6 +32,7 @@ struct microblaze_frame_cache CORE_ADDR base; CORE_ADDR pc; + CORE_ADDR saved_sp; /* Do we have a frame? */ int frameless_p; @@ -42,7 +43,7 @@ struct microblaze_frame_cache int fp_regnum; /* Offsets to saved registers. */ - int register_offsets[57]; /* Must match MICROBLAZE_NUM_REGS. */ + int register_offsets[59]; /* Must match MICROBLAZE_NUM_REGS. */ /* Table of saved registers. */ struct trad_frame_saved_reg *saved_regs; @@ -107,7 +108,10 @@ enum microblaze_regnum MICROBLAZE_RTLBX_REGNUM, MICROBLAZE_RTLBSX_REGNUM, MICROBLAZE_RTLBLO_REGNUM, - MICROBLAZE_RTLBHI_REGNUM + MICROBLAZE_RTLBHI_REGNUM, + MICROBLAZE_SLR_REGNUM, + MICROBLAZE_SHR_REGNUM + }; /* All registers are 32 bits. */ @@ -116,5 +120,6 @@ enum microblaze_regnum /* MICROBLAZE_BREAKPOINT defines the breakpoint that should be used. Only used for native debugging. */ #define MICROBLAZE_BREAKPOINT {0xb9, 0xcc, 0x00, 0x60} +#define MICROBLAZE_BREAKPOINT_LE {0x18, 0x00, 0x0c, 0xba} #endif /* microblaze-tdep.h */ diff --git a/gdb/regformats/reg-microblaze.dat b/gdb/regformats/reg-microblaze.dat new file mode 100644 index 0000000..936bc44 --- /dev/null +++ b/gdb/regformats/reg-microblaze.dat @@ -0,0 +1,41 @@ +name:microblaze +expedite:r1,pc +32:r0 +32:r1 +32:r2 +32:r3 +32:r4 +32:r5 +32:r6 +32:r7 +32:r8 +32:r9 +32:r10 +32:r11 +32:r12 +32:r13 +32:r14 +32:r15 +32:r16 +32:r17 +32:r18 +32:r19 +32:r20 +32:r21 +32:r22 +32:r23 +32:r24 +32:r25 +32:r26 +32:r27 +32:r28 +32:r29 +32:r30 +32:r31 +32:pc +32:msr +32:ear +32:esr +32:fsr +32:slr +32:shr -- 1.7.1