KGDB set / remove breakpoints
PATCH 1/1 KGDB set / remove breakpoints
This patch extends the current KGDB logic to handle 'Z' and 'z' GDB packets for setting or removing breakpoints.
Two weak functions have been added to the kgdb_stub.c:arch_kgdb_set_sw_break() and arch_kgdb_remove_sw_break() could be overrode by the arch implementations.
Please note, after applying this patch, those architectures, which already enabled KGDB support, have to create a new asm/kgdb.h and define the length of the break instruction (BREAK_INSTR_SIZE) in that file.
--- common/kgdb.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ common/kgdb_stubs.c | 12 +++++++ include/kgdb.h | 31 ++++++++++++++++++ 3 files changed, 128 insertions(+), 0 deletions(-)
common/kgdb.c +85 -0
@@ -220,6 +220,85 @@ hexToInt(char **ptr, int *intValue)return (numChars); } +/* +* Holds information about breakpoints in a kernel. These breakpoints are +* added and removed by gdb. +*/ +static struct kgdb_bkpt kgdb_break[KGDB_MAX_BREAKPOINTS ]; + +static int kgdb_set_sw_break (int addr) +{ +int i, breakno =-1 ; +struct kgdb_bkpt *bkpt; + +for (i =0 ; i <KGDB_MAX_BREAKPOINTS ; i++) { +if ((kgdb_break[i].state ==BP_SET ) && + (kgdb_break[i].bpt_addr == addr)) +return -KGDBERR_BPEXIST ; +if ((kgdb_break[i].state ==BP_REMOVED ) && + (kgdb_break[i].bpt_addr == addr)) { + breakno = i; +break ; + } + } +if (breakno ==-1 ) +for (i =0 ; i <KGDB_MAX_BREAKPOINTS ; i++) { +if (kgdb_break[i].state ==BP_UNDEFINED ) { + breakno = i; +break ; + } + } +if (breakno ==-1 ) +return -KGDBERR_BPNOENT ; + + bkpt = kgdb_break + breakno; + bkpt->state =BP_SET ; + bkpt->type =BP_BREAKPOINT ; + bkpt->bpt_addr = addr; +arch_kgdb_set_sw_break (bkpt); + +return 0 ; +} + +static int kgdb_remove_sw_break (int addr) +{ +int i; +struct kgdb_bkpt *bkpt; + +for (i =0 ; i <KGDB_MAX_BREAKPOINTS ; i++) { + bkpt = kgdb_break + i; +if ((bkpt->state ==BP_SET ) && (bkpt->bpt_addr == addr)) { + bkpt->state =BP_REMOVED ; +arch_kgdb_remove_sw_break (bkpt); +return 0 ; + } + } +return -KGDBERR_BPNOENT ; +} + +/* Handle the 'z' or 'Z' breakpoint remove or set packets */ +static void gdb_cmd_break (kgdb_data *kdp) +{ +/* +* Since GDB-5.3, it's been drafted that '0' is a software +* breakpoint, '1' is a hardware breakpoint, so let's do that. +*/ +char *bpt_type = &remcomInBuffer[1 ]; +char *ptr = &remcomInBuffer[2 ]; +int addr, length; + +if (*bpt_type !='0' ) +return ;/* Unsupported. */ +if (*ptr++ !=',' || !hexToInt (&ptr, &addr) || + *ptr++ !=',' || !hexToInt (&ptr, &length)) { +kgdb_error (KGDBERR_BADPARAMS ); + } + +if ((remcomInBuffer[0 ] =='Z' &&kgdb_set_sw_break (addr) ==0 ) || + (remcomInBuffer[0 ] =='z' &&kgdb_remove_sw_break (addr) ==0 )) +strcpy (remcomOutBuffer,"OK" ); +} +/* scan for the sequence $<data>#<checksum> */ static void getpacket (char *buffer)
@@ -341,7 +420,9 @@ handle_exception (struct pt_regs *regs)kgdb_interruptible (0 ); +#ifdef KGDB_DEBUG printf ("kgdb: handle_exception; trap [0x%x]\n" ,kgdb_trap (regs)); +#endif if (kgdb_setjmp (error_jmp_buf) !=0 )panic ("kgdb: error or fault in entry init!\n" );
@@ -516,6 +597,10 @@ handle_exception (struct pt_regs *regs)kgdb_error (KGDBERR_BADPARAMS ); }break ; +case 'Z' :/* [Z|z]N,AA..AA,LLLL Set/Remove breakpoint type N */ +case 'z' :/* LLLL bytes at address AA.AA return OK */ +gdb_cmd_break (&kd); +break ; }/* switch */ if (errnum !=0 )
common/kgdb_stubs.c +12 -0
@@ -45,6 +45,18 @@ void kgdb_interruptible(int yes) } __attribute__((weak)) +void arch_kgdb_set_sw_break (struct kgdb_bkpt *bkpt) +{ +return ; +} + +__attribute__((weak)) +void arch_kgdb_remove_sw_break (struct kgdb_bkpt *bkpt) +{ +return ; +} + +__attribute__((weak))void kgdb_flush_cache_range (void *from,void *to) {flush_cache ((unsigned long )from, (unsigned long )(to - from));
include/kgdb.h +31 -0
@@ -2,12 +2,41 @@#define __KGDB_H__#include <asm/ptrace.h> +#include <asm/kgdb.h> #define KGDBERR_BADPARAMS 1#define KGDBERR_NOTHEXDIG 2#define KGDBERR_MEMFAULT 3#define KGDBERR_NOSPACE 4#define KGDBERR_ALIGNFAULT 5 +#define KGDBERR_BPEXIST 6 +#define KGDBERR_BPNOENT 7 + +#ifndef KGDB_MAX_BREAKPOINTS +#define KGDB_MAX_BREAKPOINTS 1000 +#endif + +enum kgdb_bptype { +BP_BREAKPOINT =0 , +BP_HARDWARE_BREAKPOINT , +BP_WRITE_WATCHPOINT , +BP_READ_WATCHPOINT , +BP_ACCESS_WATCHPOINT +}; + +enum kgdb_bpstate { +BP_UNDEFINED =0 , +BP_REMOVED , +BP_SET , +BP_ACTIVE +}; + +struct kgdb_bkpt { +unsigned long bpt_addr; +unsigned char saved_instr[BREAK_INSTR_SIZE ]; +enum kgdb_bptype type; +enum kgdb_bpstate state; +};#define KGDBDATA_MAXREGS 8#define KGDBDATA_MAXPRIV 8
@@ -56,6 +85,8 @@ extern void kgdb_putreg(struct pt_regs *, int, char *, int);extern void kgdb_putregs (struct pt_regs *,char *,int );extern int kgdb_trap (struct pt_regs *);extern void kgdb_breakpoint (int argc,char *argv[]); +extern void arch_kgdb_set_sw_break (struct kgdb_bkpt *); +extern void arch_kgdb_remove_sw_break (struct kgdb_bkpt *);/* these functions are provided by the platform serial driver */ extern void kgdb_serial_init (void );
Signature · 1 line
1.6.0.6
PATCH 1/1 KGDB set / remove breakpoints
Quoted 11 lines · On Saturday 17 April 2010 13:20:11 Tonny Tzeng wrote:
This patch extends the current KGDB logic to handle 'Z' and 'z' GDB packets for setting or removing breakpoints.
Two weak functions have been added to the
kgdb_stub.c:arch_kgdb_set_sw_break()andarch_kgdb_remove_sw_break()could be overrode by the arch implementations.Please note, after applying this patch, those architectures, which already enabled KGDB support, have to create a new
asm/kgdb.hand define the length of the break instruction (BREAK_INSTR_SIZE) in that file.
i dont think breaking build is a good idea. i would have the code simply disable itself if BREAK_INSTR_SIZE isnt set.
common/kgdb.c hexToInt(char **ptr, int *intValue) · line 227
Quoted 5 lines
common/kgdb.c +5
-0+/* +* Holds information about breakpoints in a kernel. These breakpoints are +* added and removed by gdb. +*/ +static struct kgdb_bkpt kgdb_break[KGDB_MAX_BREAKPOINTS ];
use a space between the type and the name, not a tab
Quoted 5 lines
common/kgdb.c +5
-0+static int kgdb_set_sw_break (int addr) +{ +int i, breakno =-1 ; +struct kgdb_bkpt *bkpt; +
common/kgdb.c hexToInt(char **ptr, int *intValue) · line 243
Quoted 10 lines
common/kgdb.c +10
-0+for (i =0 ; i <KGDB_MAX_BREAKPOINTS ; i++) { +if ((kgdb_break[i].state ==BP_SET ) && + (kgdb_break[i].bpt_addr == addr)) +return -KGDBERR_BPEXIST ; +if ((kgdb_break[i].state ==BP_REMOVED ) && + (kgdb_break[i].bpt_addr == addr)) { + breakno = i; +break ; + } + }
there are a few places that loop over the structure to find a bpt by its addr. would probably be better to write a helper function:
static int kgdb_find_break_by_addr(int addr)
{
int i;
for (i = 0; i < KGDB_MAX_BREAKPOINTS; ++i)
if (kgdb_break[i].bpt_addr == addr)
return i;
return -1;
}then this function becomes a lot simpler:
breakno = kgdb_find_break_by_addr(addr);
if (breakno != -1) {
if (kgdb_break[breakno].state == BP_SET)
return .....
....
} else {
....include/kgdb.h line 39
Quoted 10 lines
include/kgdb.h +9
-0+#ifndef KGDB_MAX_BREAKPOINTS +#define KGDB_MAX_BREAKPOINTS 1000 +#endif +struct kgdb_bkpt { +unsigned long bpt_addr; +unsigned char saved_instr[BREAK_INSTR_SIZE ]; +enum kgdb_bptype type; +enum kgdb_bpstate state; +};
the kgdb_bkpt is going to be about 16 bytes, and you're setting a default of 1000 ? that seems like an excessively large number that will simply waste memory (16k of it). please use something much smaller like say 10 or 20.
also, for struct packing, it'd be better if the saved_instr was at the end of the struct so it doesnt force an alignment hole in the middle.
the define also needs a CONFIG_ type prefix on it.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20100417/fd869d8e/attachment.pgp
PATCH 1/1 KGDB set / remove breakpoints
Thanks for the review, Mike.
Quoted 7 lines
Quoted 4 lines
Please note, after applying this patch, those architectures, which already enabled KGDB support, have to create a new
asm/kgdb.hand define the length of the break instruction (BREAK_INSTR_SIZE) in that file.i dont think breaking build is a good idea. ?i would have the code simply disable itself if
BREAK_INSTR_SIZEisnt set.
That's why I used ifndef in the previous patch, and set BREAK_INSTR_SIZE to 4 if it isn't set, but I thought you prefer "an undefined size should be used as a tip that the arch doesnt yet support break points"?
In Linux kgdb code, there is an arch independent header file include/linux/kgdb.h, which includes arch dependent header asm/kgdb.h.
I am trying to include this concept here, unfortunately current
u-boot code only has linux/kgdb.h, if we want to define arch specific code in asm/kgdb.h, we may need to include asm/kgdb.h from linux/kgdb.h, so it looks to me it will definitely break other arch, do you have any suggestion for that?
Best Regards,
Tonny
PATCH 1/1 KGDB set / remove breakpoints
Quoted 5 lines · On Monday 19 April 2010 04:54:50 Tonny Tzeng wrote:
Quoted 5 lines
Quoted 4 lines
Please note, after applying this patch, those architectures, which already enabled KGDB support, have to create a new
asm/kgdb.hand define the length of the break instruction (BREAK_INSTR_SIZE) in that file.
Quoted 7 lines
Quoted 2 lines
i dont think breaking build is a good idea. i would have the code simply disable itself if
BREAK_INSTR_SIZEisnt set.That's why I used ifndef in the previous patch, and set
BREAK_INSTR_SIZEto 4 if it isn't set, but I thought you prefer "an undefined size should be used as a tip that the arch doesnt yet support break points"?
i meant have the functions always return an error. have the header do:
#ifndef BREAK_INSTR_SIZE
#define BREAK_INSTR_SIZE 0
#endif
and then in gdb_cmd_break(), do something at the top like:
if (BREAK_INSTR_SIZE == 0)
return;
Quoted 7 lines
In Linux kgdb code, there is an arch independent header file
include/linux/kgdb.h, which includes arch dependent headerasm/kgdb.h.
I am trying to include this concept here, unfortunately current
u-boot code only haslinux/kgdb.h, if we want to define arch specific code inasm/kgdb.h, we may need to includeasm/kgdb.hfromlinux/kgdb.h, so it looks to me it will definitely break other arch, do you have any suggestion for that?
just post a patch to add asm/kgdb.h stubs for the few arches that you dont implement yourself. i think only blackfin/i386/ppc support kgdb atm. -mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20100420/e316eefb/attachment.pgp
v2 cover Add KGDB support for ARM platforms
In reply to Tonny TzengThis patchset adds KGDB support for ARM platforms.
Since the KGDB support for ARM is through the undef instruction handler, we need to add code to the startup file to restore the user context after exception. Unfortunately, each ARM variant has his own start.S, so please reference the patch designed for arm720 to add the 'bad_restore_user_regs' logic to your ARM start-up file.
v1 - initial patchset
v2 - (a) move code, which should be common to all arch, to common/kgdb.c;
add two new weak funcs to common/kgdb_stubs.c, and separate these common code to the patch "KGDB set / remove breakpoints".
(b) remove the watchdog func during the board initialization.
(c) flush all cache after mangling instructions.
Best Regards,
Tonny
PATCH v2 1/4 Add KGDB support for ARM platforms
--- arch/arm/lib/board.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/lib/board.c +4 -0
@@ -381,6 +381,10 @@ void start_armboot (void)/* miscellaneous platform dependent initialisations */ misc_init_r ();#endif +#if defined(CONFIG_CMD_KGDB ) +puts ("KGDB: " ); +kgdb_init (); +#endif /* enable exceptions */ enable_interrupts ();
Signature · 1 line
1.6.0.6
PATCH v2 2/4 Add KGDB support for ARM platforms
--- arch/arm/lib/interrupts.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
arch/arm/lib/interrupts.c +9 -0
@@ -37,6 +37,9 @@#include <common.h> #include <asm/proc-armv/ptrace.h> +#ifdef CONFIG_CMD_KGDB +#include <kgdb.h> +#endif #ifdef CONFIG_USE_IRQ DECLARE_GLOBAL_DATA_PTR ;
@@ -137,6 +140,12 @@ void show_regs (struct pt_regs *regs)void do_undefined_instruction (struct pt_regs *pt_regs) { +#ifdef CONFIG_CMD_KGDB +if (*(unsigned long *)(instruction_pointer (pt_regs) -4 ) ==KGDB_COMPILED_BREAK ) { + (*debugger_exception_handler)(pt_regs); +return ; + } +#endif printf ("undefined instruction\n" );show_regs (pt_regs);bad_mode ();
Signature · 1 line
1.6.0.6
PATCH v2 3/4 Add KGDB support for ARM platforms
--- arch/arm/include/asm/kgdb.h | 66 +++++++++++++++ arch/arm/lib/Makefile | 1 + arch/arm/lib/kgdb.c | 194 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/kgdb.h create mode 100644 arch/arm/lib/kgdb.c
arch/arm/include/asm/kgdb.h new file +66 -0
@@ -0,0 +1,66 @@ +/* +* ARM KGDB support +* +* Author: Deepak Saxena <[email protected]> +* +* Copyright (C) 2002 MontaVista Software Inc. +* +*/ +#ifndef __ARM_KGDB_H__ +#define __ARM_KGDB_H__ + +#define BREAK_INSTR_SIZE 4 +#define KGDB_COMPILED_BREAK 0xe7ffdeff + +#ifndef __ASSEMBLY__ + +static inline void arch_kgdb_breakpoint (void ) +{ + asm(".word 0xe7ffdeff" ); +} + +#endif /* !__ASSEMBLY__ */ + +/* +* From Kevin Hilman: +* +* gdb is expecting the following registers layout. +* +* r0-r15: 1 long word each +* f0-f7: unused, 3 long words each !! +* fps: unused, 1 long word +* cpsr: 1 long word +* +* Even though f0-f7 and fps are not used, they need to be +* present in the registers sent for correct processing in +* the host-side gdb. +* +* In particular, it is crucial that CPSR is in the right place, +* otherwise gdb will not be able to correctly interpret stepping over +* conditional branches. +*/ +#define _GP_REGS 16 +#define _FP_REGS 8 +#define _EXTRA_REGS 2 +#define GDB_MAX_REGS (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS) + +#define _R0 0 +#define _R1 1 +#define _R2 2 +#define _R3 3 +#define _R4 4 +#define _R5 5 +#define _R6 6 +#define _R7 7 +#define _R8 8 +#define _R9 9 +#define _R10 10 +#define _FP 11 +#define _IP 12 +#define _SPT 13 +#define _LR 14 +#define _PC 15 +#define _CPSR (GDB_MAX_REGS - 1) + +#endif /* __ASM_KGDB_H__ */ +
arch/arm/lib/Makefile +1 -0
@@ -44,6 +44,7 @@ COBJS-y += cache-cp15.o endif COBJS-y += interrupts.o COBJS-y += reset.o +COBJS-$(CONFIG_CMD_KGDB) += kgdb.o SRCS := $(GLSOBJS:.o=.S) $(GLCOBJS:.o=.c) \ $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
arch/arm/lib/kgdb.c new file +194 -0
194 lines not on this page · raw message
Signature · 1 line
1.6.0.6
PATCH v2 4/4 Add KGDB support for ARM platforms
In reply to Tonny Tzeng--- arch/arm/cpu/arm720t/start.S | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
arch/arm/cpu/arm720t/start.S +7 -0
@@ -459,6 +459,12 @@ lock_loop: mov r0, sp .endm + .macro bad_restore_user_regs + ldr lr, [sp, #S_PSR] @ Get SVC cpsr + msr spsr_cxsf, lr + ldmia sp, {r0 - pc}^ @ Restore SVC registers + .endm + .macro irq_save_user_regs sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0-r12
@@ -510,6 +516,7 @@ undefined_instruction: get_bad_stack bad_save_user_regs bl do_undefined_instruction + bad_restore_user_regs .align 5 software_interrupt:
Signature · 1 line
1.6.0.6
PATCH v2 2/4 Add KGDB support for ARM platforms
In reply to Tonny TzengI was looking at using this code for Marvell's ARM-like platform. Was this patch ever accepted in uboot? I don't see it in the current git tree.
Thanks!
Ben Baron
Oracle Development Engineer.
v2 cover Add KGDB support for ARM platforms
In reply to Tonny Tzengsplitting patches is good, but you cant use the same exact summary for each one with no changelog
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20100420/19a318ee/attachment.pgp