6 #include "lwp_threads.h"
7 #include "debug_supp.h"
9 extern lwp_objinfo _lwp_cond_objects
;
10 extern lwp_objinfo _lwp_thr_objects
;
11 extern lwp_objinfo _lwp_tqueue_objects
;
12 extern lwp_objinfo _lwp_mqbox_objects
;
13 extern lwp_objinfo _lwp_mutex_objects
;
14 extern lwp_objinfo _lwp_sema_objects
;
16 extern const u8 hexchars
[];
18 extern u8 __text_start
[],__data_start
[],__bss_start
[];
19 extern u8 __text_fstart
[],__data_fstart
[],__bss_fstart
[];
21 s32
hstr2nibble(const char *buf
,s32
*nibble
)
26 if(ch
>='0' && ch
<='9') {
30 if(ch
>='a' && ch
<='f') {
31 *nibble
= ch
- 'a' + 10;
34 if(ch
>='A' && ch
<='F') {
35 *nibble
= ch
- 'A' + 10;
41 s32
hstr2byte(const char *buf
,s32
*bval
)
45 if(!hstr2nibble(buf
,&hnib
) || !hstr2nibble(buf
+1,&lnib
)) return 0;
47 *bval
= (hnib
<<4)|lnib
;
51 const char* vhstr2int(const char *buf
,s32
*ival
)
57 for(i
=0;i
<8;i
++,buf
++) {
65 for(i
=0;i
<lim
;i
++,buf
++) {
66 if(!hstr2nibble(buf
,&nibble
)) {
67 if(i
==0 && !found0
) return NULL
;
72 val
= (val
<<4)|nibble
;
74 if(hstr2nibble(buf
,&nibble
)) return NULL
;
80 const char* fhstr2int(const char *buf
,s32
*ival
)
85 for(i
=0;i
<8;i
++,buf
++) {
86 if(!hstr2nibble(buf
,&nibble
)) return NULL
;
88 val
= (val
<<4)|nibble
;
95 char* int2fhstr(char *buf
,s32 val
)
99 for(i
=0,shift
=28;i
<8;i
++,shift
-=4,buf
++) {
100 nibble
= (val
>>shift
)&0x0f;
101 *buf
= hexchars
[nibble
];
106 char* int2vhstr(char *buf
,s32 val
)
110 for(i
=0,shift
=28;i
<8;i
++,shift
-=4) {
111 nibble
= (val
>>shift
)&0x0f;
119 *buf
++ = hexchars
[nibble
];
120 for(i
++,shift
-=4;i
<8;i
++,shift
-=4,buf
++) {
121 nibble
= (val
>>shift
)&0x0f;
122 *buf
= hexchars
[nibble
];
127 char* mem2hstr(char *buf
,const char *mem
,s32 count
)
132 for(i
=0;i
<count
;i
++,mem
++) {
134 *buf
++ = hexchars
[ch
>>4];
135 *buf
++ = hexchars
[ch
&0x0f];
140 char* thread2fhstr(char *buf
,s32 thread
)
144 for(i
=0;i
<8;i
++,buf
++) *buf
= '0';
145 for(i
=0,shift
=28;i
<8;i
++,shift
-=4,buf
++) {
146 nibble
= (thread
>>shift
)&0x0f;
147 *buf
= hexchars
[nibble
];
152 char* thread2vhstr(char *buf
,s32 thread
)
156 for(i
=0,shift
=28;i
<8;i
++,shift
-=4) {
157 nibble
= (thread
>>shift
)&0x0f;
165 *buf
++ = hexchars
[nibble
];
166 for(i
++,shift
-=4;i
<8;i
++,shift
-=4,buf
++) {
167 nibble
= (thread
>>shift
)&0x0f;
168 *buf
= hexchars
[nibble
];
173 const char* fhstr2thread(const char *buf
,s32
*thread
)
177 for(i
=0;i
<8;i
++,buf
++)
178 if(*buf
!='0') return NULL
;
181 for(i
=0;i
<8;i
++,buf
++) {
182 if(!hstr2nibble(buf
,&nibble
)) return NULL
;
184 val
= (val
<<4)|nibble
;
191 const char* vhstr2thread(const char *buf
,s32
*thread
)
197 for(i
=0;i
<16;i
++,buf
++) {
205 for(i
=0;i
<lim
;i
++,buf
++) {
206 if(!hstr2nibble(buf
,&nibble
)) {
207 if(i
==0 && found0
) return NULL
;
213 val
= (val
<<4)|nibble
;
215 if(hstr2nibble(buf
,&nibble
)) return NULL
;
221 s32
gdbstub_idtoindex(s32 objid
)
226 if(_thr_executing
==_thr_idle
) return 1;
229 min_id
= _lwp_thr_objects
.min_id
;
230 max_id
= _lwp_thr_objects
.max_id
;
231 if(objid
>=min_id
&& objid
<max_id
) return first_id
+ (objid
- min_id
);
236 lwp_cntrl
* gdbstub_indextoid(s32 thread
)
238 s32 min_id
,max_id
,first_id
;
241 if(thread
<=0) return NULL
;
243 if(thread
==1) return _thr_idle
;
246 min_id
= _lwp_thr_objects
.min_id
;
247 max_id
= _lwp_thr_objects
.max_id
;
248 if(thread
<(first_id
+ (max_id
- min_id
))) {
249 th
= (lwp_cntrl
*)_lwp_thr_objects
.local_table
[thread
- first_id
];
255 s32
gdbstub_getcurrentthread()
257 return gdbstub_idtoindex(_thr_executing
->object
.id
);
260 s32
gdbstub_getnextthread(s32 athread
)
263 s32 first_id
,min_id
,max_id
,lim
;
265 if(athread
<1) return 1;
268 min_id
= _lwp_thr_objects
.min_id
;
269 max_id
= _lwp_thr_objects
.max_id
;
270 lim
= first_id
+ max_id
- min_id
;
277 for(id
=start
;id
<lim
;id
++)
278 if(_lwp_thr_objects
.local_table
[id
- first_id
]!=NULL
) return id
;
284 s32
gdbstub_getoffsets(char **textaddr
,char **dataaddr
,char **bssaddr
)
286 *textaddr
= (char*)((u32
)__text_fstart
- (u32
)__text_fstart
);
287 *dataaddr
= (char*)((u32
)__data_fstart
- (u32
)__text_fstart
);
288 *bssaddr
= (char*)((u32
)__bss_fstart
- (u32
)__text_fstart
);
293 s32
gdbstub_getthreadinfo(s32 thread
,struct gdbstub_threadinfo
*info
)
295 s32 first_id
,min_id
,max_id
;
299 if(thread
<=0) return 0;
302 strcpy(info
->display
,"idle thread");
303 strcpy(info
->name
,"IDLE");
304 info
->more_display
[0] = 0;
309 min_id
= _lwp_thr_objects
.min_id
;
310 max_id
= _lwp_thr_objects
.max_id
;
311 if(thread
<=(first_id
+ (max_id
- min_id
))){
312 th
= (lwp_cntrl
*)_lwp_thr_objects
.local_table
[thread
- first_id
];
313 if(th
==NULL
) return 0;
315 strcpy(info
->display
,"libogc task: control at: 0x");
316 tmp_buf
[0] = hexchars
[(((int)th
)>>28)&0x0f];
317 tmp_buf
[1] = hexchars
[(((int)th
)>>24)&0x0f];
318 tmp_buf
[2] = hexchars
[(((int)th
)>>20)&0x0f];
319 tmp_buf
[3] = hexchars
[(((int)th
)>>16)&0x0f];
320 tmp_buf
[4] = hexchars
[(((int)th
)>>12)&0x0f];
321 tmp_buf
[5] = hexchars
[(((int)th
)>>8)&0x0f];
322 tmp_buf
[6] = hexchars
[(((int)th
)>>4)&0x0f];
323 tmp_buf
[7] = hexchars
[((int)th
)&0x0f];
325 strcat(info
->display
,tmp_buf
);
333 info
->more_display
[0] = 0;
339 s32
parsezbreak(const char *in
,int *type
,char **addr
,int *len
)
344 if(!hstr2nibble(in
,&ttmp
) || *(in
+1)!=',') return 0;
347 in
= vhstr2int(in
,&atmp
);
348 if(in
==NULL
|| *in
!=',') return 0;
351 in
= vhstr2int(in
,<mp
);
352 if(in
==NULL
|| ltmp
<1) return 0;
361 s32
parseqp(const char *in
,s32
*mask
,s32
*thread
)
365 ptr
= fhstr2int(in
+2,mask
);
366 if(ptr
==NULL
) return 0;
368 ptr
= fhstr2thread(ptr
,thread
);
369 if(ptr
==NULL
) return 0;
374 void packqq(char *out
,s32 mask
,s32 thread
,struct gdbstub_threadinfo
*info
)
380 out
= int2fhstr(out
,mask
);
381 out
= thread2fhstr(out
,thread
);
384 memcpy(out
,"00000001",8);
388 out
= thread2fhstr(out
,thread
);
391 memcpy(out
,"00000002",8);
398 memcpy(out
,"00000004",8);
401 info
->display
[sizeof(info
->display
)-1] = 0; //for god sake
402 len
= strlen(info
->display
);
404 *out
++ = hexchars
[(len
>>4)&0x0f];
405 *out
++ = hexchars
[len
&0x0f];
407 memcpy(out
,info
->display
,len
);
411 memcpy(out
,"00000008",8);
414 info
->display
[sizeof(info
->name
)-1] = 0; //for god sake
415 len
= strlen(info
->name
);
417 *out
++ = hexchars
[(len
>>4)&0x0f];
418 *out
++ = hexchars
[len
&0x0f];
420 memcpy(out
,info
->name
,len
);
424 memcpy(out
,"00000010",8);
427 info
->display
[sizeof(info
->more_display
)-1] = 0; //for god sake
428 len
= strlen(info
->more_display
);
430 *out
++ = hexchars
[(len
>>4)&0x0f];
431 *out
++ = hexchars
[len
&0x0f];
433 memcpy(out
,info
->more_display
,len
);
439 s32
parseql(const char *in
,s32
*first
,s32
*max_cnt
,s32
*athread
)
444 if(!hstr2nibble(ptr
,first
)) return 0;
447 if(!hstr2byte(ptr
,max_cnt
)) return 0;
450 ptr
= fhstr2thread(ptr
,athread
);
451 if(ptr
==NULL
) return 0;
456 char* reserve_qmheader(char *out
)
461 char* packqmthread(char *out
,s32 thread
)
463 return thread2fhstr(out
,thread
);
466 void packqmheader(char *out
,s32 count
,s32 done
,s32 athread
)
470 *out
++ = hexchars
[(count
>>4)&0x0f];
471 *out
++ = hexchars
[count
&0x0f];
473 if(done
) *out
++ = '1';
476 thread2fhstr(out
,athread
);