Why XBRA

On the 68K architecture, whenever an exception occurs, the current processor state1,2 is saved on the supervisor stack (SSP), and then the processor effectively jumps indirectly via a fixed location in memory to code that will handle that exception. This fixed location is known as the exception vector for that particular exception. Exception vectors are memory locations from which the processor fetches the address of the code that will handle that exception when it occurs. Initially, all exception vectors are initialized by TOS to point to handlers for the exceptions within TOS.

Now suppose on an exception, your program needs to get control (say to set a variable). A common practice is to ``hook your code into the exception processing chain'', for the particular exception that your program is interested in. What we mean by ``hooking your code in'' is that you make the exception vector point to your code, which in turns points to wherever the original exception vector was pointing to. When the exception occurs, your code is given control, and once it has done its job, control passes to other exception handlers in the chain. The last handler in this chain (usually the one installed there initially by TOS), finishes off the exception handling sequence by executing a RTE instruction, which restores the processor to the state in which it was before the exception occurred. Figure [*] depicts what happens when you ``hook in your code''.

Figure: Hooking into an Exception Vector
\begin{figure}\begin{center}
{\small
\setlength{\unitlength}{0.0125in}%
\begin{...
...[0pt]{\elvrm After hooking in MyCode}}}
\end{picture}}\end{center}\end{figure}

It is bad karma not to pass a control to the next exception handler in the chain. Even if your code can completely handle an exception, it denies other handlers the opportunity to do what they supposed to do. Of course, there are situations where passing control to other handlers is not appropriate (for instance if you are intercepting a particular gemdos function in order to replace it totally; in most other cases you passing control on to the next handler is the thing to do).

When you install a handler, by convention you install it at the head of the exception chain. But you cannot assume that your handler will always remain there. Other processes can execute later and may insert their own exception handlers. When it comes time to unhook first you need to find yourself. This is where XBRA comes into its own. If the exception vector (the head of the chain) does not point to your handler there is no way you can find it, unless all handlers between the head and you follow a common conventions to identify the handler and to find the pointer to the next element of this chain. The XBRA protocol specifies where to find, relative to the beginning of a handler, the next handler address. To avoid spurious identification the XBRA protocol further defines two magic numbers, again at fixed offsets relative to the handler. Now unchaining yourself becomes easy and reliable. You either encountered yourself, or you continue down the chain by picking up the address of the next handler from a fixed offset in the current handler. Once you have found yourself you check the two magic numbers, again at fixed offsets, to ensure that you actually hit an XBRA header rather than some random memory location that just happens to have the value that you are looking for. If it all checks out, you can remove yourself reliably. Figure [*] illustrates a typical XBRA exception chain.

Figure: An XBRA Exception Chain
\begin{figure}\begin{center}
{\small
\setlength{\unitlength}{0.0125in}%
\begin{...
...ebox{0pt}[0pt][0pt]{\elvrm Code Addr}}}
\end{picture}}\end{center}\end{figure}