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
)
239 s32 min_id
,max_id
,first_id
;
242 if(thread
<=0) return NULL
;
244 if(thread
==1) return _thr_idle
;
247 objid
= _thr_executing
->object
.id
;
248 min_id
= _lwp_thr_objects
.min_id
;
249 max_id
= _lwp_thr_objects
.max_id
;
250 if(thread
<(first_id
+ (max_id
- min_id
))) {
251 th
= (lwp_cntrl
*)_lwp_thr_objects
.local_table
[thread
- first_id
];
257 s32
gdbstub_getcurrentthread()
259 return gdbstub_idtoindex(_thr_executing
->object
.id
);
262 s32
gdbstub_getnextthread(s32 athread
)
265 s32 first_id
,min_id
,max_id
,lim
;
267 if(athread
<1) return 1;
270 min_id
= _lwp_thr_objects
.min_id
;
271 max_id
= _lwp_thr_objects
.max_id
;
272 lim
= first_id
+ max_id
- min_id
;
279 for(id
=start
;id
<lim
;id
++)
280 if(_lwp_thr_objects
.local_table
[id
- first_id
]!=NULL
) return id
;
286 s32
gdbstub_getoffsets(char **textaddr
,char **dataaddr
,char **bssaddr
)
288 *textaddr
= (char*)((u32
)__text_fstart
- (u32
)__text_fstart
);
289 *dataaddr
= (char*)((u32
)__data_fstart
- (u32
)__text_fstart
);
290 *bssaddr
= (char*)((u32
)__bss_fstart
- (u32
)__text_fstart
);
295 s32
gdbstub_getthreadinfo(s32 thread
,struct gdbstub_threadinfo
*info
)
297 s32 first_id
,min_id
,max_id
;
301 if(thread
<=0) return 0;
304 strcpy(info
->display
,"idle thread");
305 strcpy(info
->name
,"IDLE");
306 info
->more_display
[0] = 0;
311 min_id
= _lwp_thr_objects
.min_id
;
312 max_id
= _lwp_thr_objects
.max_id
;
313 if(thread
<=(first_id
+ (max_id
- min_id
))){
314 th
= (lwp_cntrl
*)_lwp_thr_objects
.local_table
[thread
- first_id
];
315 if(th
==NULL
) return 0;
317 strcpy(info
->display
,"libogc task: control at: 0x");
318 tmp_buf
[0] = hexchars
[(((int)th
)>>28)&0x0f];
319 tmp_buf
[1] = hexchars
[(((int)th
)>>24)&0x0f];
320 tmp_buf
[2] = hexchars
[(((int)th
)>>20)&0x0f];
321 tmp_buf
[3] = hexchars
[(((int)th
)>>16)&0x0f];
322 tmp_buf
[4] = hexchars
[(((int)th
)>>12)&0x0f];
323 tmp_buf
[5] = hexchars
[(((int)th
)>>8)&0x0f];
324 tmp_buf
[6] = hexchars
[(((int)th
)>>4)&0x0f];
325 tmp_buf
[7] = hexchars
[((int)th
)&0x0f];
327 strcat(info
->display
,tmp_buf
);
335 info
->more_display
[0] = 0;
341 s32
parsezbreak(const char *in
,int *type
,char **addr
,int *len
)
346 if(!hstr2nibble(in
,&ttmp
) || *(in
+1)!=',') return 0;
349 in
= vhstr2int(in
,&atmp
);
350 if(in
==NULL
|| *in
!=',') return 0;
353 in
= vhstr2int(in
,<mp
);
354 if(in
==NULL
|| ltmp
<1) return 0;
363 s32
parseqp(const char *in
,s32
*mask
,s32
*thread
)
367 ptr
= fhstr2int(in
+2,mask
);
368 if(ptr
==NULL
) return 0;
370 ptr
= fhstr2thread(ptr
,thread
);
371 if(ptr
==NULL
) return 0;
376 void packqq(char *out
,s32 mask
,s32 thread
,struct gdbstub_threadinfo
*info
)
382 out
= int2fhstr(out
,mask
);
383 out
= thread2fhstr(out
,thread
);
386 memcpy(out
,"00000001",8);
390 out
= thread2fhstr(out
,thread
);
393 memcpy(out
,"00000002",8);
400 memcpy(out
,"00000004",8);
403 info
->display
[sizeof(info
->display
)-1] = 0; //for god sake
404 len
= strlen(info
->display
);
406 *out
++ = hexchars
[(len
>>4)&0x0f];
407 *out
++ = hexchars
[len
&0x0f];
409 memcpy(out
,info
->display
,len
);
413 memcpy(out
,"00000008",8);
416 info
->display
[sizeof(info
->name
)-1] = 0; //for god sake
417 len
= strlen(info
->name
);
419 *out
++ = hexchars
[(len
>>4)&0x0f];
420 *out
++ = hexchars
[len
&0x0f];
422 memcpy(out
,info
->name
,len
);
426 memcpy(out
,"00000010",8);
429 info
->display
[sizeof(info
->more_display
)-1] = 0; //for god sake
430 len
= strlen(info
->more_display
);
432 *out
++ = hexchars
[(len
>>4)&0x0f];
433 *out
++ = hexchars
[len
&0x0f];
435 memcpy(out
,info
->more_display
,len
);
441 s32
parseql(const char *in
,s32
*first
,s32
*max_cnt
,s32
*athread
)
446 if(!hstr2nibble(ptr
,first
)) return 0;
449 if(!hstr2byte(ptr
,max_cnt
)) return 0;
452 ptr
= fhstr2thread(ptr
,athread
);
453 if(ptr
==NULL
) return 0;
458 char* reserve_qmheader(char *out
)
463 char* packqmthread(char *out
,s32 thread
)
465 return thread2fhstr(out
,thread
);
468 void packqmheader(char *out
,s32 count
,s32 done
,s32 athread
)
472 *out
++ = hexchars
[(count
>>4)&0x0f];
473 *out
++ = hexchars
[count
&0x0f];
475 if(done
) *out
++ = '1';
478 thread2fhstr(out
,athread
);