The Patch package exposes an API which allows
callers to provide functions to be run before
a particular function or instruction is executed,
as well as directly after that patched function is
run.  These client provided before and after functions
should be provided acces to the machine state at the
time of interruption, along with an ability to pass
data from before to after.

Structure:
hash/[hash.h,hash.c]  hash utility optimized for lookup speed
		      designed to deal with addresses
patch/patch.h	      exported patch API
patch/patchWrite.c    utility providing the ability to pull
		      instructions out from under the processor
		      during execution
patch/patch.c	      architecture independent code
		      contains the real algorithms as well as what
		      should be the bulk of the logic
patch/PatchArch.h     signatures of functions provided by the 
		      architecture dependent code.
patch/arch/patchArch*.c
		      The architecture dependent C code which 
		      bootstraps the independent code and provides
		      processor specific information
patch/arch/patchTrap*.S
		      The architecture dependent assembly code
		      responsible for bootstrapping the dependent C
		      code, and the return function


So how does all this work?
First of all, if the target uses virtual memory and doesn't have a
target side symbol table, patchWriteInit() MUST be called
(see patchWrite.c).  Otherwise, we try to automatically determine whether
or not the target uses virtual memory by searching for the
corresponding functions.  This will fail if the target has no symbol table.

Requesting a patch will cause the global patch engine to be
initialized with default values (if hadn't been explicitly initialized 
earlier).  This process includes allocating and filling out internal
record keeping data, as well as a downcall to the architecture
specific initialization routine, which will install our code as either 
an interrupt or exception handler (see patchArch<architecture>.c).

Once the engine is initialized, we determine whether or not we can
replicate the effects of the instruction at the address requested.  If 
we do know how, then a set of code is written which duplicate the
effects of the patched address and stored in a sandbox.  This code
snippet can be as simple as
	<original patched instruction>
	<jump to instruction after patched address>
The code sandbox will be run in the same context (register set,
processor state, and stack) as the original patched instruction would
have been, but at a different address,  so any pc-relative
instructions will be re-written to accomodate this.  With the sandbox
in place, the first instruction of the function to be patched is
overwritten with an instruction which generates the trap we had
previously installed ourselves as a handler for.

When the patched instruction is hit, we're catapulted into the world
of architecture dependent code, because although most processors were
built with the same principles in mind, they implement those
principles using sometimes vastly different methods.  With this in
mind, the architecture specific code's goal is to quickly
and easily create a common state from which the independent
code (in patch.c and patchWrite.c) can perform a more general
process.  Typically, the exception will place the flow of control into 
an assembly function (PatchArchTrap) which bootstraps a C procedure
(PatchArchTrapProc()). This function, in turn, bootstraps the
independent code PatchTrap.  This process should be discussed in more
detail within the patchArch*.c code.

Once control passes to the independent code, it runs the user supplied 
'before' function and asks the architecture dependent code to set the
machine state such that the exception (remember, we're still in
exception/interrupt context) returns to the sandbox built when the
patch was created.  If there was an 'after' function provided, it will 
also set up supporting data structures and have the dependent code set 
the machine state such that the patched function will return to our
code, saving the address the patched function would have returned to.
The independent code returns returns with a success indicator, false
if the exception doesn't appear to have been generated by us, true
otherwise.  If it returns false, the dependent code should call the
previous (before we installed our own) handler with the same state as
our exception was originally passed.

At this point, our handler code should exit and the processor should
return from its exceptional state into the first address of the
sandbox.  The sandbox's code fragment executes, jumping back to user
code, which executes normally.

If an after function was provided, the user's function returns into an 
architecture dependent handler, which saves any registers which may be 
overwritten, and passes the return value on to the independent
PatchReturnTrap() function.  This routine locates the data supplied by 
the before routine and calls the after routine with it, releasing said 
data afterwards and returning to the machine dependent code with the
address this .  From here, we restore trounced registers and return to
the patched function's caller.


So, how do I extend this to new architectures?  Given a good
understanding of how the new hardware operates in exceptional
conditions, this should be relatively quick and painless.  The short
version is that you must provide a mechanism such that when the
patched instruction is executed, the independent function PatchTrap()
is called with a register set representing the processor state just
before executing the patched address.  The next bit of work is
programatically generating a machine code fragment which will emulate
the   Beyond that, all you should have to do is fill out the simple
helper routines.
