picture.datatype: gi_RastPort should not be directly accessed
[AROS.git] / rom / exec / debug.c
blob50a10833183e86f1a777e2856172a7a1def561dc
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Internal debugger.
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <exec/interrupts.h>
11 #include <libraries/debug.h>
12 #include <proto/exec.h>
13 #include <proto/kernel.h>
14 #include <proto/debug.h>
16 #include <ctype.h>
17 #include <string.h>
19 #include "exec_intern.h"
21 /****************************************************************************************/
23 char GetK();
24 UQUAD GetQ(char *);
25 ULONG GetL(char *);
26 UWORD GetW(char *);
27 UBYTE GetB(char *);
28 int get_irq_list(char *buf);
30 #if __WORDSIZE == 64
31 #define GetA (APTR)GetQ
32 #else
33 #define GetA (APTR)GetL
34 #endif
36 /****************************************************************************************/
38 static char *NextWord(char *s)
40 /* Skip to first space or EOL */
41 while (*s != ' ')
43 if (!*s)
44 return s;
45 s++;
48 /* Then skip to first non-space */
49 while (*++s == ' ');
51 return s;
54 /*****************************************************************************
56 NAME */
58 AROS_LH1(void, Debug,
60 /* SYNOPSIS */
61 AROS_LHA(unsigned long, flags, D0),
63 /* LOCATION */
64 struct ExecBase *, SysBase, 19, Exec)
66 /* FUNCTION
67 Runs SAD - internal debuger.
69 INPUTS
70 flags not used. Should be 0 now.
72 RESULT
74 NOTES
76 EXAMPLE
78 BUGS
80 SEE ALSO
82 INTERNALS
84 HISTORY
85 18-01-99 initial PC version.
87 *****************************************************************************/
89 AROS_LIBFUNC_INIT
91 char comm[128];
92 char *data;
93 BOOL ignorelf = FALSE;
95 #ifdef KrnObtainInput
97 * Try to obtain debug input from the kernel.
98 * If it failed, we will hang up in RawMayGetChar(), so exit immediately.
100 if (!KrnObtainInput())
101 return;
102 #endif
104 RawIOInit();
106 for (;;)
108 int i = 0;
110 kprintf("SAD(%d,%d)>", SysBase->TDNestCnt, SysBase->IDNestCnt);
112 /* Get Command code */
115 char key = GetK(SysBase);
116 BOOL t = ignorelf;
118 /* We skip only single LF which immediately follows the CR. So we remember
119 previous value of the flag and reset it when any character arrives. */
120 ignorelf = FALSE;
121 if (key == '\n') {
122 if (t)
123 continue;
124 else
125 break;
128 /* TABs are problematic to deal with, we ignore them */
129 else if (key == 0x09)
130 continue;
132 /* If we've just got CR, we may get LF next and we'll need to skip it */
133 else if (key == '\r') {
134 ignorelf = TRUE;
135 break;
138 /* Process backspace */
139 else if (key == 0x08)
141 if (i > 0) {
142 /* Go backwards, erase the character, then go backwards again */
143 RawPutChar(key);
144 RawPutChar(' ');
145 RawPutChar(key);
146 i--;
148 continue;
151 RawPutChar(key);
152 comm[i++] = key;
154 while (i < (int)sizeof(comm)-1);
155 comm[i] = 0;
156 RawPutChar('\n');
158 /* Now get data for command */
159 data = NextWord(comm);
160 comm[2] = 0;
162 /* Reboot command */
163 if (strcmp(comm, "RE") == 0 && strcmp(data, "AAAAAAAA") == 0)
164 ColdReboot();
165 /* Restart command */
166 else if (strcmp(comm, "RS") == 0 && strcmp(data, "FFFFFFFF") == 0)
167 ShutdownA(SD_ACTION_COLDREBOOT);
168 /* Forbid command */
169 else if (strcmp(comm, "FO") == 0)
170 Forbid();
171 /* Permit command */
172 else if (strcmp(comm, "PE") == 0)
173 Permit();
174 /* Disable command */
175 else if (strcmp(comm, "DI") == 0)
176 Disable();
177 /* Show active task information */
178 else if (strcmp(comm, "TI") == 0)
180 struct Task *t = SysBase->ThisTask;
182 kprintf("Active task (%p = '%s'):\n"
183 "tc_Node.ln_Pri = %d\n"
184 "tc_SigAlloc = %04.4lx\n"
185 "tc_SPLower = %p\n"
186 "tc_SPUpper = %p\n"
187 "tc_Flags = %p\n"
188 "tc_SPReg = %p\n",
189 t, t->tc_Node.ln_Name,
190 t->tc_Node.ln_Pri,
191 t->tc_SigAlloc,
192 t->tc_SPLower,
193 t->tc_SPUpper,
194 t->tc_Flags,
195 t->tc_SPReg);
197 else if (strcmp(comm,"RI") == 0)
200 * TODO: this function is not useful at all in its current implementation.
201 * When the task is running its context is not valid. It would be much better
202 * to be able to examine contexts of other tasks.
203 * I left this here for demonstration purposes.
205 * 24.12.2010: reference to kernel.resource's private includes is removed,
206 * so PRINT_CPU_CONTEXT is not defined at all. Exec needs some CPU-specific
207 * .c file where all CPU-dependent functionality needs to be gathered. This
208 * is going to include full CPU context dump, stack trace, etc.
210 #ifdef PRINT_CPU_CONTEXT
211 struct ExceptionContext *r = SysBase->ThisTask->tc_UnionETask.tc_ETask->et_RegFrame;
213 PRINT_CPU_CONTEXT(r);
214 #else
215 kprintf("Not implemented on this platform.\n");
216 #endif
218 /* Enable command */
219 else if (strcmp(comm, "EN") == 0)
220 Enable();
221 /* ShowLibs command */
222 else if (strcmp(comm, "SL") == 0)
224 struct Node * node;
226 kprintf("Available libraries:\n");
228 /* Look through the list */
229 for (node = GetHead(&SysBase->LibList); node; node = GetSucc(node))
231 kprintf("0x%p : %s\n", node, node->ln_Name);
234 else if (strcmp(comm, "SI") == 0)
236 /* char buf[512];
238 kprintf("Available interrupts:\n");
240 get_irq_list(&buf);
241 kprintf(buf);*/
242 kprintf("Not implemented\n");
244 /* ShowResources command */
245 else if (strcmp(comm, "SR") == 0)
247 struct Node * node;
249 kprintf("Available resources:\n");
251 /* Look through the list */
252 for (node = GetHead(&SysBase->ResourceList); node; node = GetSucc(node))
254 kprintf("0x%p : %s\n", node, node->ln_Name);
257 /* ShowDevices command */
258 else if (strcmp(comm,"SD") == 0)
260 struct Node * node;
262 kprintf("Available devices:\n");
264 /* Look through the list */
265 for (node=GetHead(&SysBase->DeviceList); node; node = GetSucc(node))
267 kprintf("0x%p : %s\n", node, node->ln_Name);
270 /* ShowTasks command */
271 else if (strcmp(comm, "ST") == 0)
273 struct Node * node;
275 kprintf("Task List:\n");
277 kprintf("0x%p T %d %s\n",SysBase->ThisTask,
278 SysBase->ThisTask->tc_Node.ln_Pri,
279 SysBase->ThisTask->tc_Node.ln_Name);
281 /* Look through the list */
282 for (node = GetHead(&SysBase->TaskReady); node; node = GetSucc(node))
284 kprintf("0x%p R %d %s\n", node, node->ln_Pri, node->ln_Name);
287 for (node = GetHead(&SysBase->TaskWait); node; node = GetSucc(node))
289 kprintf("0x%p W %d %s\n", node, node->ln_Pri, node->ln_Name);
292 kprintf("Idle called %d times\n", SysBase->IdleCount);
294 /* Help command */
295 else if (strcmp(comm, "HE") == 0)
297 kprintf("SAD Help:\n");
298 kprintf("RE AAAAAAAA - reboots AROS - ColdReboot()\n"
299 "RS FFFFFFFF - RESET\n"
300 "FO - Forbid()\n"
301 "PE - Permit()\n"
302 "DI - Disable()\n"
303 "EN - Enable()\n"
304 "SI - Show IRQ lines status\n"
305 "TI - Show Active task info\n"
306 "RI - Show registers inside task's context\n"
307 "AM xxxxxxxx yyyyyyyy - AllocVec - size=xxxxxxxx, "
308 "requiments=yyyyyyyy\n"
309 "FM xxxxxxxx - FreeVec from xxxxxxxx\n"
310 "RB xxxxxxxx - read byte from xxxxxxxx\n"
311 "RW xxxxxxxx - read word from xxxxxxxx\n"
312 "RL xxxxxxxx - read long from xxxxxxxx\n"
313 "WB xxxxxxxx bb - write byte bb at xxxxxxxx\n"
314 "WW xxxxxxxx wwww - write word wwww at xxxxxxxx\n"
315 "WL xxxxxxxx llllllll - write long llllllll at xxxxxxxx\n"
316 "RA xxxxxxxx ssssssss - read array(ssssssss bytes long) "
317 "from xxxxxxxx\n"
318 "RC xxxxxxxx ssssssss - read ascii (ssssssss bytes long) "
319 "from xxxxxxxx\n"
320 "QT 00000000 - quit SAD\n"
321 "SL - show all available libraries (libbase : libname)\n"
322 "SR - show all available resources (resbase : resname)\n"
323 "SD - show all available devices (devbase : devname)\n"
324 "SS xxxxxxxx - show symbol for xxxxxxxx\n"
325 "ST - show tasks (T - this, R - ready, W - wait)\n"
326 "HE - this help.\n");
328 /* AllocMem command */
329 else if (strcmp(comm, "AM") == 0)
331 ULONG size = GetL(data);
332 ULONG requim = GetL(NextWord(data));
334 kprintf("Allocated at 0x%p\n", AllocVec(size, requim));
336 /* FreeMem command */
337 else if (strcmp(comm, "FM") == 0)
339 APTR base = GetA(&data[0]);
341 kprintf("Freed at 0x%p\n", base);
342 FreeVec(base);
344 /* ReadByte */
345 else if (strcmp(comm, "RB") == 0)
347 UBYTE *addr = GetA(data);
349 kprintf("Byte at 0x%p: %02X\n", addr, *addr);
351 /* ReadWord */
352 else if (strcmp(comm, "RW") == 0)
354 UWORD *addr = GetA(data);
356 kprintf("Word at 0x%p: %04X\n", addr, *addr);
358 /* ReadLong */
359 else if (strcmp(comm, "RL") == 0)
361 ULONG *addr = GetA(data);
363 kprintf("Long at 0x%p: %08X\n", addr, *addr);
365 /* WriteByte */
366 else if (strcmp(comm,"WB") == 0)
368 UBYTE *addr = GetA(data);
369 UBYTE val = GetB(NextWord(data));
371 kprintf("Byte at 0x%p: %02X\n", addr, val);
372 *addr = val;
374 /* WriteWord */
375 else if (strcmp(comm, "WW") == 0)
377 UWORD *addr = GetA(data);
378 UWORD val = GetW(NextWord(data));
380 kprintf("Word at 0x%p: %04X\n", addr, val);
381 *addr = val;
383 /* WriteLong */
384 else if (strcmp(comm, "WL") == 0)
386 ULONG *addr = GetA(data);
387 ULONG val = GetL(NextWord(data));
389 kprintf("Long at 0x%p: %08X\n", addr, val);
390 *addr = val;
392 /* ReadArray */
393 else if (strcmp(comm, "RA") == 0)
395 UBYTE *ptr = GetA(data);
396 ULONG cnt = GetL(NextWord(data));
397 ULONG t;
399 kprintf("Array from 0x%p (size=0x%08lX):\n", ptr, cnt);
401 for(t = 1; t <= cnt; t++)
403 kprintf("%02X ", *ptr++);
404 if(!(t % 16)) kprintf("\n");
406 kprintf("\n");
408 /* ReadASCII */
409 else if (strcmp(comm, "RC") == 0)
411 char *ptr = GetA(data);
412 ULONG cnt = GetL(NextWord(data));
413 ULONG t;
415 kprintf("ASCII from 0x%p (size=%08X):\n", ptr, cnt);
417 for(t = 1; t <= cnt; t++)
419 RawPutChar(*ptr++);
420 if(!(t % 70)) kprintf(" \n");
422 kprintf(" \n");
424 else if (strcmp(comm, "SS") == 0) {
425 char *ptr = GetA(data);
426 STRPTR modname = "(unknown)";
427 STRPTR symname = "(unknown)";
428 APTR sym_l = (APTR)(IPTR)0;
429 APTR sym_h = (APTR)~(IPTR)0;
430 struct TagItem tags[] = {
431 { DL_ModuleName, (IPTR)&modname },
432 { DL_SymbolName, (IPTR)&symname },
433 { DL_SymbolStart, (IPTR)&sym_l },
434 { DL_SymbolEnd, (IPTR)&sym_h },
435 { TAG_END }
438 if (DebugBase) {
439 DecodeLocationA(ptr, tags);
442 kprintf("%p-%p %s.%s\n", sym_l, sym_h, modname, symname);
444 else if (strcmp(comm, "QT") == 0 && strcmp(data, "00000000") == 0)
446 kprintf("Quitting SAD...\n");
448 #ifdef KrnReleaseInput
449 /* Release debug input */
450 KrnReleaseInput();
451 #endif
452 return;
454 else kprintf("?? Type HE for help\n");
457 AROS_LIBFUNC_EXIT
458 } /* Debug */
460 /****************************************************************************************/
462 char GetK(struct ExecBase *SysBase)
464 int i;
468 i = RawMayGetChar();
469 } while(i == -1);
471 return (char)i;
474 /****************************************************************************************/
476 UQUAD GetQ(char* string)
478 UQUAD ret = 0;
479 int i;
480 char digit;
482 for(i = 0; i < 16; i++)
484 digit = toupper(string[i]);
486 if (!isxdigit(digit))
487 break;
489 digit -= '0';
490 if (digit > 9) digit -= 'A' - '0' - 10;
491 ret = (ret << 4) + digit;
494 return ret;
497 /****************************************************************************************/
499 ULONG GetL(char* string)
501 ULONG ret = 0;
502 int i;
503 char digit;
505 for(i = 0; i < 8; i++)
507 digit = toupper(string[i]);
509 if (!isxdigit(digit))
510 break;
512 digit -= '0';
513 if (digit > 9) digit -= 'A' - '0' - 10;
514 ret = (ret << 4) + digit;
517 return ret;
520 /****************************************************************************************/
522 UWORD GetW(char* string)
524 UWORD ret = 0;
525 int i;
526 char digit;
528 for(i = 0; i < 4; i++)
530 digit = toupper(string[i]);
532 if (!isxdigit(digit))
533 break;
535 digit -= '0';
536 if (digit > 9) digit -= 'A' - '0' - 10;
537 ret = (ret << 4) + digit;
540 return ret;
543 /****************************************************************************************/
545 UBYTE GetB(char* string)
547 UBYTE ret = 0;
548 int i;
549 char digit;
551 for(i = 0; i < 2; i++)
553 digit = toupper(string[i]);
555 if (!isxdigit(digit))
556 break;
558 digit -= '0';
559 if (digit > 9) digit -= 'A' - '0' - 10;
560 ret = (ret << 4) + digit;
563 return ret;