Moved DisplayError() back to base code
[AROS.git] / rom / exec / debug.c
blob5d50e88464bfd8d293f777f896660e3e13cb910d
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 <proto/exec.h>
12 #include <proto/kernel.h>
14 #include <ctype.h>
15 #include <string.h>
17 #include "exec_intern.h"
19 /****************************************************************************************/
21 char GetK();
22 UQUAD GetQ(char *);
23 ULONG GetL(char *);
24 UWORD GetW(char *);
25 UBYTE GetB(char *);
26 int get_irq_list(char *buf);
28 #if __WORDSIZE == 64
29 #define GetA (APTR)GetQ
30 #else
31 #define GetA (APTR)GetL
32 #endif
34 /****************************************************************************************/
36 static char *NextWord(char *s)
38 /* Skip to first space or EOL */
39 while (*s != ' ')
41 if (!*s)
42 return s;
43 s++;
46 /* Then skip to first non-space */
47 while (*++s == ' ');
49 return s;
52 /*****************************************************************************
54 NAME */
56 AROS_LH1(void, Debug,
58 /* SYNOPSIS */
59 AROS_LHA(unsigned long, flags, D0),
61 /* LOCATION */
62 struct ExecBase *, SysBase, 19, Exec)
64 /* FUNCTION
65 Runs SAD - internal debuger.
67 INPUTS
68 flags not used. Should be 0 now.
70 RESULT
72 NOTES
74 EXAMPLE
76 BUGS
78 SEE ALSO
80 INTERNALS
82 HISTORY
83 18-01-99 initial PC version.
85 *****************************************************************************/
87 AROS_LIBFUNC_INIT
89 char comm[128];
90 char *data;
91 BOOL ignorelf = FALSE;
93 #ifdef KrnObtainInput
95 * Try to obtain debug input from the kernel.
96 * If it failed, we will hang up in RawMayGetChar(), so exit immediately.
98 if (!KrnObtainInput())
99 return;
100 #endif
102 RawIOInit();
104 for (;;)
106 int i = 0;
108 kprintf("SAD(%d,%d)>", SysBase->TDNestCnt, SysBase->IDNestCnt);
110 /* Get Command code */
113 char key = GetK(SysBase);
114 BOOL t = ignorelf;
116 /* We skip only single LF which immediately follows the CR. So we remember
117 previous value of the flag and reset it when any character arrives. */
118 ignorelf = FALSE;
119 if (key == '\n') {
120 if (t)
121 continue;
122 else
123 break;
126 /* TABs are problematic to deal with, we ignore them */
127 else if (key == 0x09)
128 continue;
130 /* If we've just got CR, we may get LF next and we'll need to skip it */
131 else if (key == '\r') {
132 ignorelf = TRUE;
133 break;
136 /* Process backspace */
137 else if (key == 0x08)
139 if (i > 0) {
140 /* Go backwards, erase the character, then go backwards again */
141 RawPutChar(key);
142 RawPutChar(' ');
143 RawPutChar(key);
144 i--;
146 continue;
149 RawPutChar(key);
150 comm[i++] = key;
152 while (i < (int)sizeof(comm)-1);
153 comm[i] = 0;
154 RawPutChar('\n');
156 /* Now get data for command */
157 data = NextWord(comm);
158 comm[2] = 0;
160 /* Reboot command */
161 if (strcmp(comm, "RE") == 0 && strcmp(data, "AAAAAAAA") == 0)
162 ColdReboot();
163 /* Restart command */
164 else if (strcmp(comm, "RS") == 0 && strcmp(data, "FFFFFFFF") == 0)
165 ShutdownA(SD_ACTION_COLDREBOOT);
166 /* Forbid command */
167 else if (strcmp(comm, "FO") == 0)
168 Forbid();
169 /* Permit command */
170 else if (strcmp(comm, "PE") == 0)
171 Permit();
172 /* Disable command */
173 else if (strcmp(comm, "DI") == 0)
174 Disable();
175 /* Show active task information */
176 else if (strcmp(comm, "TI") == 0)
178 struct Task *t = SysBase->ThisTask;
180 kprintf("Active task (%p = '%s'):\n"
181 "tc_Node.ln_Pri = %d\n"
182 "tc_SigAlloc = %04.4lx\n"
183 "tc_SPLower = %p\n"
184 "tc_SPUpper = %p\n"
185 "tc_Flags = %p\n"
186 "tc_SPReg = %p\n",
187 t, t->tc_Node.ln_Name,
188 t->tc_Node.ln_Pri,
189 t->tc_SigAlloc,
190 t->tc_SPLower,
191 t->tc_SPUpper,
192 t->tc_Flags,
193 t->tc_SPReg);
195 else if (strcmp(comm,"RI") == 0)
198 * TODO: this function is not useful at all in its current implementation.
199 * When the task is running its context is not valid. It would be much better
200 * to be able to examine contexts of other tasks.
201 * I left this here for demonstration purposes.
203 * 24.12.2010: reference to kernel.resource's private includes is removed,
204 * so PRINT_CPU_CONTEXT is not defined at all. Exec needs some CPU-specific
205 * .c file where all CPU-dependent functionality needs to be gathered. This
206 * is going to include full CPU context dump, stack trace, etc.
208 #ifdef PRINT_CPU_CONTEXT
209 struct ExceptionContext *r = SysBase->ThisTask->tc_UnionETask.tc_ETask->et_RegFrame;
211 PRINT_CPU_CONTEXT(r);
212 #else
213 kprintf("Not implemented on this platform.\n");
214 #endif
216 /* Enable command */
217 else if (strcmp(comm, "EN") == 0)
218 Enable();
219 /* ShowLibs command */
220 else if (strcmp(comm, "SL") == 0)
222 struct Node * node;
224 kprintf("Available libraries:\n");
226 /* Look through the list */
227 for (node = GetHead(&SysBase->LibList); node; node = GetSucc(node))
229 kprintf("0x%p : %s\n", node, node->ln_Name);
232 else if (strcmp(comm, "SI") == 0)
234 /* char buf[512];
236 kprintf("Available interrupts:\n");
238 get_irq_list(&buf);
239 kprintf(buf);*/
240 kprintf("Not implemented\n");
242 /* ShowResources command */
243 else if (strcmp(comm, "SR") == 0)
245 struct Node * node;
247 kprintf("Available resources:\n");
249 /* Look through the list */
250 for (node = GetHead(&SysBase->ResourceList); node; node = GetSucc(node))
252 kprintf("0x%p : %s\n", node, node->ln_Name);
255 /* ShowDevices command */
256 else if (strcmp(comm,"SD") == 0)
258 struct Node * node;
260 kprintf("Available devices:\n");
262 /* Look through the list */
263 for (node=GetHead(&SysBase->DeviceList); node; node = GetSucc(node))
265 kprintf("0x%p : %s\n", node, node->ln_Name);
268 /* ShowTasks command */
269 else if (strcmp(comm, "ST") == 0)
271 struct Node * node;
273 kprintf("Task List:\n");
275 kprintf("0x%p T %d %s\n",SysBase->ThisTask,
276 SysBase->ThisTask->tc_Node.ln_Pri,
277 SysBase->ThisTask->tc_Node.ln_Name);
279 /* Look through the list */
280 for (node = GetHead(&SysBase->TaskReady); node; node = GetSucc(node))
282 kprintf("0x%p R %d %s\n", node, node->ln_Pri, node->ln_Name);
285 for (node = GetHead(&SysBase->TaskWait); node; node = GetSucc(node))
287 kprintf("0x%p W %d %s\n", node, node->ln_Pri, node->ln_Name);
290 kprintf("Idle called %d times\n", SysBase->IdleCount);
292 /* Help command */
293 else if (strcmp(comm, "HE") == 0)
295 kprintf("SAD Help:\n");
296 kprintf("RE AAAAAAAA - reboots AROS - ColdReboot()\n"
297 "RS FFFFFFFF - RESET\n"
298 "FO - Forbid()\n"
299 "PE - Permit()\n"
300 "DI - Disable()\n"
301 "EN - Enable()\n"
302 "SI - Show IRQ lines status\n"
303 "TI - Show Active task info\n"
304 "RI - Show registers inside task's context\n"
305 "AM xxxxxxxx yyyyyyyy - AllocVec - size=xxxxxxxx, "
306 "requiments=yyyyyyyy\n"
307 "FM xxxxxxxx - FreeVec from xxxxxxxx\n"
308 "RB xxxxxxxx - read byte from xxxxxxxx\n"
309 "RW xxxxxxxx - read word from xxxxxxxx\n"
310 "RL xxxxxxxx - read long from xxxxxxxx\n"
311 "WB xxxxxxxx bb - write byte bb at xxxxxxxx\n"
312 "WW xxxxxxxx wwww - write word wwww at xxxxxxxx\n"
313 "WL xxxxxxxx llllllll - write long llllllll at xxxxxxxx\n"
314 "RA xxxxxxxx ssssssss - read array(ssssssss bytes long) "
315 "from xxxxxxxx\n"
316 "RC xxxxxxxx ssssssss - read ascii (ssssssss bytes long) "
317 "from xxxxxxxx\n"
318 "QT 00000000 - quit SAD\n"
319 "SL - show all available libraries (libbase : libname)\n"
320 "SR - show all available resources (resbase : resname)\n"
321 "SD - show all available devices (devbase : devname)\n"
322 "ST - show tasks (T - this, R - ready, W - wait)\n"
323 "HE - this help.\n");
325 /* AllocMem command */
326 else if (strcmp(comm, "AM") == 0)
328 ULONG size = GetL(data);
329 ULONG requim = GetL(NextWord(data));
331 kprintf("Allocated at 0x%p\n", AllocVec(size, requim));
333 /* FreeMem command */
334 else if (strcmp(comm, "FM") == 0)
336 APTR base = GetA(&data[0]);
338 kprintf("Freed at 0x%p\n", base);
339 FreeVec(base);
341 /* ReadByte */
342 else if (strcmp(comm, "RB") == 0)
344 UBYTE *addr = GetA(data);
346 kprintf("Byte at 0x%p: %02X\n", addr, *addr);
348 /* ReadWord */
349 else if (strcmp(comm, "RW") == 0)
351 UWORD *addr = GetA(data);
353 kprintf("Word at 0x%p: %04X\n", addr, *addr);
355 /* ReadLong */
356 else if (strcmp(comm, "RL") == 0)
358 ULONG *addr = GetA(data);
360 kprintf("Long at 0x%p: %08X\n", addr, *addr);
362 /* WriteByte */
363 else if (strcmp(comm,"WB") == 0)
365 UBYTE *addr = GetA(data);
366 UBYTE val = GetB(NextWord(data));
368 kprintf("Byte at 0x%p: %02X\n", addr, val);
369 *addr = val;
371 /* WriteWord */
372 else if (strcmp(comm, "WW") == 0)
374 UWORD *addr = GetA(data);
375 UWORD val = GetW(NextWord(data));
377 kprintf("Word at 0x%p: %04X\n", addr, val);
378 *addr = val;
380 /* WriteLong */
381 else if (strcmp(comm, "WL") == 0)
383 ULONG *addr = GetA(data);
384 ULONG val = GetL(NextWord(data));
386 kprintf("Long at 0x%p: %08X\n", addr, val);
387 *addr = val;
389 /* ReadArray */
390 else if (strcmp(comm, "RA") == 0)
392 UBYTE *ptr = GetA(data);
393 ULONG cnt = GetL(NextWord(data));
394 ULONG t;
396 kprintf("Array from 0x%p (size=0x%08lX):\n", ptr, cnt);
398 for(t = 1; t <= cnt; t++)
400 kprintf("%02X ", *ptr++);
401 if(!(t % 16)) kprintf("\n");
403 kprintf("\n");
405 /* ReadASCII */
406 else if (strcmp(comm, "RC") == 0)
408 char *ptr = GetA(data);
409 ULONG cnt = GetL(NextWord(data));
410 ULONG t;
412 kprintf("ASCII from 0x%p (size=%08X):\n", ptr, cnt);
414 for(t = 1; t <= cnt; t++)
416 RawPutChar(*ptr++);
417 if(!(t % 70)) kprintf(" \n");
419 kprintf(" \n");
421 else if (strcmp(comm, "QT") == 0 && strcmp(data, "00000000") == 0)
423 kprintf("Quitting SAD...\n");
425 #ifdef KrnReleaseInput
426 /* Release debug input */
427 KrnReleaseInput();
428 #endif
429 return;
431 else kprintf("?? Type HE for help\n");
434 AROS_LIBFUNC_EXIT
435 } /* Debug */
437 /****************************************************************************************/
439 char GetK(struct ExecBase *SysBase)
441 int i;
445 i = RawMayGetChar();
446 } while(i == -1);
448 return (char)i;
451 /****************************************************************************************/
453 UQUAD GetQ(char* string)
455 UQUAD ret = 0;
456 int i;
457 char digit;
459 for(i = 0; i < 16; i++)
461 digit = toupper(string[i]);
463 if (!isxdigit(digit))
464 break;
466 digit -= '0';
467 if (digit > 9) digit -= 'A' - '0' - 10;
468 ret = (ret << 4) + digit;
471 return ret;
474 /****************************************************************************************/
476 ULONG GetL(char* string)
478 ULONG ret = 0;
479 int i;
480 char digit;
482 for(i = 0; i < 8; 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 UWORD GetW(char* string)
501 UWORD ret = 0;
502 int i;
503 char digit;
505 for(i = 0; i < 4; 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 UBYTE GetB(char* string)
524 UBYTE ret = 0;
525 int i;
526 char digit;
528 for(i = 0; i < 2; 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;