10 #include "lwp_threads.h"
11 #include "sys_state.h"
17 #include "lwp_config.h"
22 #include "debug_supp.h"
24 #define GEKKO_MAX_BP 256
26 #define SP_REGNUM 1 //register no. for stackpointer
27 #define PC_REGNUM 64 //register no. for programcounter (srr0)
29 #define BUFMAX 2048 //we take the same as in ppc-stub.c
31 #define BPCODE 0x7d821008
33 #define highhex(x) hexchars [((x)>>4)&0xf]
34 #define lowhex(x) hexchars [(x)&0xf]
38 #define UIP_LOG(m) uip_log(__FILE__,__LINE__,m)
41 #endif /* UIP_LOGGING == 1 */
43 static s32 dbg_active
= 0;
44 static s32 dbg_instep
= 0;
45 static s32 dbg_initialized
= 0;
47 static struct dbginterface
*current_device
= NULL
;
49 static char remcomInBuffer
[BUFMAX
];
50 static char remcomOutBuffer
[BUFMAX
];
52 const char hexchars
[]="0123456789abcdef";
54 static struct hard_trap_info
{
57 } hard_trap_info
[] = {
58 {EX_MACH_CHECK
,SIGSEGV
},/* Machine Check */
59 {EX_DSI
,SIGSEGV
}, /* Adress Error(store) DSI */
60 {EX_ISI
,SIGBUS
}, /* Instruction Bus Error ISI */
61 {EX_INT
,SIGINT
}, /* Interrupt */
62 {EX_ALIGN
,SIGBUS
}, /* Alignment */
63 {EX_PRG
,SIGTRAP
}, /* Breakpoint Trap */
64 {EX_FP
,SIGFPE
}, /* FPU unavail */
65 {EX_DEC
,SIGALRM
}, /* Decrementer */
66 {EX_SYS_CALL
,SIGSYS
}, /* System Call */
67 {EX_TRACE
,SIGTRAP
}, /* Singel-Step/Watch */
68 {0xB,SIGILL
}, /* Reserved */
69 {EX_IABR
,SIGTRAP
}, /* Instruction Address Breakpoint (GEKKO) */
70 {0xD,SIGFPE
}, /* FP assist */
71 {0,0} /* MUST be the last */
74 static struct bp_entry
{
77 struct bp_entry
*next
;
78 } bp_entries
[GEKKO_MAX_BP
];
80 static struct bp_entry
*p_bpentries
= NULL
;
81 static frame_context current_thread_registers
;
84 void c_debug_handler(frame_context
*ctx
);
86 extern void dbg_exceptionhandler();
87 extern void __exception_sethandler(u32 nExcept
, void (*pHndl
)(frame_context
*));
89 extern void __clr_iabr();
90 extern void __enable_iabr();
91 extern void __disable_iabr();
92 extern void __set_iabr(void *);
94 extern const char *tcp_localip
;
95 extern const char *tcp_netmask
;
96 extern const char *tcp_gateway
;
97 extern u8 __text_start
[],__data_start
[],__bss_start
[];
98 extern u8 __text_fstart
[],__data_fstart
[],__bss_fstart
[];
100 static __inline__
void bp_init()
104 for(i
=0;i
<GEKKO_MAX_BP
;i
++) {
105 bp_entries
[i
].address
= NULL
;
106 bp_entries
[i
].instr
= 0xffffffff;
107 bp_entries
[i
].next
= NULL
;
111 static s32
hex(char ch
)
113 if (ch
>= 'a' && ch
<= 'f')
115 if (ch
>= '0' && ch
<= '9')
117 if (ch
>= 'A' && ch
<= 'F')
122 static s32
hexToInt(char **ptr
, s32
*ival
)
133 val
= (val
<<4)|nibble
;
142 static s32
computeSignal(s32 excpt
)
144 struct hard_trap_info
*ht
;
145 for(ht
= hard_trap_info
;ht
->tt
&& ht
->signo
;ht
++) {
146 if(ht
->tt
==excpt
) return ht
->signo
;
151 static u32
insert_bp(void *mem
)
156 for(i
=0;i
<GEKKO_MAX_BP
;i
++) {
157 if(bp_entries
[i
].address
== NULL
) break;
159 if(i
==GEKKO_MAX_BP
) return 0;
162 p
->next
= p_bpentries
;
166 p
->instr
= *(p
->address
);
167 *(p
->address
) = BPCODE
;
169 DCStoreRangeNoSync((void*)((u32
)mem
&~0x1f),32);
170 ICInvalidateRange((void*)((u32
)mem
&~0x1f),32);
176 static u32
remove_bp(void *mem
)
178 struct bp_entry
*e
= p_bpentries
;
179 struct bp_entry
*f
= NULL
;
182 if(e
->address
==mem
) {
183 p_bpentries
= e
->next
;
186 for(;e
->next
;e
=e
->next
) {
187 if(e
->next
->address
==mem
) {
196 *(f
->address
) = f
->instr
;
197 f
->instr
= 0xffffffff;
200 DCStoreRangeNoSync((void*)((u32
)mem
&~0x1f),32);
201 ICInvalidateRange((void*)((u32
)mem
&~0x1f),32);
207 static char getdbgchar()
212 len
= current_device
->read(current_device
,&ch
,1);
217 static void putdbgchar(char ch
)
219 current_device
->write(current_device
,&ch
,1);
222 static void putdbgstr(const char *str
)
224 current_device
->write(current_device
,str
,strlen(str
));
227 static void putpacket(const char *buffer
, bool wait
)
233 static char outbuf
[2048];
243 while((ch
=*inp
++)!='\0') {
249 *ptr
++ = hexchars
[chksum
>>4];
250 *ptr
++ = hexchars
[chksum
&0x0f];
259 } while((recv
&0x7f)!='+');
262 static void getpacket(char *buffer
)
269 while((ch
=(getdbgchar()&0x7f))!='$');
276 ch
= getdbgchar()&0x7f;
283 if(cnt
>=BUFMAX
) continue;
287 xmitsum
= hex(getdbgchar()&0x7f)<<4;
288 xmitsum
|= hex(getdbgchar()&0x7f);
290 if(chksum
!=xmitsum
) putdbgchar('-');
293 putdbgchar(buffer
[0]);
294 putdbgchar(buffer
[1]);
296 cnt
= strlen((const char*)buffer
);
297 for(i
=3;i
<=cnt
;i
++) buffer
[i
-3] = buffer
[i
];
301 } while(chksum
!=xmitsum
);
304 static void process_query(const char *inp
,char *outp
,s32 thread
)
313 optr
= thread2vhstr(optr
,thread
);
318 s32 ret
,rthread
,mask
;
319 struct gdbstub_threadinfo info
;
321 ret
= parseqp(inp
,&mask
,&rthread
);
322 if(!ret
|| mask
&~0x1f) {
327 ret
= gdbstub_getthreadinfo(rthread
,&info
);
332 packqq(outp
,mask
,rthread
,&info
);
337 s32 ret
,athread
,first
,max_cnt
,i
,done
,rthread
;
339 ret
= parseql(inp
,&first
,&max_cnt
,&athread
);
348 if(max_cnt
>QM_MAXTHREADS
) max_cnt
= QM_MAXTHREADS
;
350 optr
= reserve_qmheader(outp
);
351 if(first
) rthread
= 0;
352 else rthread
= athread
;
355 for(i
=0;i
<max_cnt
;i
++) {
356 rthread
= gdbstub_getnextthread(rthread
);
361 optr
= packqmthread(optr
,rthread
);
364 packqmheader(outp
,i
,done
,athread
);
372 static s32
gdbstub_setthreadregs(s32 thread
,frame_context
*frame
)
377 static s32
gdbstub_getthreadregs(s32 thread
,frame_context
*frame
)
381 th
= gdbstub_indextoid(thread
);
383 memcpy(frame
->GPR
,th
->context
.GPR
,(32*4));
384 memcpy(frame
->FPR
,th
->context
.FPR
,(32*8));
385 frame
->SRR0
= th
->context
.LR
;
386 frame
->SRR1
= th
->context
.MSR
;
387 frame
->CR
= th
->context
.CR
;
388 frame
->LR
= th
->context
.LR
;
389 frame
->CTR
= th
->context
.CTR
;
390 frame
->XER
= th
->context
.XER
;
391 frame
->FPSCR
= th
->context
.FPSCR
;
397 static void gdbstub_report_exception(frame_context
*frame
,s32 thread
)
402 ptr
= remcomOutBuffer
;
403 sigval
= computeSignal(frame
->EXCPT_Number
);
405 *ptr
++ = highhex(sigval
);
406 *ptr
++ = lowhex(sigval
);
407 *ptr
++ = highhex(SP_REGNUM
);
408 *ptr
++ = lowhex(SP_REGNUM
);
410 ptr
= mem2hstr(ptr
,(char*)&frame
->GPR
[1],4);
412 *ptr
++ = highhex(PC_REGNUM
);
413 *ptr
++ = lowhex(PC_REGNUM
);
415 ptr
= mem2hstr(ptr
,(char*)&frame
->SRR0
,4);
425 ptr
= thread2vhstr(ptr
,thread
);
433 void c_debug_handler(frame_context
*frame
)
437 s32 thread
,current_thread
;
438 s32 host_has_detached
;
439 frame_context
*regptr
;
442 thread
= gdbstub_getcurrentthread();
443 current_thread
= thread
;
445 if(current_device
->open(current_device
)<0) return;
448 gdbstub_report_exception(frame
,thread
);
449 putpacket(remcomOutBuffer
, true);
452 if(frame
->SRR0
==(u32
)__breakinst
) frame
->SRR0
+= 4;
454 host_has_detached
= 0;
455 while(!host_has_detached
) {
457 remcomOutBuffer
[0]= 0;
458 getpacket(remcomInBuffer
);
459 switch(remcomInBuffer
[0]) {
461 gdbstub_report_exception(frame
,thread
);
466 frame
->SRR1
&= ~MSR_SE
;
467 strcpy(remcomOutBuffer
,"OK");
468 host_has_detached
= 1;
473 frame
->SRR1
&= ~MSR_SE
;
474 frame
->SRR0
= 0x80001800;
475 host_has_detached
= 1;
480 ptr
= remcomOutBuffer
;
481 if(current_thread
!=thread
) regptr
= ¤t_thread_registers
;
483 ptr
= mem2hstr(ptr
,(char*)regptr
->GPR
,32*4);
484 ptr
= mem2hstr(ptr
,(char*)regptr
->FPR
,32*8);
485 ptr
= mem2hstr(ptr
,(char*)®ptr
->SRR0
,4);
486 ptr
= mem2hstr(ptr
,(char*)®ptr
->SRR1
,4);
487 ptr
= mem2hstr(ptr
,(char*)®ptr
->CR
,4);
488 ptr
= mem2hstr(ptr
,(char*)®ptr
->LR
,4);
489 ptr
= mem2hstr(ptr
,(char*)®ptr
->CTR
,4);
490 ptr
= mem2hstr(ptr
,(char*)®ptr
->XER
,4);
491 ptr
= mem2hstr(ptr
,(char*)®ptr
->FPSCR
,4);
494 ptr
= &remcomInBuffer
[1];
495 if(hexToInt(&ptr
,&addr
) && ((addr
&0xC0000000)==0xC0000000 || (addr
&0xC0000000)==0x80000000)
497 && hexToInt(&ptr
,&len
) && len
<=((BUFMAX
- 4)/2))
498 mem2hstr(remcomOutBuffer
,(void*)addr
,len
);
500 strcpy(remcomOutBuffer
,"E00");
503 process_query(remcomInBuffer
,remcomOutBuffer
,thread
);
508 frame
->SRR1
&= ~MSR_SE
;
509 current_device
->wait(current_device
);
514 frame
->SRR1
|= MSR_SE
;
515 current_device
->wait(current_device
);
522 ret
= parsezbreak(remcomInBuffer
,&type
,&addr
,&len
);
524 strcpy(remcomOutBuffer
,"E01");
530 strcpy(remcomOutBuffer
,"E02");
534 ret
= remove_bp(addr
);
536 strcpy(remcomOutBuffer
,"E03");
539 strcpy(remcomOutBuffer
,"OK");
543 if(remcomInBuffer
[1]=='g')
547 if(vhstr2thread(&remcomInBuffer
[2],&tmp
)==NULL
) {
548 strcpy(remcomOutBuffer
,"E01");
551 if(!tmp
) tmp
= thread
;
552 if(tmp
==current_thread
) {
553 strcpy(remcomOutBuffer
,"OK");
557 if(current_thread
!=thread
) ret
= gdbstub_setthreadregs(current_thread
,¤t_thread_registers
);
559 ret
= gdbstub_getthreadregs(tmp
,¤t_thread_registers
);
561 strcpy(remcomOutBuffer
,"E02");
567 strcpy(remcomOutBuffer
,"OK");
573 if(vhstr2thread(&remcomInBuffer
[1],&tmp
)==NULL
) {
574 strcpy(remcomOutBuffer
,"E01");
577 if(gdbstub_indextoid(tmp
)==NULL
) strcpy(remcomOutBuffer
,"E02");
578 else strcpy(remcomOutBuffer
,"OK");
586 ret
= parsezbreak(remcomInBuffer
,&type
,&addr
,&len
);
588 strcpy(remcomOutBuffer
,"E01");
592 strcpy(remcomOutBuffer
,"E02");
596 strcpy(remcomOutBuffer
,"E03");
600 ret
= insert_bp(addr
);
602 strcpy(remcomOutBuffer
,"E04");
605 strcpy(remcomOutBuffer
,"OK");
609 putpacket(remcomOutBuffer
, wait
);
611 current_device
->close(current_device
);
618 if(!dbg_initialized
) return;
619 __asm__
__volatile__ (".globl __breakinst\n\
620 __breakinst: .long 0x7d821008");
623 void DEBUG_Init(s32 device_type
,s32 channel_port
)
626 struct uip_ip_addr localip
,netmask
,gateway
;
628 UIP_LOG("DEBUG_Init()\n");
630 __lwp_thread_dispatchdisable();
634 if(device_type
==GDBSTUB_DEVICE_USB
) {
635 current_device
= usb_init(channel_port
);
637 localip
.addr
= uip_ipaddr((const u8_t
*)tcp_localip
);
638 netmask
.addr
= uip_ipaddr((const u8_t
*)tcp_netmask
);
639 gateway
.addr
= uip_ipaddr((const u8_t
*)tcp_gateway
);
641 current_device
= tcpip_init(&localip
,&netmask
,&gateway
,(u16
)channel_port
);
644 if(current_device
!=NULL
) {
645 _CPU_ISR_Disable(level
);
646 __exception_sethandler(EX_DSI
,dbg_exceptionhandler
);
647 __exception_sethandler(EX_PRG
,dbg_exceptionhandler
);
648 __exception_sethandler(EX_TRACE
,dbg_exceptionhandler
);
649 __exception_sethandler(EX_IABR
,dbg_exceptionhandler
);
650 _CPU_ISR_Restore(level
);
655 __lwp_thread_dispatchenable();