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
)
233 static char outbuf
[2048];
242 while((ch
=*inp
++)!='\0') {
248 *ptr
++ = hexchars
[chksum
>>4];
249 *ptr
++ = hexchars
[chksum
&0x0f];
255 } while((recv
&0x7f)!='+');
258 static void getpacket(char *buffer
)
265 while((ch
=(getdbgchar()&0x7f))!='$');
272 ch
= getdbgchar()&0x7f;
279 if(cnt
>=BUFMAX
) continue;
283 xmitsum
= hex(getdbgchar()&0x7f)<<4;
284 xmitsum
|= hex(getdbgchar()&0x7f);
286 if(chksum
!=xmitsum
) putdbgchar('-');
290 putdbgchar(buffer
[0]);
291 putdbgchar(buffer
[1]);
293 cnt
= strlen((const char*)buffer
);
294 for(i
=3;i
<=cnt
;i
++) buffer
[i
-3] = buffer
[i
];
298 } while(chksum
!=xmitsum
);
301 static void process_query(const char *inp
,char *outp
,s32 thread
)
310 optr
= thread2vhstr(optr
,thread
);
315 s32 ret
,rthread
,mask
;
316 struct gdbstub_threadinfo info
;
318 ret
= parseqp(inp
,&mask
,&rthread
);
319 if(!ret
|| mask
&~0x1f) {
324 ret
= gdbstub_getthreadinfo(rthread
,&info
);
329 packqq(outp
,mask
,rthread
,&info
);
334 s32 ret
,athread
,first
,max_cnt
,i
,done
,rthread
;
336 ret
= parseql(inp
,&first
,&max_cnt
,&athread
);
345 if(max_cnt
>QM_MAXTHREADS
) max_cnt
= QM_MAXTHREADS
;
347 optr
= reserve_qmheader(outp
);
348 if(first
) rthread
= 0;
349 else rthread
= athread
;
352 for(i
=0;i
<max_cnt
;i
++) {
353 rthread
= gdbstub_getnextthread(rthread
);
358 optr
= packqmthread(optr
,rthread
);
361 packqmheader(outp
,i
,done
,athread
);
369 static s32
gdbstub_setthreadregs(s32 thread
,frame_context
*frame
)
374 static s32
gdbstub_getthreadregs(s32 thread
,frame_context
*frame
)
378 th
= gdbstub_indextoid(thread
);
380 memcpy(frame
->GPR
,th
->context
.GPR
,(32*4));
381 memcpy(frame
->FPR
,th
->context
.FPR
,(32*8));
382 frame
->SRR0
= th
->context
.LR
;
383 frame
->SRR1
= th
->context
.MSR
;
384 frame
->CR
= th
->context
.CR
;
385 frame
->LR
= th
->context
.LR
;
386 frame
->CTR
= th
->context
.CTR
;
387 frame
->XER
= th
->context
.XER
;
388 frame
->FPSCR
= th
->context
.FPSCR
;
394 static void gdbstub_report_exception(frame_context
*frame
,s32 thread
)
399 ptr
= remcomOutBuffer
;
400 sigval
= computeSignal(frame
->EXCPT_Number
);
402 *ptr
++ = highhex(sigval
);
403 *ptr
++ = lowhex(sigval
);
404 *ptr
++ = highhex(SP_REGNUM
);
405 *ptr
++ = lowhex(SP_REGNUM
);
407 ptr
= mem2hstr(ptr
,(char*)&frame
->GPR
[1],4);
409 *ptr
++ = highhex(PC_REGNUM
);
410 *ptr
++ = lowhex(PC_REGNUM
);
412 ptr
= mem2hstr(ptr
,(char*)&frame
->SRR0
,4);
422 ptr
= thread2vhstr(ptr
,thread
);
430 void c_debug_handler(frame_context
*frame
)
434 s32 thread
,current_thread
;
435 s32 host_has_detached
;
436 frame_context
*regptr
;
438 thread
= gdbstub_getcurrentthread();
439 current_thread
= thread
;
441 if(current_device
->open(current_device
)<0) return;
444 gdbstub_report_exception(frame
,thread
);
445 putpacket(remcomOutBuffer
);
448 if(frame
->SRR0
==(u32
)__breakinst
) frame
->SRR0
+= 4;
450 host_has_detached
= 0;
451 while(!host_has_detached
) {
452 remcomOutBuffer
[0]= 0;
453 getpacket(remcomInBuffer
);
454 switch(remcomInBuffer
[0]) {
456 gdbstub_report_exception(frame
,thread
);
461 frame
->SRR1
&= ~MSR_SE
;
462 strcpy(remcomOutBuffer
,"OK");
463 host_has_detached
= 1;
468 frame
->SRR1
&= ~MSR_SE
;
469 frame
->SRR0
= 0x80001800;
470 host_has_detached
= 1;
474 ptr
= remcomOutBuffer
;
475 if(current_thread
!=thread
) regptr
= ¤t_thread_registers
;
477 ptr
= mem2hstr(ptr
,(char*)regptr
->GPR
,32*4);
478 ptr
= mem2hstr(ptr
,(char*)regptr
->FPR
,32*8);
479 ptr
= mem2hstr(ptr
,(char*)®ptr
->SRR0
,4);
480 ptr
= mem2hstr(ptr
,(char*)®ptr
->SRR1
,4);
481 ptr
= mem2hstr(ptr
,(char*)®ptr
->CR
,4);
482 ptr
= mem2hstr(ptr
,(char*)®ptr
->LR
,4);
483 ptr
= mem2hstr(ptr
,(char*)®ptr
->CTR
,4);
484 ptr
= mem2hstr(ptr
,(char*)®ptr
->XER
,4);
485 ptr
= mem2hstr(ptr
,(char*)®ptr
->FPSCR
,4);
488 ptr
= &remcomInBuffer
[1];
489 if(hexToInt(&ptr
,&addr
) && ((addr
&0xC0000000)==0xC0000000 || (addr
&0xC0000000)==0x80000000)
491 && hexToInt(&ptr
,&len
) && len
<=((BUFMAX
- 4)/2))
492 mem2hstr(remcomOutBuffer
,(void*)addr
,len
);
494 strcpy(remcomOutBuffer
,"E00");
497 process_query(remcomInBuffer
,remcomOutBuffer
,thread
);
502 frame
->SRR1
&= ~MSR_SE
;
503 current_device
->wait(current_device
);
508 frame
->SRR1
|= MSR_SE
;
509 current_device
->wait(current_device
);
516 ret
= parsezbreak(remcomInBuffer
,&type
,&addr
,&len
);
518 strcpy(remcomOutBuffer
,"E01");
524 strcpy(remcomOutBuffer
,"E02");
528 ret
= remove_bp(addr
);
530 strcpy(remcomOutBuffer
,"E03");
533 strcpy(remcomOutBuffer
,"OK");
537 if(remcomInBuffer
[1]=='g')
541 if(vhstr2thread(&remcomInBuffer
[2],&tmp
)==NULL
) {
542 strcpy(remcomOutBuffer
,"E01");
545 if(!tmp
) tmp
= thread
;
546 if(tmp
==current_thread
) {
547 strcpy(remcomOutBuffer
,"OK");
551 if(current_thread
!=thread
) ret
= gdbstub_setthreadregs(current_thread
,¤t_thread_registers
);
553 ret
= gdbstub_getthreadregs(tmp
,¤t_thread_registers
);
555 strcpy(remcomOutBuffer
,"E02");
561 strcpy(remcomOutBuffer
,"OK");
567 if(vhstr2thread(&remcomInBuffer
[1],&tmp
)==NULL
) {
568 strcpy(remcomOutBuffer
,"E01");
571 if(gdbstub_indextoid(tmp
)==NULL
) strcpy(remcomOutBuffer
,"E02");
572 else strcpy(remcomOutBuffer
,"OK");
580 ret
= parsezbreak(remcomInBuffer
,&type
,&addr
,&len
);
582 strcpy(remcomOutBuffer
,"E01");
586 strcpy(remcomOutBuffer
,"E02");
590 strcpy(remcomOutBuffer
,"E03");
594 ret
= insert_bp(addr
);
596 strcpy(remcomOutBuffer
,"E04");
599 strcpy(remcomOutBuffer
,"OK");
603 putpacket(remcomOutBuffer
);
605 current_device
->close(current_device
);
612 if(!dbg_initialized
) return;
613 __asm__
__volatile__ (".globl __breakinst\n\
614 __breakinst: .long 0x7d821008");
617 void DEBUG_Init(s32 device_type
,s32 channel_port
)
620 struct uip_ip_addr localip
,netmask
,gateway
;
622 UIP_LOG("DEBUG_Init()\n");
624 __lwp_thread_dispatchdisable();
628 if(device_type
==GDBSTUB_DEVICE_USB
) {
629 current_device
= usb_init(channel_port
);
631 localip
.addr
= uip_ipaddr((const u8_t
*)tcp_localip
);
632 netmask
.addr
= uip_ipaddr((const u8_t
*)tcp_netmask
);
633 gateway
.addr
= uip_ipaddr((const u8_t
*)tcp_gateway
);
635 current_device
= tcpip_init(&localip
,&netmask
,&gateway
,(u16
)channel_port
);
638 if(current_device
!=NULL
) {
639 _CPU_ISR_Disable(level
);
640 __exception_sethandler(EX_DSI
,dbg_exceptionhandler
);
641 __exception_sethandler(EX_PRG
,dbg_exceptionhandler
);
642 __exception_sethandler(EX_TRACE
,dbg_exceptionhandler
);
643 __exception_sethandler(EX_IABR
,dbg_exceptionhandler
);
644 _CPU_ISR_Restore(level
);
649 __lwp_thread_dispatchenable();