[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

There are some things to keep in mind when using SetFunction().  The
scheme described above can force a second task to hang around forever if
it SetFunction()ed a routine before you, since your debugger will not
normally release its handle on the second task's function.  Whenever
possible, install jump table based debuggers before any other
SetFunction()ing program (but after SetPatch of course).

Some debuggers interpret the return address of the caller.  When a
debugger jumps (JMP) to (what it thinks is) the original function, there
will be no problem.  However, if a debugger performs a JSR to a second
debugging function which interprets the return address, the second
debugging function will receive the first debugging function's return
address (the one that performed the JSR) rather than the return address of
the application that called the library function in the first place. This
can confuse the second debugger.  Two good examples of this are Scratcher
and MungWall, which both SetFunction() FreeMem().  MungWall looks at the
return address of the caller.  Since Scratcher calls the old FreeMem()
function with a JSR instruction, it would mislead MungWall if run after
it.  Preferably, debuggers that interpret the return address should be
started after other debuggers.

Although it is not common, some library functions call other library
functions and depend on certain scratch registers to contain valid values.
SetFunction()ing one of these functions is likely to change the values in
these scratch registers, leading to problems.  Because these dependencies
are not always documented, you might innocently run into one.  Scratcher
is an excellent tool for finding such dependencies.

In the past, some system functions did not have a JMP vector in their
entry in the LVO table.  Instead, the actual function was in the jump
table.  SetFunction() will not work on such a function.

Any debugging routine should be careful not to call the function it has
patched with SetFunction(), either directly or indirectly.  Doing so will
likely cause a stack overflow and crash the machine.  This may seem a bit
obvious until you consider how easy it is to indirectly call a system
routine.   Many system functions are not atomic.  They have to call lower
level system functions.  If you call a higher level system functions in
the debugging code and you have SetFunction()ed one of the routines the
high level function uses, the machine will probably crash from a stack
overflow.

Using SetFunction() on disk-based libraries and devices requires a little
extra care.  Unlike a ROM library, libraries (and devices) loaded into RAM
can be expunged when memory gets low.  To prevent the system from
expunging a library (or device) you have SetFunction()ed, either keep the
library (or device) opened, or use SetFunction() to patch the library's
expunge function.

Remember that when you install a wedge, another program can call it almost
instantly.  Because of this, the wedge should be completely set up before
you install it.

Note that dos.library is now a standard library and can be SetFunction()ed
as of V36.  Before V36 you would have to Forbid(), get the six original
bytes of the entry in the function vector table, install the new vector,
perform a SumLibrary() and then Permit().

If it is necessary to put debugging code into a Forbid() or Disable()
state, keep it in that state for as little time as possible to limit
system slowdown.  Remember that you cannot Disable() for more than 250
microseconds.  Be sure to read the Disable()/Enable() Autodocs before
using them.