Copyright (c) Hyperion Entertainment and contributors.
How to open and use the exec debug interface
Author
Alfkil Wennermark
Copyright (c) 2010 Alfkil Wennermark
Used by permission.
Tutorial
Next step in my small series concerns itself with how to open and use the "secret" (but very useful) debug interface. Thanks to Steven Solie and Thomas Frieden.
Probably the best way to trap exceptions from within your code is to use the debug interface, that is "hidden" inside exec.library. The main problem with this interface is, that it is not very well documented. My main source of documentation on this issue is the amigaos-nat.c file from Thomas Friedens GDB sources. These can be found inside the adtools project on sourceforge.net.
The following code just plainly opens the interface, attaches a debug hook to itself, causes an exception and tells you what has happened. Normally you wouldn't attach the hook to your own process. Rather you would open whatever code you want to debug with fx. LoadSeg(), run it with CreateNewProc() (or some other way) and attach the debug hook to it. To keep things simple, though, this code just attaches the hook to itself.
/* debugtrap.cExample of use of the exec debug interface by Alfkil Wennermark 2010 Thanks to Steven Solie, Thomas Frieden and others This code is partially copied from Thomas' GDB source */ #include <proto/exec.h> #include <proto/dos.h> #include <exec/types.h> #include <exec/interrupts.h> #include <exec/tasks.h> #include <dos/dos.h> #include <stdio.h> struct DebugIFace *IDebug = 0; struct KernelDebugMessage { uint32 type; union { struct ExceptionContext *context; struct Library *library; } message; }; static ULONG amigaos_debug_callback(struct Hook *, struct Task *, struct KernelDebugMessage *); struct Hook debug_hook; struct Task *amiga_task; BPTR exec_seglist; ULONG debug_data = 1234; void init() { IDebug = (struct DebugIFace *)IExec->GetInterface((struct Library *)SysBase, "debug", 1, 0); if (!IDebug) { printf("Can't get DEBUG access\n"); exit(RETURN_FAIL); } debug_hook.h_Entry = (ULONG (*)())amigaos_debug_callback; debug_hook.h_Data =(APTR)&debug_data; /* NB: Ideally we would start up another task, that we want to debug, and attach ourselves to that task using the debug hook, but for simplicity we just use our own task here */ amiga_task = IExec->FindTask(NULL); IDebug->AddDebugHook(amiga_task, &debug_hook); } void end() { IDebug->AddDebugHook(amiga_task, 0); if (IDebug)IExec->DropInterface((struct Interface *)IDebug); IDebug = NULL; } ULONG amigaos_debug_callback(struct Hook *hook, struct Task *currentTask, struct KernelDebugMessage *dbgmsg) { struct ExecIFace *IExec = (struct ExecIFace *)((struct ExecBase *)SysBase)->MainInterface; uint32 *data = (uint32 *)hook->h_Data; /* these are the 4 types of debug msgs: */ switch (dbgmsg->type) { case DBHMT_REMTASK: *data = 9; break; case DBHMT_EXCEPTION: *data = 11; break; case DBHMT_OPENLIB: *data = 13; break; case DBHMT_CLOSELIB: *data = 15; break; default: *data = 0; break; } /* returning 1 will suspend the task ! */ return 0; } int main() { init(); /* Cause an exception on purpose: */ uint32 *beef = 0; *beef = 0L; printf("We received a"); switch (debug_data) { case 9: printf(" REMTASK"); break; case 11: printf("n EXCEPTION"); break; case 13: printf("n OPENLIB"); break; case 15: printf(" CLOSELIB"); break; default: printf("n unknown"); break; } printf(" signal!n"); end(); return RETURN_OK; }