@DATABASE Enforcer.guide
@INDEX Index
@NODE MAIN
@TITLE "Enforcer Documentation"

                            Table of contents:

                            @{"    Enforcer     " link Enforcer}
                            @{"    SegTracker   " link SegTracker}
                            @{"    FindHit      " link FindHit}
                            @{"    LawBreaker   " link LawBreaker}
                            @{"    RebootOff    " link RebootOff}
                            @{"    Move4K       " link Move4K}

                   @{"    Copyright    " link Copyright}@{"    Credits      " link Credits}

******************************************************************************
*                                                                            *
* Permission is hereby granted to distribute the Enforcer archive            *
* containing the executables and documentation for non-commercial purposes   *
* so long as the archive and its contents are not modified in any way.       *
*                                                                            *
* Enforcer and related tools may not be distributed for a profit.            *
*                                                                            *
* Enforcer and related tools are not in the public domain.                   *
*                                                                            *
******************************************************************************

        +-----------------------------------------------------------+
        | Michael Sinz                                              |
        |                  UUNET:  mks@cbmvax.cbm.commodore.com     |
        | BIX:  msinz      or      msinz@bix.com                    |
        | "Can't I just bend one of the rules?" said the student.   |
        | The Master just looked back at him with a sad expression. |
        +-----------------------------------------------------------+
@ENDNODE

@NODE Credits
@TITLE "Enforcer Credits"

I would like to thank Bryce Nesbitt for coming up with the original
Enforcer idea.  Enforcer has helped the Amiga more than any other
debugging tool.

The Enforcer shield in the icon was designed by David "talin" Joiner.

I would also like to thank @{"the people" link Credits_Testers} who stayed with me during
all the long testing and the many beta releases Enforcer had.

However, I want to thank most the Amiga developers who use Enforcer
every day.  Like any other tool, Enforcer can not help the quality
of Amiga software if it is not used.  Running Enforcer all the time
makes it easier to notice bugs that happen during regular use of
the Amiga.

Thank you for making your software better!  It really does help the
Amiga when the software for it works well.

                    -- Michael Sinz

PS - To those people who still say that Enforcer causes working software
to have problems:  Enforcer just points out actions in software that
are already a problem and could cause major problems in some cases.
Enforcer does *not* cause any problems for software that does not
access invalid addresses.  Enforcer is 100% benign to software that
follows the rules.
@ENDNODE

@NODE Credits_Testers
@TITLE "Enforcer Beta Testers"

The following are some of the people who helped test
various versions of Enforcer V37:

Martin Taillefer                vertex@cbmvax.cbm.commodore.com
Peter Cherna                    peter@cbmvax.cbm.commodore.com
Brian Gontowski                 bgontowski@bix.com
Toby Simpson                    toby@bix
Benjamin Fuller                 benfuller@bix.com
David Joiner                    talin@bix.com
James M. Barkley, Jr            jim2@bix.com
Chris Green                     c_green@bix.com
David N. Junod                  djunod@bix.com
Joanne Dow                      jdow@bix.com
Jim Cooper                      jcooper@bix.com
Doug Walker                     djwalker@bix.com
Steve Krueger                   skrueger@bix.com
Steve Tibbett                   s.tibbett@bix.com
Kenneth T. Spoor                metadigm@bix.com
Victor A. Wagner                metadigm@bix.com
Sebastiano Vigna                svigna@bix.com
Tomas Rokicki                   radical.eye@bix.com
Redmond Simonsen                rsimonsen@bix.com
Willem Langeveld                langeveld@bix.com
Marvin Weinstein                mweinstein@bix.com
Lamonte Koop                    lkoop@bix.com
Allan M. Purtle                 snapper@bix.com
Gregory B Tibbs                 gbtibbs@bix.com
Robert Chapman                  rchapman@bix.com
@ENDNODE

@NODE Enforcer
@TITLE "Enforcer"
Enforcer V37 - An advanced version of Enforcer - Requires V37

SYNOPSIS
     Enforcer - A tool to watch for illegal memory accesses

FUNCTION
     Enforcer will use the MMU in the advanced 680x0 processors
     to set up MMU tables to watch for illegal accesses to memory
     such as the low-page and non-existent pages.

     To use, run Enforcer (plus any options you may wish)
     If you wish to detach, just use RUN >NIL: <NIL: to start it.
     You can also start it from the Workbench.  When started from Workbench,
     Enforcer will read the tooltypes of its icon or selected project icon
     for its options.  (See the sample project icons)

     Enforcer should only be run *after* SetPatch.

     If @{"SegTracker" link SegTracker} is running in the system when Enforcer is started,
     Enforcer will use the public @{"SegTracker" link SegTracker} seglist tracking for
     identifying the hits.

INPUTS
     The options for Enforcer are as follows:

     @{" QUIET        " link Option_QUIET}    @{" DATESTAMP    " link Option_DATESTAMP}    @{" STDIO        " link Option_STDIO}
     @{" TINY         " link Option_TINY}    @{" DEADLY       " link Option_DEADLY}    @{" BUFFERSIZE   " link Option_BUFFERSIZE}
     @{" SMALL        " link Option_SMALL}    @{" FSPACE       " link Option_FSPACE}    @{" INTRO        " link Option_INTRO}
     @{" SHOWPC       " link Option_SHOWPC}    @{" VERBOSE      " link Option_VERBOSE}    @{" PRIORITY     " link Option_PRIORITY}
     @{" STACKLINES   " link Option_STACKLINES}    @{" LED          " link Option_LED}    @{" NOALERTPATCH " link Option_NOALERTPATCH}
     @{" STACKCHECK   " link Option_STACKCHECK}    @{" PARALLEL     " link Option_PARALLEL}    @{" ON           " link Option_ON}
     @{" AREGCHECK    " link Option_AREGCHECK}    @{" RAWIO        " link Option_RAWIO}    @{" QUIT         " link Option_QUIT}
     @{" DREGCHECK    " link Option_DREGCHECK}    @{" FILE         " link Option_FILE}

RESULTS
     When running, a set of MMU tables that map addresses that are not
     in the system's address map as invalid such that any access to them
     will cause an access fault.  Enforcer will then display this fact
     and generate a diagnostic message as to what the illegal access
     was.  The first memory page (the one starting at location 0) is
     also marked as invalid as many programming errors cause invalid
     access to these addresses.  These addresses are completely off
     limits to applications.

     When an access violation happens, a report such as the following
     is output.

     @{" Output Example " link Output}     @{" Detail Example " link DetailExample}

WARNING
     Enforcer is for software testing.  In this role it is vital.
     Software that causes Enforcer hits may well not be able to run on
     newer hardware.  (Enforcer hits of high addresses on systems not
     running Enforcer but with a 68040 will most likely crash the system)
     Future systems and hardware will make this even more important.  The
     system can NOT survive software that causes Enforcer hits.

     However, Enforcer is NOT a system protector.  As a side effect, it
     may well keep a system from crashing when Enforcer hits happen, but
     it may just as well make the software crash earlier.  Enforcer is
     mainly a development and testing tool.

     Enforcer causes no ill effects with correctly working software.
     If a program fails to work while Enforcer is active, you should
     contact the developer of that program.

NOTES
     @{" General Notes " link Notes1}
     @{" 68020 Notes " link Notes2}
     @{" 68030 Notes " link Notes3}
     @{" 68040 Notes " link Notes4}
     @{" BridgeBoard " link Option_QUIET}

WRITING DEBUGGERS
     If you wish to make a debugger that works with Enforcer to help
     pinpoint Enforcer hits in the application and not cause Enforcer
     hits itself, here are some simple tips and a bit of code.

     @{" Debuggers: Trapping a hit " link Debuggers1}
     @{" Debuggers: Not causing a hit " link Debuggers2}

SEE ALSO
     "A master's secrets are only as good as the
      master's ability to explain them to others."  -  Michael Sinz
@ENDNODE

@NODE FindHit
@TITLE "FindHit"
FindHit - A tool that can locate the source file and line number
          that a @{"SegTracker" link SegTracker} report happened at.

SYNOPSIS
     FindHit will read the executable file and if there is debugging
     information in it, will try to locate the source file and line
     number that correspond to the @{"Enforcer" link Enforcer} hit HUNK/OFFSET.

FUNCTION
     FindHit uses the Lattice/SAS/MetaScope standard 'LINE'
     debug hunk to locate the closest line to the hunk/offset given.
     Note that this can only happen if the executable has the
     LINE debugging turned on.  (The @{"LawBreaker" link LawBreaker} program has this
     such that you can test this yourself.)

     In SAS/C 6.x, you need to compile with DEBUG=LINE or better
     and do not use the link option of NODEBUG.

     In SAS/C 5.x, you need to compile with -d1 or better.
     Note that FindHit works with the old SAS/C 5.x 'SRC '
     debugging information too.  This is required for -d2 or
     higher debugging support.  However, I do not have 'SRC ' hunk
     documentation and thus FindHit may be very specific to the
     SAS/C 5.x version of this hunk.

     In DICE (2.07 registered being the one I tried) the -d1
     debug switch also supports the 'LINE' debug hunk and
     works with FindHit.

     In HX68 and CAPE, you need to add the DEBUG directive to
     the assembly code program.  (See @{"LawBreaker" link LawBreaker} source)

     For other languages, or other versions of the above, please
     see the documentation that comes with the language.

INPUTS
     FILE/A      - The executable file, with debugging information.

     OFFSETS/A/M - The HEX offset (with or without leading $)
                   If a hunk number other than the default
                   is needed, it is expressed as hunk:offset.
                   The default hunk is that of the last argument
                   or hunk 0 if no hunk number has been given.
                   For example:  12 $22 $3:12 22 4:$12 32 $0:$32
                   will find information for:
                   hunk $0, offset $12
                   hunk $0, offset $22
                   hunk $3, offset $12
                   hunk $3, offset $22
                   hunk $4, offset $12
                   hunk $4, offset $32
                   hunk $0, offset $32

EXAMPLE
     FindHit FooBar $0342 $1:4F2 3:$1A 2C
     badcode.c : Line 184
     No line number information for Hunk $1, Offset $4F2
     badcode2.c : Line 12

     See the @{"Enforcer" link Enforcer} documentation about issues dealing with the
     exact location of the @{"Enforcer" link Enforcer} hit.  The line given may
     not be exactly where the hit happened.

     The way I use this is to always have line debugging turned on
     when I compile.  This does not change the quality of the code
     and takes only a small amount of extra disk space.  However,
     what I do is to link the program twice:  Once to a file called
     program.ld which contains all of the debugging information.
     Then, I link program.ld to program, stripping debug information.
     The command line for SLINK or BLINK is as follows:

         BLINK program.ld TO program NODEBUG

     I keep both of these on hand; with program being the one I
     distribute and use.  When a hit happens, I can just use program.ld
     with FindHit to get the line number and source file that it happened
     in.  This way you can distribute your software without the debugging
     information and still be able to use FindHit on the actual code.
     (After all, that link command does nothing but strip symbol and
     debug hunks)

NOTES
     Note that this program does nothing when run from the Workbench
     and thus does not have an icon.

SEE ALSO
     "Quantum Physics:  The Dreams that Stuff is made of." - Michael Sinz
@ENDNODE

@NODE LawBreaker
@TITLE "LawBreaker"
LawBreaker - A quicky test of @{"Enforcer" link Enforcer}

SYNOPSIS
     This is a quick test of @{"Enforcer" link Enforcer} and its reporting abilities.

FUNCTION
     This program is used to make sure that @{"Enforcer" link Enforcer} is correctly
     installed and operating.  LawBreaker works from either the CLI
     or Workbench.  It will try to read and write certain memory
     areas that will cause an @{"Enforcer" link Enforcer} hit or four.

     LawBreaker will also do an Alert to show how @{"Enforcer" link Enforcer} reports
     an Alert.

     Note that the LawBreaker executable has debugging information
     in it (standard LINE format debug hunk) such that you can
     try the @{"FindHit" link FindHit} program to find the line that causes the hit.

INPUTS
     Just run it...

RESULTS
     When running @{"Enforcer" link Enforcer}, you will see some output from @{"Enforcer" link Enforcer}.
     Output on a 68030 machine would look something like this:

25-Jul-93  17:15:04
WORD-WRITE to  00000000        data=0000       PC: 0763857C
USP:  07657C14 SR: 0004 SW: 04C1  (U0)(-)(-)  TCB: 07642F70
Data: DDDD0000 DDDD1111 DDDD2222 DDDD3333 0763852A DDDD5555 DDDD6666 DDDD7777
Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 0763852A 07400810 --------
Stck: 00000000 0752EE9A 00002800 07643994 00000000 076786D8 000208B0 2EAC80EE
Stck: 487AFD12 486C82C4 4EBA3D50 4EBAEA28 4FEF0014 52ACE2E4 204D43EC 88BC203C
----> 0763857C - "lawbreaker"  Hunk 0000 Offset 00000074
Name: "Shell"  CLI: "LawBreaker"  Hunk 0000 Offset 00000074

25-Jul-93  17:15:04
LONG-READ from AAAA4444                        PC: 07638580
USP:  07657C14 SR: 0015 SW: 0501  (U0)(F)(-)  TCB: 07642F70
Data: DDDD0000 DDDD1111 DDDD2222 DDDD3333 0763852A DDDD5555 DDDD6666 DDDD7777
Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 0763852A 07400810 --------
Stck: 00000000 0752EE9A 00002800 07643994 00000000 076786D8 000208B0 2EAC80EE
Stck: 487AFD12 486C82C4 4EBA3D50 4EBAEA28 4FEF0014 52ACE2E4 204D43EC 88BC203C
----> 07638580 - "lawbreaker"  Hunk 0000 Offset 00000078
Name: "Shell"  CLI: "LawBreaker"  Hunk 0000 Offset 00000078

25-Jul-93  17:15:04
BYTE-WRITE to  00000101        data=11         PC: 0763858A
USP:  07657C14 SR: 0010 SW: 04A1  (U0)(F)(D)  TCB: 07642F70
Data: 00000000 DDDD1111 DDDD2222 DDDD3333 0763852A DDDD5555 DDDD6666 DDDD7777
Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 0763852A 07400810 --------
Stck: 00000000 0752EE9A 00002800 07643994 00000000 076786D8 000208B0 2EAC80EE
Stck: 487AFD12 486C82C4 4EBA3D50 4EBAEA28 4FEF0014 52ACE2E4 204D43EC 88BC203C
----> 0763858A - "lawbreaker"  Hunk 0000 Offset 00000082
Name: "Shell"  CLI: "LawBreaker"  Hunk 0000 Offset 00000082

25-Jul-93  17:15:04
LONG-WRITE to  00000102        data=00000000   PC: 07638592
USP:  07657C14 SR: 0014 SW: 0481  (U0)(-)(D)  TCB: 07642F70
Data: 00000000 DDDD1111 DDDD2222 DDDD3333 0763852A DDDD5555 DDDD6666 DDDD7777
Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 0763852A 07400810 --------
Stck: 00000000 0752EE9A 00002800 07643994 00000000 076786D8 000208B0 2EAC80EE
Stck: 487AFD12 486C82C4 4EBA3D50 4EBAEA28 4FEF0014 52ACE2E4 204D43EC 88BC203C
----> 07638592 - "lawbreaker"  Hunk 0000 Offset 0000008A
Name: "Shell"  CLI: "LawBreaker"  Hunk 0000 Offset 0000008A

25-Jul-93  17:15:06
Alert !! Alert 35000000     TCB: 07642F70     USP: 07657C10
Data: 00000000 DDDD1111 DDDD2222 DDDD3333 0763852A DDDD5555 DDDD6666 35000000
Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 0763852A 07400810 --------
Stck: 076385A0 00000000 0752EE9A 00002800 07643994 00000000 0762F710 076305F0
----> 076385A0 - "lawbreaker"  Hunk 0000 Offset 00000098

     Now, using @{"FindHit" link FindHit}, you would type:

     FindHit LawBreaker 0:82

     and it will tell you the source file name and the line number
     where the hit happened.  See the @{"FindHit" link FindHit} documentation.

NOTES
     If @{"Enforcer" link Enforcer} is not running, the program should not cause the
     system to crash.  It will, however, write to certain areas
     of low memory.  Also, it will cause read access of some
     addresses that may not exist.  This may cause bus faults.

SEE ALSO
     "Quantum Physics:  The Dreams that Stuff is made of." - Michael Sinz

BUGS
     There are 4 known @{"Enforcer" link Enforcer} hits in this code and 1 alert, however,
     they will not be fixed.  ;^)
@ENDNODE

@NODE Move4K
@TITLE "Move4K"
Move4K - Moves as much out of the lower 4K of RAM as possible

SYNOPSIS
     On 68040 systems, as much of the lower 4K of CHIP RAM as possible
     is removed from system use.

FUNCTION
     On 68040 systems the MMU page sizes are 4K and 8K.  @{"Enforcer" link Enforcer}
     uses the 4K page size.  Since watching for hits of low memory
     is a vital part of @{"Enforcer" link Enforcer}, this means that the first 4K
     of RAM will be marked invalid.  On current systems, only
     the first 1K of RAM is invalid and thus 3K of RAM in that
     first 4K will end up needing to be emulated in @{"Enforcer" link Enforcer}.
     In order to reduce the overhead that this causes (and the
     major performance loss) this program will try to move as much
     from that first 4K as possible and make any of the free
     memory within the first 4K inaccessible.

     @{"Enforcer" link Enforcer} itself also has this logic, but it may be useful
     to be able to run this program as the first program in
     the Startup-Sequence (*AFTER* SetPatch) to try to limit
     the number of things that may use the lower 4K of RAM.

INPUTS
     Just run it...  Can be run from CLI or Workbench

RESULTS
     Any available memory in the lower 4K of CHIP RAM is removed
     plus a special graphics buffer is moved if it needs to be.
     After running this program you may have a bit less CHIP RAM
     than before.  You can run this program as many times as you
     wish since it only moves things if it needs to.

NOTES
     This program will do nothing on systems without a 68040.
     It does not, however, check for the MMU and thus it will
     move the lower 4K even if the CPU is not able to run @{"Enforcer" link Enforcer}.

     V39 of the operating system already does have the lowest
     MMU page empty and thus this program will effectively do
     nothing under V39.

SEE ALSO
     "Eloquence is vehement simplicity"

BUGS
     None.
@ENDNODE

@NODE SegTracker
@TITLE "SegTracker"
SegTracker - A global SegList tracking utility

SYNOPSIS
     A global tracking utility for disk loaded files including
     libraries and devices.  If placed in the startup-sequence
     right after SetPatch, it will track all disk loaded segments
     (other than those loaded by SetPatch)

FUNCTION
     SegTracker will patch the DOS LoadSeg(), NewLoadSeg(), and UnLoadSeg()
     functions in order to track the SegLists that are loaded.
     SegTracker keeps these seglist stored in a "safe" manner and
     even handles programs which SegList split.

     The first time the program is run, it installs the patches
     and semaphore.  After that point, it just finds the semaphore
     and uses it.

     By using SegTracker, it will be possible to better identify
     where @{"Enforcer" link Enforcer} hits come from when dealing with libraries
     and devices.  Basically, it is a system-global Hunk-o-matic.

     External programs can then pass in an address to SegTracker
     either via the command line or via the given function pointer
     in the SegTracker semaphore and get back results as to what
     hunk and offset the address is at.

     To work with the function directly, you need to find the
     the semaphore of "SegTracker" using FindSemaphore().
     The structure found will be the following:

     struct  SegSem
     {
     struct  SignalSemaphore seg_Semaphore;
             SegTrack        *seg_Find;
     };

     The function pointer points to a routine that takes an address
     and two pointers to long words for returning the Segment number
     and Offset within the segment.  The function returns the name
     of the file loaded.  Note that you must call this function
     while in Forbid() and then copy the name as the seglist may
     be UnLoadSeg'ed at any moment and the name string will then
     no longer be in memory.

     typedef char (* __asm SegTrack(register __a0 ULONG Address,
                                    register __a1 ULONG *SegNum,
                                    register __a2 ULONG *Offset));

     The above is for use in C code function pointer prototype
     in SAS/C 5 and 6.

INPUTS
     SHOW/S  - Shows all of the segments being tracked.

     DUMP/S  - Displays all of the segment elements being tracked.

     FIND/M  - Find the hex (in $xxxxx format) address in
               the tracked segments.  Multiple addresses
               can be given.

     Options are not available from Workbench as they require
     the CLI.  However, you can run SegTracker from Workbench
     to install it.

EXAMPLE USAGE

     @{" Example program " link FindSeg}

NOTES
     The earlier this command is run, the better off it will be in
     tracking disk loaded segments.  Under debug usage, you may
     wish to run the command right *AFTER* SetPatch.

     Some things may not call UnLoadSeg() to free their seglists.
     There is no way SegTracker can follow a seglist that is not
     unloaded via the dos.library call to UnLoadSeg().  For this
     reason, SegTracker adds new LoadSeg() segments to the top
     of its list.  This way, if any old segments are still on
     the list but have been unloaded via some other method
     they will not clash with newer segments during the find operation.

     Note that the resident list is one such place where
     UnLoadSeg() is not called to free the seglist.  Thus,
     if something is made resident and then later unloaded
     it will still be listed as tracked by SegTracker.

     In order to support a new feature in CPR, the SegTracker function
     got a "kludge" added to it.  If a segment is found, you can then
     call the function again with the same address but with having
     both pointers point to the same longword of storage.  By doing
     this, the function will now return (in that longword) the
     SegList pointer (CPTR not BPTR) of the file that contains
     the address.  The reason this method was used was such that
     it was compatible with older SegTracker versions.  In older
     versions you would not get the result you wanted but you would
     also not crash.  See the example above for more details on how
     to use this feature.  The SegTracker FIND option has been
     expanded to include this information.

     Due to the fact that I am working on a design of a new set of
     debugging tools (Enforcer/SegTracker/etc)  I do not wish to
     expand the current SegTracker model in too many ways.

SEE ALSO
     "Quantum Physics:  The Dreams that Stuff is made of." - Michael Sinz
@ENDNODE

@NODE RebootOff
@TITLE "RebootOff"
RebootOff - A keyboard reset handler to turn off Enforcer

SYNOPSIS
     This is a simple utility that will turn off @{"Enforcer" LINK Enforcer} when a
     keyboard reset happens.

FUNCTION
     This utility uses the feature of the A1000/A2000/A3000/A4000
     Amiga systems to turn off @{"Enforcer" LINK Enforcer} when the user does a
     keyboard reset (ctrl-Amiga-Amiga).  This utility requires that
     your Amiga supports (in hardware) the keyboard reset system.

     The reason this was written was such that @{"Enforcer" LINK Enforcer} could be
     "quit" just before you reboot your Amiga 3000.  The reason for
     this is that it will then let the kickstart not need to be reloaded
     and thus let utilities such as RAD: work across Reboots.  Note
     that this does *not* help in the case where the Amiga reboots
     under software conditions.  It is only for keyboard resets.

INPUTS
     Just run it from either the CLI or Workbench.  It installs
     a handler and exits.  On a keyboard reset, it will turn @{"Enforcer" LINK Enforcer}
     off before it lets the reset continue...  (max time of 10 seconds)

RESULTS
     Installs a small reset handler object and task into the system.
     About 3700 bytes needed the first time it is run.

NOTES
     If @{"Enforcer" LINK Enforcer} is not running, nothing will happen at Reset time.
     If @{"Enforcer" LINK Enforcer} can not quit, the reset system will continue to try
     to quit @{"Enforcer" LINK Enforcer} until the hardware timeout happens...

SEE ALSO
     From the home of the imaginary deadlines:
     "It will take 2i weeks to do that project." - Michael Sinz
@ENDNODE

@NODE Debuggers1
@TITLE "Debuggers: Trapping a hit"
To trap a hit requires a number of things to work.

First, the debugger itself must never cause an @{"Enforcer" LINK Enforcer} hit.
For help on that, see the "DEBUGGERS: NOT CAUSING A HIT"

Second, the debugger must be global.  That is, you must be
able to deal with a task getting a hit that is not the task
under test.  There are a number of simple ways to deal with
this, and I will leave this up to the debugger writer.
(One method will be shown below)

Third, the debugger must start *AFTER* @{"Enforcer" LINK Enforcer} starts.
If it is started before @{"Enforcer" LINK Enforcer}, the hits will not be
trapped.  (Note that this is not a problem)

A very important point:  The code needs to be fast for
the special case of location 4.  This is shown in the
code below.  It is very important that this be fast.

Note that it is much prefered that debuggers use the
method described below for trapping hits.  It should
be much more supportable this way as any of the tricky
work that may need to be done in the hit processing
will be handled by @{"Enforcer" LINK Enforcer} itself.  If you wish the
hit decoded, you can capture the @{"Enforcer" LINK Enforcer} output via a
pipe or some other method (such as @{"RAWIO" LINK Option_RAWIO}) or you can
leave that issue up to the user.

Now, given the above, the following bits of code can be
used to get the debugger to switch into single-step mode
at the point of the @{"Enforcer" LINK Enforcer} hit.  You can also set some
data value here to tell your debugger about this.

;
; The following code is inserted into the bus error vector.
; Make sure you follow the VBR to find the vector.
; Store the old vector in the address OldVector
; Make sure you already have the single-step trap vector
; installed before you install this.  Note that any extra
; code you add in the comment area *MUST NOT* cause a bus
; fault of any kind, including reading of location 4.
;
; This is the 68020 and 68030 version...
;
EnforcerHit:    ds.l    1                       ; Some private flag
MyTask:         ds.l    1                       ; Task under test
MyExecBase:     ds.l    1                       ; The local copy
OldVector:      ds.l    1                       ; One long word
NewVector:      cmp.l   #4,$10(sp)              ; 68020 and 68030
                beq.s   TraceSkip               ; If AbsExecBase, OK
                ;
                ; Now, if you wish to only trap a specific task,
                ; do the check at this point.  For example, a
                ; simple single-task debugger would do something
                ; like this:
                move.l  a0,-(sp)                ; Save this...
                move.l  MyExecBase(pc),a0       ; Get ExecBase...
                move.l  ThisTask(a0),a0         ; Get ThisTask
                cmp.l   MyTask(pc),a0           ; Are they the same?
                move.l  (sp)+,a0                ; Restore A0 (no flags)
                bne.s   TraceSkip               ; If not my task, skip
                ;
                bset.b  #7,(sp)                 ; Set trace bit...
                ; If you have any other data to set, do it now...
                ; Set as setting the EnforcerHit bit in your data...
                addq.l  #1,EnforcerHit          : Count the hit...
                ;
TraceSkip:      move.l  OldVector(pc),-(sp)     ; Ready to return
                rts
;
; This is the 68040 version...
;
NewVector040:   cmp.l   #4,$14(sp)              ; 68040
                beq.s   TraceSkip040            ; If AbsExecBase, OK
                ;
                ; Now, if you wish to only trap a specific task,
                ; do the check at this point.  For example, a
                ; simple single-task debugger would do something
                ; like this:
                move.l  a0,-(sp)                ; Save this...
                move.l  MyExecBase(pc),a0       ; Get ExecBase...
                move.l  ThisTask(a0),a0         ; Get ThisTask
                cmp.l   MyTask(pc),a0           ; Are they the same?
                move.l  (sp)+,a0                ; Restore A0 (no flags)
                bne.s   TraceSkip               ; If not my task, skip
                ;
                bset.b  #7,(sp)                 ; Set trace bit...
                ; If you have any other data to set, do it now...
                ; Set as setting the EnforcerHit bit in your data...
                addq.l  #1,EnforcerHit          : Count the hit...
                ;
TraceSkip040:   move.l  OldVector(pc),-(sp)     ; Ready to return
                rts
@ENDNODE

@NODE Debuggers2
@TITLE "Debuggers: Not causing a hit"
In order not to cause Enforcer hits, you can do a number
of things.  The easiest is to test the address with the TypeOfMem()
EXEC function.  If TypeOfMem() returns 0, the address is not
in the memory lists.  However, this does not mean it is not a
valid address in all cases.  (ROM, chip registers, I/O boards)
For those cases, you can build a "valid memory access table"
much like Enforcer does.  Here is the code from Enforcer for
the base memory tables:

/*
 * Mark_Address(mmu,start address,length,type)
 */

/*
 * Special case the first page of CHIP RAM
 */
mmu=Mark_Address(mmu,0,0x1000,INVALID | NONCACHEABLE);

/*
 * Map in the free memory
 */
Forbid();
mem=(struct MemHeader *)SysBase->MemList.lh_Head;
while (mem->mh_Node.ln_Succ)
{
  mmu=Mark_Address(mmu,
                   (ULONG)(mem->mh_Lower),
                   (ULONG)(mem->mh_Upper)-(ULONG)(mem->mh_Lower),
                   ((MEMF_CHIP & TypeOfMem(mem->mh_Lower)) ?
                     (NONCACHEABLE | VALID) : (CACHEABLE | VALID)));
  mem=(struct MemHeader *)(mem->mh_Node.ln_Succ);
}
Permit();

/*
 * Map in the autoconfig boards
 */
if (ExpansionBase=OpenLibrary("expansion.library",0))
{
struct  ConfigDev       *cd=NULL;

  while (cd=FindConfigDev(cd,-1L,-1L))
  {
    /* Skip memory boards... */
    if (!(cd->cd_Rom.er_Type & ERTF_MEMLIST))
    {
      mmu=Mark_Address(mmu,
                       (ULONG)(cd->cd_BoardAddr),
                       cd->cd_BoardSize,
                       VALID | NONCACHEABLE);
    }
  }
  CloseLibrary(ExpansionBase);
}

/*
 * Now for the control areas...
 */
mmu=Mark_Address(mmu,0x00BC0000,0x00040000,VALID | NONCACHEABLE);
mmu=Mark_Address(mmu,0x00D80000,0x00080000,VALID | NONCACHEABLE);

/*
 * and the ROM...
 */
mmu=Mark_Address(mmu,
                 0x00F80000,
                 0x00080000,
                 VALID | CACHEABLE | WRITEPROTECT);

/*
 * If the credit card resource, make the addresses valid...
 */
if (OpenResource("card.resource"))
{
  mmu=Mark_Address(mmu,0x00600000,0x00440002,VALID | NONCACHEABLE);
}

/*
 * If CD-based Amiga (CDTV, A570, etc.)
 */
if (FindResident("cdstrap"))
{
  mmu=Mark_Address(mmu,0x00E00000,0x00080000,VALID | NONCACHEABLE);
  mmu=Mark_Address(mmu,0x00B80000,0x00040000,VALID | NONCACHEABLE);
}

/*
 * Check for ReKick/ZKick/KickIt
 */
if ((((ULONG)(SysBase->LibNode.lib_Node.ln_Name)) >> 16) == 0x20)
{
  mmu=Mark_Address(mmu,
                   0x00200000,
                   0x00080000,
                   VALID | CACHEABLE | WRITEPROTECT);
}
@ENDNODE

@NODE Notes1
@TITLE "General Notes"
This is Enforcer V37.  Bryce Nesbitt came up with the original
"Enforcer" that has been instrumental to the improvement in the
quality of software on the Amiga.  The Amiga users and developers
owe him a great deal for this.  Thank you Bryce!  Enforcer V37,
however, is a greatly enhanced and more advanced tool.

Enforcer V37 came about due to a number of needs.  These included
the need for more output options and better performance.  It also
marks the removal of all kludges that were in the older versions.
Also, some future plans required some of these changes...

In addition, the complete redesign was needed in order to also
support the 68040.  The internal design of Enforcer is now set up
such that CPU/MMU specific code can be cleanly accessed from the
general house keeping aspect of the code.  The MMU bus error
handling is, however, 100% CPU specific.

Since AbsExecBase is in low memory, reads of this address are slower
with Enforcer running.  Caching AbsExecBase locally is highly
recommended since it is in CHIP memory and on systems with FAST
memory, it will be faster to access the local cached value. (In
addition to the performance increase when running Enforcer) Note
that doing many reads of location 4 will hurt interrupt performance.

When the Amiga produces an ALERT, EXEC places some magic numbers
into some special locations in low memory.  The exact pattern
changes between versions of the operating system.

Enforcer will patch the EXEC function ColdReboot() in an attempt to
"get out of the way" when someone tries to reboot the system.
Enforcer will clean up as much as possible the MMU tables and then
call the original LVO.  When Enforcer is asked to quit, it will
check to make sure it can remove itself from this LVO. If it can
not, it will not quit at that time.  If run from the shell, it will
display a message saying that it tried but could not exit.  Enforcer
will continue to be active and you can try later to deactivate it.

Enforcer will also patch the EXEC function Alert() in an attempt to
provide better tracking of other events in the system.  It is also
patched such that dead-end alerts will correctly reset the system
and be displayed.  With this patch in place, the normal alerts will
not be seen but will be replaced by the Enforcer output shown
above.  See @{"LawBreaker" link LawBreaker} for a more complete example of this.

Other notes:
     @{" 68020 Notes " link Notes2}
     @{" 68030 Notes " link Notes3}
     @{" 68040 Notes " link Notes4}
     @{" BridgeBoard " link Option_QUIET}
@ENDNODE

@NODE Notes2
@TITLE "68020 Notes"
The 68020 does not have a built-in MMU but has a co-processor
feature that lets an external MMU be connected.  Enforcer MMU code
is designed for use with 68851 MMU.  This is the some-what 68030
compatible MMU by Motorola.  Enforcer uses the same code for both
the 68030 and the 68020/68851.  For this reason, 68020/68851 users
should see the @{"68030 NOTES" link Notes3} section.
@ENDNODE

@NODE Notes3
@TITLE "68030 Notes"
The 68030 uses cycle/instruction continuation and will
supply the data on reads and ignore writes during an access
fault rather than let the real bus cycle happen.  This means
that on a fault caused by MMU tables, no bus cycle to the
fault address will be generated.  (For those of you with analyzers)

In some cases, the 68030 will have advanced the Program Counter
past the instruction by the time the access fault happens.
This is usually only on WRITE faults.  For this reason, the PC
may either point at the instruction that caused the fault or
just after the instruction that caused the fault.  (Which could
mean that it is pointing to the middle of the instruction
that caused the fault.)

Note that there is a processor called 68EC030.  This processor
has a disabled or defective MMU.  However, it may function well
enough for Enforcer to think it has a fully functional MMU and
thus Enforcer will attempt to run.  However, even if it looks like
the MMU is functioning, it is not fully operational and thus may
cause strange system activity and even crashes.  Do not assume
that Enforcer is safe to use on 68EC030 systems.
@ENDNODE

@NODE Notes4
@TITLE "68040 Notes"
Enforcer, on the 68040, *requires* that the 68040.library be
installed and it requires an MMU 68040 CPU.  The 68EC040 does not
have a MMU.  The 68LC040 does have an MMU and is supported. Enforcer
will work best in a system with the 68040.library 37.10 or better
but it does know how to deal with systems that do not have that
version.

Due to the design of the 68040, Enforcer is required to do a number
of things differently.  For example, the MMU page size can only be
either 8K or 4K.  This means that to protect the low 1K of memory,
Enforcer will end up having to mark the first 4K of memory as
invalid and emulate the access to the 3K of that memory that is
valid. For this reason Enforcer moves a number of possible
structures from the first 4K of memory to higher addresses.  This
means that the system will continue to run at a reasonable speed.
The first time Enforcer is run it may need to allocate memory for
these structures that it will move.  Enforcer can never return this
memory to the system.

In addition to the fact that the 68040 MMU table size is different,
the address fault handling is also different.  Namely, the 68040 can
only rerun the cycle and not continue it like the 68030. This means
that on a 68040, the page must be made available first and then made
unavailable.  Make this work, Enforcer will switch the instruction
that caused the error into trace mode and let it run with a special
MMU setup.  When the trace exception comes in, the MMU is set up
back to the way it was.  Enforcer does its best to keep debuggers
working.  Note, however, that the interrupt level during a trace of
a READ will end up being set to 7.  This is to prevent interrupts
from changing the order of trace/MMU table execution.  The level
will be restored to the original state before continuing.  Since T0
mode tracing is also supported, there are also some changes in the
way it operates.  T0 mode tracing is defined, on the 68040, to cause
a trace whenever the instruction pipeline needed to be reloaded.
While on the 68020/030 processors this was normally only for the
branch instructions, in the 68040 this includes a large number of
other instructions.  (Including NOP!)  Anyway, if an Enforcer hit
happens while in T0 tracing mode, the trace will happen even on
instructions that normally would not cause a T0 mode trace.  Since
this may actually help in debugging and because it was not possible
to do anything else, this method of operation is deemed acceptable.

Another issue with the 68040 is that WRITE faults happen *after* the
instruction has executed.  (Except for MOVEM)  In fact, it is common
for the 68040 to execute one or more extra instructions before the
WRITE fault is executed.  This design makes the 68040 much faster,
but it also makes the Program Counter value that Enforcer can report
for the fault much less likely to be pointing to the instruction
that caused it.  The worst cases are sequences such as a write fault
followed by a branch instruction.  In these cases, the branch is
usually already executed before the write fault happens and thus the
PC will be pointing to the target of the branch.  There is nothing
that can be done within Enforcer to help out here.  You will just
need to be aware of this and deal with it as best as possible.

Along with the above issue, is the fact that since a write fault may
be delayed, a read fault may happen before the write fault shows up.
Internally, enforcer does not do special processing for these and
they will not show up.  Since another hit was happening anyway, it
is felt that it is best to just not report the hit.  Along the same
lines, the hit generated from a MOVEM instruction may only show as a
single hit rather than 1 for each register moved.

On the Amiga, MOVE16 is not supported 100%.  Causing an Enforcer hit
with a MOVE16 will cause major problems and maybe cause Enforcer or
your task to lock.  Since MOVE16 is not supported, this is not a
major issue.  Just watch out if you are using this 68040
instruction.  (Also, watch out for the 68040 CPU bug with MOVE16)

The functions CachePreDMA(), CachePostDMA(), and CacheControl() are
patched when the 68040 MMU is turned on by Enforcer.  These
functions are patched such the issues with DMA and the 68040
COPYBACK data caches are addressed.  The 68040.library normally
deals with this, however since Enforcer turns on the MMU, the method
of dealing with it in the 68040.library will not work. For this
reason, Enforcer will patch these and implement the required fix for
when the MMU is on.  When Enforcer is asked to exit, it will check
if it can remove itself from these functions.  If it can not, it
will ignore the request to exit.  If Enforcer was run from the CLI,
it will print a message saying that it can not exit when the attempt
is made.
@ENDNODE

@NODE Option_QUIET
@TITLE "Option: QUIET"
QUIET/S

This tells Enforcer to not complain about any invalid
access and to just build MMU tables for cache setting
reasons -- mainly used in conjunction with an
Amiga BridgeBoard in a 68030 environment so that
the system can run with the data cache turned on.
In this case,
               RUN >NIL: Enforcer QUIET
should be placed into the startup-sequence right
after SetPatch.
@ENDNODE

@NODE Option_TINY
@TITLE "Option: TINY"
TINY/S

This tells Enforcer to output a minimal hit.  The
output is basically the first line of the Enforcer
hit.
@ENDNODE

@NODE Option_SMALL
@TITLE "Option: SMALL"
SMALL/S

This tells Enforcer to output the hit line, the
USP: line, and the Name: line.  (This means that
no register or stack display will be output)
@ENDNODE

@NODE Option_SHOWPC
@TITLE "Option: SHOWPC"
SHOWPC/S

This tells Enforcer to also output the two lines
that contain the memory area around the PC where
the hit happened.  Useful for disassembly.
This option will not do anything if @{"QUIET" link Option_QUIET}, @{"SMALL" link Option_SMALL} or
@{"TINY" link Option_TINY} output modes are selected.
@ENDNODE

@NODE Option_STACKLINES
@TITLE "Option: STACKLINES"
STACKLINES/K/N

This lets you pick the number of lines of stack
backtrace to display.  The default is 2.  If set
to 0, no stack backtrace will be displayed.  There
is NO ENFORCED LIMIT on the number of lines.
@ENDNODE

@NODE Option_STACKCHECK
@TITLE "Option: STACKCHECK"
STACKCHECK/S

This option tells Enforcer that you wish all of
the long words displayed in the stack to be checked
against the global seglists via @{"SegTracker" link SegTracker}.
This will tell you what seglist various return
addresses are on the stack.  If you are not
displaying stack information in the Enforcer hit
then STACKCHECK will have nothing to check.
If you are displaying stack information, then
each long word will be check and only those which
are in one of the tracked seglists will be
displayed in a @{"SegTracker" link SegTracker} line.
The output will show the PC address first and
then work its way back on the stack such that you
can read it from bottom up as the order of calling
or from top down as the stack-frame backtrace.
@ENDNODE

@NODE Option_AREGCHECK
@TITLE "Option: AREGCHECK"
AREGCHECK/S

This option tells Enforcer that you wish all of
the values in the Address Registers checked via
@{"SegTracker" link SegTracker}, much like @{"STACKCHECK" link Option_STACKCHECK}.
@ENDNODE

@NODE Option_DREGCHECK
@TITLE "Option: DREGCHECK"
DREGCHECK/S

This option tells Enforcer that you wish all of
the values in the Data Registers checked via
@{"SegTracker" link SegTracker}, much like @{"STACKCHECK" link Option_STACKCHECK}.
@ENDNODE

@NODE Option_DATESTAMP
@TITLE "Option: DATESTAMP"
DATESTAMP/S

This makes Enforcer output a date and time with each
hit.  Due to the nature of the way Enforcer must
work, the time can not be read during the Enforcer
hit itself so the time output will be the last time
value the main Enforcer task set up.  Enforcer will
update this value every second as to try to not
use any real CPU time.  The time displayed in the
hit will thus be exact.
(Assuming the system clock is correct.)
The date is output before anything from the hit
other than the optional introduction string.
@ENDNODE

@NODE Option_DEADLY
@TITLE "Option: DEADLY"
DEADLY/S

This makes Enforcer be a bit more nasty.  Normally,
when an illegal read happens, Enforcer returns 0
as the result of this read.  With this option,
Enforcer will return $ABADFEED as the read data.
This option can make programs with Enforcer hits
cause even more hits.
@ENDNODE

@NODE Option_FSPACE
@TITLE "Option: FSPACE"
FSPACE/S

This option will make the special $00F00000 address
space available for writing to.  This is useful for
those people with $00F00000 boards.  Mainly Commodore
internal development work -- should only be used
in that enviroment.
@ENDNODE

@NODE Option_VERBOSE
@TITLE "Option: VERBOSE"
VERBOSE/S

This option will make Enforcer display information
as to the mapping of the I/O boards and other
technical information.  This information maybe useful
in specialized debugging.
@ENDNODE

@NODE Option_LED
@TITLE "Option: LED"
LED/K/N

This option lets you specify the speed at which
the LED will be toggled for each Enforcer hit.
The default is 1 (which is like it always was)
Setting it to 0 will make Enforcer not touch
the LED.  Using a larger value will make the
flash take longer (such that it can be noticed
when doing I/O models other than the default
serial output)  The time that the flash will
take is a bit more than 1.3 microseconds times
the number.  So 1000 will be a bit more than
1.3 milliseconds.  (Or 1000000 is a bit more than
1.3 seconds.)
@ENDNODE

@NODE Option_PARALLEL
@TITLE "Option: PARALLEL"
PARALLEL/S

This option will make Enforcer use the parallel port
hardware rather than the serial port for output.
@ENDNODE

@NODE Option_RAWIO
@TITLE "Option: RAWIO"
RAWIO/S

This option will make Enforcer stuff the hit report
into an internal buffer and then from the main
Enforcer process output the results via the
RawPutChar() EXEC debugging LVO.  Since the output
happens on the Enforcer task it is possible for a
hit that ends in a system crash to not be able to
be reported.  This option is here such that tools
which can redirect debugging output can redirect
the Enforcer output too.
@ENDNODE

@NODE Option_FILE
@TITLE "Option: FILE"
FILE/K

This option will make Enforcer output the hit report
but to a file insted of sending it to the hardware
directly or using the @{"RAWIO" link Option_RAWIO} LVO.  A good example of
such a file is CON:0/0/640/100/HIT/AUTO/WAIT.
Another thing that can be done is to have a program
sit on a named pipe and have Enforcer output to it.
This program can then do whatever it feels like with
the Enforcer hits.  (Such as decode them, etc.)
*NOTE*  It is not a good idea to have Enforcer hits
go to a file on a disk as if the system crashes
during/after the Enforcer hit, the disk may
become corrupt.
@ENDNODE

@NODE Option_STDIO
@TITLE "Option: STDIO"
STDIO/S

This option will make Enforcer output the hit report
to STDOUT.  This option only works from the CLI as it
requires STDOUT.  It is best used with redirection or
pipes.
@ENDNODE

@NODE Option_BUFFERSIZE
@TITLE "Option: BUFFERSIZE"
BUFFERSIZE/K/N

This lets you set Enforcer's internal output buffer
for the special I/O options.  This option is only
valid with the @{"RAWIO" link Option_RAWIO}, @{"FILE" link Option_FILE}, or @{"STDIO" link Option_STDIO} options.
The minimum setting is 8000.  The default is 8000.
Having the right amount of buffer is rather
important for the special I/O modes.  The reason
is due to the fact that no operating system calls
can be made from a bus error.  Thus, in the
special I/O mode, Enforcer must store the output
in this buffer and, via some special magic,
wake up the Enforcer task to read the buffer and
write it out as needed.  However, if a task is
in Forbid() or Disable() when the Enforcer hit
happens, the Enforcer task will not be able to
output the results of the hit.  This buffer lets
a number of hits happen even if the Enforcer task
was unable to do the I/O.  If the number of
hits that happen before the I/O was able to
run gets too large, the last few hits will either
be cut off completely or contain only partial
information.
@ENDNODE

@NODE Option_INTRO
@TITLE "Option: INTRO"
INTRO/K

This optional introduction string will be output
at the start of every Enforcer hit.  For example:
INTRO="*NBad Program!"   The default is no string.
@ENDNODE

@NODE Option_PRIORITY
@TITLE "Option: PRIORITY"
PRIORITY/K/N

This lets you set Enforcer's I/O task priority.
The default for this priority is 99.  In some
special cases, you may wish to adjust this.
It is, however, recommended that if you are using
one of the special I/O options (@{"RAWIO" link Option_RAWIO}, @{"FILE" link Option_FILE}, or
@{"STDIO" link Option_STDIO}) that you keep the priority rather high.
If the priority you supply is outside of the
valid task priority range (-127 to 127) Enforcer
will use the default priority.
@ENDNODE

@NODE Option_NOALERTPATCH
@TITLE "Option: NOALERTPATCH"
NOALERTPATCH/S

This option disables the patching of the EXEC
Alert() function.  Normally Enforcer will patch
this function to provide information as to what
called Alert() and to prevent the Enforcer hits
that a call to Alert() would cause.
@ENDNODE

@NODE Option_ON
@TITLE "Option: ON"
ON/S

Mainly for completeness.  If not specified, it
is assumed you want to turn ON Enforcer.
@ENDNODE

@NODE Option_QUIT
@TITLE "Option: QUIT"
QUIT=OFF/S

Tells Enforcer to turn off.  Enforcer can also be
stopped by sending a CTRL-C to its process.
@ENDNODE

@NODE Output
@TITLE "Example Enforcer output"
Example Enforcer output

03-Apr-93  21:26:18
WORD-WRITE to  00000000        data=4444       PC: 07895CA4
USP:  078D692C SR: 0000 SW: 0729  (U0)(-)(-)  TCB: 078A2690
Data: DDDD0000 DDDD1111 DDDD2222 DDDD3333 DDDD4444 DDDD5555 DDDD6666 DDDD7777
Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 AAAA5555 07800804 --------
Stck: 00000000 07848E1C 00009C40 078A30B4 BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB
Stck: BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 078E9048 00011DA8 DEADBEEF
----> 07895CA4 - "lawbreaker"  Hunk 0000 Offset 0000007C
PC-8: AAAA1111 247CAAAA 2222267C AAAA3333 287CAAAA 44442A7C AAAA5555 31C40000
PC *: 522E0127 201433FC 400000DF F09A522E 012611C7 00CE4EAE FF7642B8 0324532E
Name: "New_Shell"  CLI: "lawbreaker"  Hunk 0000 Offset 0000007C

LONG-READ from AAAA4444                        PC: 07895CA8
USP:  078D692C SR: 0015 SW: 0749  (U0)(F)(-)  TCB: 078A2690
Data: DDDD0000 DDDD1111 DDDD2222 DDDD3333 DDDD4444 DDDD5555 DDDD6666 DDDD7777
Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 AAAA5555 07800804 --------
Stck: 00000000 07848E1C 00009C40 078A30B4 BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB
Stck: BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 078E9048 00011DA8 DEADBEEF
----> 07895CA8 - "lawbreaker"  Hunk 0000 Offset 00000080
PC-8: 247CAAAA 2222267C AAAA3333 287CAAAA 44442A7C AAAA5555 31C40000 522E0127
PC *: 201433FC 400000DF F09A522E 012611C7 00CE4EAE FF7642B8 0324532E 01266C08
Name: "New_Shell"  CLI: "lawbreaker"  Hunk 0000 Offset 00000080

Here is a breakdown of what these reports are saying:

In the first report, the first line is the date stamp.

The first line of each report describes the access violation
and where it happened from.  In the case of a WRITE, the data
that was being written will be displayed as well.  If an instruction
mode access caused the fault, there will be an (INST) in the line.

The first line may also contain the BUS ERROR message.  This will
be displayed when an address that is valid in the system lists
causes a physical bus fault during the access.  This usually
will happen with plug-in cards or when a hardware problem causes
some form of system fault.  Watch out, if this does show up, your
system may be unstable and/or unreliable.

The second line (starts USP:) displays the USER stack pointer (USP),
the status register (SR:), the special status word (SW:).  It then
displays the supervisor/user state and the interrupt level.  This
will be from (U0) to (U7) or (S0) to (S7)  (S=Supervisor)  Next
is the forbid state (F=forbid, -=not) and the disable state (D or -)
of the task that was running when the access fault took place.
Finally, the task control block address is displayed (TCB:)

The next two lines contain the data and address register dumps from
when the access fault happened.  Note that A7 is not listed here.
It is the stack pointer and is listed as USP: in the line above.

Then come the lines of stack backtrace.  These lines show the
data on the stack.  If the stack is in invalid memory, Enforcer will
display a message to that fact.

If @{"SegTracker" link SegTracker} was installed before Enforcer, the "---->" lines
will display in which seglist the given addresses are in based on the
global tracking that @{"SegTracker" link SegTracker} does.  (See docs on @{"SegTracker" link SegTracker})
If no seglist match is found, no lines will be displayed.
One line will be displayed for each of the stack longwords asked
for (see the STACKCHECK option) and one line for the PC address of
the Enforcer hit.  (The PC line is always checked for is @{"SegTracker" link SegTracker}
is installed.)  The lines are in order: hit, first stack find,
second stack find, etc.  This is useful for tracking down who
called the routine that caused the Enforcer hit.

Next, optionally, comes the data around the program counter when the
access fault happened.  The first line (PC-8:) is the 8 long-words
before the program counter.  The second line starts at the program
counter and goes for 8 long words.

The last line displays the name of the task that was running when
the access fault took place.  If the task was a CLI, it will display
the name of the CLI command that was running.  If the access fault
was found to have happened within the seglist of a loaded program,
the segment number and the offset from the start of the segment will
be displayed.  (Note that this works for any LoadSeg()'ed process)

Note that the name will display as "Processor Interrupt Level x"
if the access happened in an interrupt.

25-Jul-93  17:15:06
Alert !! Alert 35000000     TCB: 07642F70     USP: 07657C10
Data: 00000000 DDDD1111 DDDD2222 DDDD3333 0763852A DDDD5555 DDDD6666 35000000
Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 0763852A 07400810 --------
Stck: 076385A0 00000000 0752EE9A 00002800 07643994 00000000 0762F710 076305F0
----> 076385A0 - "lawbreaker"  Hunk 0000 Offset 00000098

This output happens when a program or the OS calls the EXEC Alert
function.  Enforcer catches these calls and will display the alert
information as seen above.  (With the data and time as needed)

See also the @{"Detail Example" link DetailExample} for information.
@ENDNODE

@NODE FindSeg
@TITLE "FindSeg: A SegTracker example"
/*
 * A simple program that will "find" given addresses in the SegLists
 * This program has been compiled with SAS/C 6.3 without errors or
 * warnings.
 *
 * Compiler options:
 * DATA=FARONLY PARAMETERS=REGISTER NOSTACKCHECK
 * NOMULTIPLEINCLUDES STRINGMERGE STRUCTUREEQUIVALENCE
 * MULTIPLECHARACTERCONSTANTS DEBUG=LINE NOVERSION
 * OPTIMIZE OPTIMIZERINLOCAL NOICONS
 *
 * Linker options:
 * FindSeg.o TO FindSeg SMALLCODE SMALLDATA NODEBUG LIB LIB:sc.lib
 */
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/libraries.h>
#include <exec/semaphores.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>

#include <clib/exec_protos.h>
#include <pragmas/exec_sysbase_pragmas.h>

#include <clib/dos_protos.h>
#include <pragmas/dos_pragmas.h>

#include <string.h>

#include "FindSeg_rev.h"

#define EXECBASE (*(struct ExecBase **)4)

typedef char (* __asm SegTrack(register __a0 ULONG,
                               register __a1 ULONG *,
                               register __a2 ULONG *));

struct SegSem
{
struct SignalSemaphore seg_Semaphore;
       SegTrack        *seg_Find;
};

#define SEG_SEM "SegTracker"

#define TEMPLATE "FIND/M" VERSTAG

#define OPT_FIND  0
#define OPT_COUNT 1

ULONG cmd(void)
{
struct ExecBase *SysBase;
struct Library  *DOSBase;
struct RDArgs   *rdargs;
       ULONG    rc=RETURN_FAIL;
struct SegSem   *segSem;
       char     **hex;
       LONG     opts[OPT_COUNT];

  SysBase = EXECBASE;
  if (DOSBase = OpenLibrary("dos.library",37))
  {
    memset((char *)opts, 0, sizeof(opts));

    if (!(rdargs = ReadArgs(TEMPLATE, opts, NULL)))
    {
      PrintFault(IoErr(),NULL);
    }
    else if (CheckSignal(SIGBREAKF_CTRL_C))
    {
      PrintFault(ERROR_BREAK,NULL);
    }
    else if (segSem=(struct SegSem *)FindSemaphore(SEG_SEM))
    {
      rc=RETURN_OK;
      if (opts[OPT_FIND])
      {
        for (hex=(char **)opts[OPT_FIND];(*hex);hex++)
        {
        char  *p;
        ULONG val;
        ULONG tmp[4];
        ULONG c;

          val=0;
          p=*hex;
          if (*p=='$') p++; /* Support $hex */
          while (*p)
          {
            c=(ULONG)*p;
            if ((c>='a') && (c<='f')) c-=32;
            c-='0';
            if (c>9)
            {
              c-=7;
              if (c<10) c=16;
            }

            if (c<16)
            {
              val=(val << 4) + c;
              p++;
            }
            else
            {
              val=0;
              p=&p[strlen(p)];
            }
          }

          /*
           * Ok, we need to do this within Forbid()
           * as segments can unload at ANY time, including
           * during AllocMem(), so we use a stack buffer...
           *
           */
          Forbid();
          if (p=(*segSem->seg_Find)(tmp[0]=val,&tmp[2],&tmp[3]))
          {
          char Buffer[200];

            stccpy(Buffer,p,200);
            tmp[1]=(ULONG)Buffer;
            VPrintf("$%08lx - %s : Hunk %ld, Offset $%08lx",tmp);

            /*
             * Now get the SegList address by passing the
             * same pointer for both hunk & offset.  Note
             * that this is only in the newer SegTracker
             * To test if this worked, check if the result
             * of this call is either a hunk or an offset.
             */
            (*segSem->seg_Find)(val,&tmp[0],&tmp[0]);
            /*
             * This "kludge" is for compatibility reasons
             * Check if result is the same as either the hunk
             * or the offset.  If so, do not print it...
             */
            if ((tmp[0]!=tmp[2]) && (tmp[0]!=tmp[3]))
            {
              VPrintf(", SegList $%08lx",tmp);
            }

            PutStr("\n");
          }
          else VPrintf("$%08lx - Not found\n",tmp);
          Permit();
        }
      }
    }
    else PutStr("Could not find SegTracker semaphore.\n");

    if (rdargs) FreeArgs(rdargs);
    CloseLibrary(DOSBase);
  }
  else if (DOSBase=OpenLibrary("dos.library",0))
  {
    Write(Output(),"Requires Kickstart 2.04 (37.175) or later.\n",43);
    CloseLibrary(DOSBase);
  }

  return(rc);
}
@ENDNODE

@NODE Quotes
@TITLE "Famous MKSoft Quotes"

Some of my quotes that have been in my signatures in the past:

Quantum Physics:  The Dreams that Stuff is made of. - Michael Sinz

"A master's secrets are only as good as the
 master's ability to explain them to others" - Michael Sinz

"Can't I just bend one of the rules?" said the student.
The Master just looked back at him with a sad expression. - Michael Sinz

From the home of the imaginary deadlines:
"It will take 2i weeks to do that project." - Michael Sinz

By doing the impossible one just proves the point
that one can not do the impossible. - Michael Sinz


_________________________________________________________________________

Some other quotes that I have used but did not come up with:

When one does business in the vicinity of a gorilla, you
spend much of your time muttering, "Nice gorilla..."

HELP!  I am starting to like it here...

Eloquence is vehement simplicity

Programming is like sex:
One mistake and you have to support it for life.

I multitask, therefor we are.
@ENDNODE

@NODE Copyright
@TITLE "Enforcer - Copyright © 1992-1993"

Enforcer - Copyright © 1992-1993 - Michael Sinz
           Copyright © 1992-1993 - Commodore-Amiga, Inc.

The original Enforcer was written by Bryce Nesbitt.  It was instrumental
to the development of 2.04 and to the improvement in the quality of
software on the Amiga.  It was Copyright © 1991 - Commodore-Amiga, Inc.

Enforcer V37 is a completely new set of code designed to provide even
more debugging capabilities across more hardware configurations and
with more options.  Michael Sinz designed and developed Enforcer V37.
Enforcer V37.1 to V37.42 are Copyright © 1992-1993 - Commodore-Amiga, Inc.

Enforcer V37.43 and up is still being developed by Michael Sinz,
however, Michael is no longer working for Commodore.  As such,
all changes and enhancements to Enforcer as of version 37.43
are Copyright © 1992-1993 - Michael Sinz

Enforcer and the tools and documentation in the Enforcer archive are
*not* public domain.  They are Copyright © 1992-1993 - Michael Sinz.

Enforcer.guide - Copyright © 1993 - Michael Sinz

Permission is hereby granted to distribute the Enforcer archive
containing the executables and documentation for non-commercial purposes
so long as the archive and its contents are not modified in any way.

Enforcer and related tools may not be distributed for profit.
@ENDNODE

@NODE DetailExample
@TITLE "Detail Example Hit"

Example @{"Enforcer" link Enforcer} Hit:  Click on the field for explaination.

@{"25-Jul-93  17:15:04" link Output_DateStamp}
@{"WORD-WRITE" link Output_Write} to @{"00000000" link Output_Address}    @{"data=0000" link Output_WriteData}        @{"PC: 0763857C" link Output_PC}    @{"----BUS ERROR----" link Output_BusError}
@{"USP: " link Output_A7}@{"07657C14" link Output_A7}@{"SR: 0004" link Output_SR}@{"SW: 04C1" link Output_SW} @{"(U0)(-)(-)" link Output_Decode} @{"TCB: 07642F70" link Output_TCB}
@{"Data:" link Output_DataRegs}@{"DDDD0000" link Output_D0}@{"DDDD1111" link Output_D1}@{"DDDD2222" link Output_D2}@{"DDDD3333" link Output_D3}@{"0763852A" link Output_D4}@{"DDDD5555" link Output_D5}@{"DDDD6666" link Output_D6}@{"DDDD7777" link Output_D7}
@{"Addr:" link Output_AddrRegs}@{"AAAA0000" link Output_A0}@{"AAAA1111" link Output_A1}@{"AAAA2222" link Output_A2}@{"AAAA3333" link Output_A3}@{"AAAA4444" link Output_A4}@{"0763852A" link Output_A5}@{"07400810" link Output_A6}@{"--------" link Output_A7}
@{"Stck:" link Output_Stack}@{"00000000" link Output_StackWord}@{"0752EE9A" link Output_StackWord}@{"00002800" link Output_StackWord}@{"07643994" link Output_StackWord}@{"00000000" link Output_StackWord}@{"076786D8" link Output_StackWord}@{"000208B0" link Output_StackWord}@{"2EAC80EE" link Output_StackWord}
@{"Stck:" link Output_Stack}@{"487AFD12" link Output_StackWord}@{"486C82C4" link Output_StackWord}@{"4EBA3D50" link Output_StackWord}@{"4EBAEA28" link Output_StackWord}@{"4FEF0014" link Output_StackWord}@{"52ACE2E4" link Output_StackWord}@{"204D43EC" link Output_StackWord}@{"88BC203C" link Output_StackWord}
@{"---->" link Output_SegTracker}@{"0763857C" link Output_SegTrackerAddress} - "@{"lawbreaker" link Output_SegTrackerName}" @{"Hunk 0000" link Output_SegTrackerHunk} @{"Offset 00000074" link Output_SegTrackerOffset}
@{"PC-8:" link Output_ShowPC}@{"2222263C" link Output_ShowPC_M8}@{"DDDD3333" link Output_ShowPC_M7}@{"280D2A3C" link Output_ShowPC_M6}@{"DDDD5555" link Output_ShowPC_M5}@{"2C3CDDDD" link Output_ShowPC_M4}@{"66662E3C" link Output_ShowPC_M3}@{"DDDD7777" link Output_ShowPC_M2}@{"31C00000" link Output_ShowPC_M1}
@{"PC *:" link Output_ShowPC}@{"4EAEFF7C" link Output_ShowPC_P0}@{"20144EAE" link Output_ShowPC_P1}@{"FF8811C1" link Output_ShowPC_P2}@{"01014EAE" link Output_ShowPC_P3}@{"FF7621C0" link Output_ShowPC_P4}@{"01024EAE" link Output_ShowPC_P5}@{"FF822E3C" link Output_ShowPC_P6}@{"35000000" link Output_ShowPC_P7}
@{"Name:" link Output_Name}"@{"Shell" link Output_TaskName}" CLI: "@{"LawBreaker" link Output_CLIName}" @{"Hunk 0000" link Output_SegTrackerHunk} @{"Offset 00000074" link Output_SegTrackerOffset}

And, for Alert hits:

@{"25-Jul-93  17:15:06" link Output_DateStamp}
@{"Alert" link Output_Alert}!!@{"Alert" link Output_Alert} @{"35000000" link Output_AlertNum}   @{"TCB: 07642F70" link Output_TCB}    @{"USP: 07657C10" link Output_A7}
@{"Data:" link Output_DataRegs}@{"DDDD0000" link Output_D0}@{"DDDD1111" link Output_D1}@{"DDDD2222" link Output_D2}@{"DDDD3333" link Output_D3}@{"0763852A" link Output_D4}@{"DDDD5555" link Output_D5}@{"DDDD6666" link Output_D6}@{"35000000" link Output_D7}
@{"Addr:" link Output_AddrRegs}@{"AAAA0000" link Output_A0}@{"AAAA1111" link Output_A1}@{"AAAA2222" link Output_A2}@{"AAAA3333" link Output_A3}@{"AAAA4444" link Output_A4}@{"0763852A" link Output_A5}@{"07400810" link Output_A6}@{"--------" link Output_A7}
@{"Stck:" link Output_Stack}@{"076385A0" link Output_StackWord}@{"00000000" link Output_StackWord}@{"0752EE9A" link Output_StackWord}@{"00002800" link Output_StackWord}@{"07643994" link Output_StackWord}@{"00000000" link Output_StackWord}@{"0762F710" link Output_StackWord}@{"076305F0" link Output_StackWord}
@{"---->" link Output_SegTracker}@{"076385A0" link Output_SegTrackerAddress} - "@{"lawbreaker" link Output_SegTrackerName}" @{"Hunk 0000" link Output_SegTrackerHunk} @{"Offset 00000098" link Output_SegTrackerOffset}


Note that @{"Enforcer" link Enforcer} hit output is very configurable.  The above example hit
was produced with options:  @{"SHOWPC" link Option_SHOWPC} @{"DATESTAMP" link Option_DATESTAMP} @{"STACKCHECK" link Option_STACKCHECK} @{"STACKLINES=2" link Option_STACKLINES}
Here are some examples of different output configurations:

Enforcer output with the TINY option:   (Commandline: ENFORCER @{"TINY" link Option_TINY})

@{"WORD-WRITE" link Output_Write} to @{"00000000" link Output_Address}    @{"data=0000" link Output_WriteData}        @{"PC: 0763857C" link Output_PC}


Enforcer output with the SMALL option:  (Commandline: ENFORCER @{"SMALL" link Option_SMALL})

@{"WORD-WRITE" link Output_Write} to @{"00000000" link Output_Address}    @{"data=0000" link Output_WriteData}        @{"PC: 0763857C" link Output_PC}
@{"USP: " link Output_A7}@{"07657C14" link Output_A7}@{"SR: 0004" link Output_SR}@{"SW: 04C1" link Output_SW} @{"(U0)(-)(-)" link Output_Decode} @{"TCB: 07642F70" link Output_TCB}
@{"Name:" link Output_Name}"@{"Shell" link Output_TaskName}" CLI: "@{"LawBreaker" link Output_CLIName}" @{"Hunk 0000" link Output_SegTrackerHunk} @{"Offset 00000074" link Output_SegTrackerOffset}


Enforcer output with DEFAULT options:   (Commandline: ENFORCER)

@{"WORD-WRITE" link Output_Write} to @{"00000000" link Output_Address}    @{"data=0000" link Output_WriteData}        @{"PC: 0763857C" link Output_PC}
@{"USP: " link Output_A7}@{"07657C14" link Output_A7}@{"SR: 0004" link Output_SR}@{"SW: 04C1" link Output_SW} @{"(U0)(-)(-)" link Output_Decode} @{"TCB: 07642F70" link Output_TCB}
@{"Data:" link Output_DataRegs}@{"DDDD0000" link Output_D0}@{"DDDD1111" link Output_D1}@{"DDDD2222" link Output_D2}@{"DDDD3333" link Output_D3}@{"0763852A" link Output_D4}@{"DDDD5555" link Output_D5}@{"DDDD6666" link Output_D6}@{"DDDD7777" link Output_D7}
@{"Addr:" link Output_AddrRegs}@{"AAAA0000" link Output_A0}@{"AAAA1111" link Output_A1}@{"AAAA2222" link Output_A2}@{"AAAA3333" link Output_A3}@{"AAAA4444" link Output_A4}@{"0763852A" link Output_A5}@{"07400810" link Output_A6}@{"--------" link Output_A7}
@{"Stck:" link Output_Stack}@{"00000000" link Output_StackWord}@{"0752EE9A" link Output_StackWord}@{"00002800" link Output_StackWord}@{"07643994" link Output_StackWord}@{"00000000" link Output_StackWord}@{"076786D8" link Output_StackWord}@{"000208B0" link Output_StackWord}@{"2EAC80EE" link Output_StackWord}
@{"Stck:" link Output_Stack}@{"487AFD12" link Output_StackWord}@{"486C82C4" link Output_StackWord}@{"4EBA3D50" link Output_StackWord}@{"4EBAEA28" link Output_StackWord}@{"4FEF0014" link Output_StackWord}@{"52ACE2E4" link Output_StackWord}@{"204D43EC" link Output_StackWord}@{"88BC203C" link Output_StackWord}
@{"---->" link Output_SegTracker}@{"0763857C" link Output_SegTrackerAddress} - "@{"lawbreaker" link Output_SegTrackerName}" @{"Hunk 0000" link Output_SegTrackerHunk} @{"Offset 00000074" link Output_SegTrackerOffset}
@{"Name:" link Output_Name}"@{"Shell" link Output_TaskName}" CLI: "@{"LawBreaker" link Output_CLIName}" @{"Hunk 0000" link Output_SegTrackerHunk} @{"Offset 00000074" link Output_SegTrackerOffset}
@ENDNODE

@NODE Output_DateStamp
@TITLE "Enforcer Output: Date Stamp"

The date stamp field, if enabled, is at the start of the @{"Enforcer" link Enforcer} hit.
The time is only exact to +/- 1 second.
@ENDNODE

@NODE Output_Write
@TITLE "Enforcer Output: Write Hit"

This tells you that the @{"Enforcer" link Enforcer} Hit was a READ from or WRITE to memory.
The possible writes are:

        -- WRITE -                  - READ --
        BYTE-WRITE -  8-bit write - BYTE-READ
        WORD-WRITE - 16-bit write - WORD-READ
        LONG-WRITE - 32-bit write - LONG-READ
        LINE-WRITE - 68040 only   - LINE-READ
@ENDNODE

@NODE Output_Address
@TITLE "Enforcer Output: Address hit"

This field in the output shows the illegal address that was
accessed which triggered the @{"Enforcer" link Enforcer} report.
@ENDNODE

@NODE Output_WriteData
@TITLE "Enforcer Output: Data Write"

On an illegal WRITE to memory, the value that was attempted to
be written will be displayed here.  The size of this field
changes to match the size of the write.  68040 LINE writes are
not supported in this field.
@ENDNODE

@NODE Output_PC
@TITLE "Enforcer Output: Program Counter"

This field displays the program counter at the time of the MMU
trap of the invalid axxess.  Note that this address is not always
the exact instruction that caused the hit.  See the various
notes for your processor for more details.

     @{" General Notes " link Notes1}
     @{" 68020 Notes " link Notes2}
     @{" 68030 Notes " link Notes3}
     @{" 68040 Notes " link Notes4}
@ENDNODE

@NODE Output_BusError
@TITLE "Enforcer Output: Bus Error"

This field normally would never be seen by most people.  It is generated
when a legal memory address causes a physical bus fault.  This usually
can only happen when designing hardware or a part of the system hardware
has become unreliable.  Watch out, if this does show up, your system may
be unstable and/or unreliable.

For more information on bus faults, see the Motorola CPU Hardware
Design handbook.
@ENDNODE

@NODE Output_SR
@TITLE "Enforcer Output: CPU Status Register"

This is the CPU status register as found on the MMU trap
stack frame.  It contains the condition flags and the
current mode/etc.
@ENDNODE

@NODE Output_SW
@TITLE "Enforcer Output: Special Status Word"

This is the special status word that is part of the MMU
trap frame.  Check your CPU manuals for more details as
to what this word contains.  Note that it is different
for the different versions of the 680x0 family.
@ENDNODE

@NODE Output_Decode
@TITLE "Enforcer Output: Special information"

This field contains special task information.  This is
useful for determining what is going on at the time of the hit.

     (U0)(-)(-)
      ^^  ^  ^
      ||  |  |
      ||  |  +-- This will have a D if the task is DISABLE state
      ||  +----- This will have a F if the task is FORBID state
      |+-------- This is the processor IPL level (0 is normal code)
      +--------- This is the processor state: U=user, S=supervisor
@ENDNODE

@NODE Output_TCB
@TITLE "Enforcer Output: Task Control Block"

This is the address of the Task Control Block, also known
as the task structure.  (See exec/tasks.h)  This is used by
@{"Enforcer" link Enforcer} to tell you who caused the hit.
@ENDNODE

@NODE Output_DataRegs
@TITLE "Enforcer Output: Data Register Dump"

This line contains a dump of the data registers at the time
of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_D0
@TITLE "Enforcer Output: D0 Register"

The D0 register of the 680x0 CPU.

See @{"Data:" link Output_DataRegs}
@ENDNODE

@NODE Output_D1
@TITLE "Enforcer Output: D1 Register"

The D1 register of the 680x0 CPU.

See @{"Data:" link Output_DataRegs}
@ENDNODE

@NODE Output_D2
@TITLE "Enforcer Output: D2 Register"

The D2 register of the 680x0 CPU.

See @{"Data:" link Output_DataRegs}
@ENDNODE

@NODE Output_D3
@TITLE "Enforcer Output: D3 Register"

The D3 register of the 680x0 CPU.

See @{"Data:" link Output_DataRegs}
@ENDNODE

@NODE Output_D4
@TITLE "Enforcer Output: D4 Register"

The D4 register of the 680x0 CPU.

See @{"Data:" link Output_DataRegs}
@ENDNODE

@NODE Output_D5
@TITLE "Enforcer Output: D5 Register"

The D5 register of the 680x0 CPU.

See @{"Data:" link Output_DataRegs}
@ENDNODE

@NODE Output_D6
@TITLE "Enforcer Output: D6 Register"

The D6 register of the 680x0 CPU.

See @{"Data:" link Output_DataRegs}
@ENDNODE

@NODE Output_D7
@TITLE "Enforcer Output: D7 Register"

The D7 register of the 680x0 CPU.

See @{"Data:" link Output_DataRegs}
@ENDNODE

@NODE Output_AddrRegs
@TITLE "Enforcer Output: Address Register Dump"

This line contains a dump of the address register at the
time of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_A0
@TITLE "Enforcer Output: A0 Register"

The A0 register of the 680x0 CPU.

See @{"Addr:" link Output_AddrRegs}
@ENDNODE

@NODE Output_A1
@TITLE "Enforcer Output: A1 Register"

The A1 register of the 680x0 CPU.

See @{"Addr:" link Output_AddrRegs}
@ENDNODE

@NODE Output_A2
@TITLE "Enforcer Output: A2 Register"

The A2 register of the 680x0 CPU.

See @{"Addr:" link Output_AddrRegs}
@ENDNODE

@NODE Output_A3
@TITLE "Enforcer Output: A3 Register"

The A3 register of the 680x0 CPU.

See @{"Addr:" link Output_AddrRegs}
@ENDNODE

@NODE Output_A4
@TITLE "Enforcer Output: A4 Register"

The A4 register of the 680x0 CPU.

See @{"Addr:" link Output_AddrRegs}
@ENDNODE

@NODE Output_A5
@TITLE "Enforcer Output: A5 Register"

The A5 register of the 680x0 CPU.

See @{"Addr:" link Output_AddrRegs}
@ENDNODE

@NODE Output_A6
@TITLE "Enforcer Output: A6 Register"

The A6 register of the 680x0 CPU.

See @{"Addr:" link Output_AddrRegs}
@ENDNODE

@NODE Output_A7
@TITLE "Enforcer Output: A7 Register"

The A7 register of the 680x0 CPU is also known as the
Stack Pointer or SP.  In the @{"Enforcer" link Enforcer} hit, the USER SP
(the stack of the task that caused the hit) is displayed
in the USP: field.

See @{"Addr:" link Output_AddrRegs}
@ENDNODE

@NODE Output_Stack
@TITLE "Enforcer Output: Stack Dump"

These lines contain stack dumps from the task that caused
the @{"Enforcer" link Enforcer} hit.  It can be used to figure out what the
program was doing and what routines called the current
routine by looking at the values on the stack.
@ENDNODE

@NODE Output_StackWord
@TITLE "Enforcer Output: Stack Word"

This is a longword on the stack of the task that caused the hit
See @{"Stck:" link Output_Stack} for more details.
@ENDNODE

@NODE Output_SegTracker
@TITLE "Enforcer Output: SegTracker"

This symbol "---->" identifies a line produced via the
@{"SegTracker" link SegTracker} utility.

See @{"FindHit" link FindHit} for details as to how to use this information.
@ENDNODE

@NODE Output_SegTrackerAddress
@TITLE "Enforcer Output: SegTracker Address"

This is the address that the hunk/offset describes.  This is here such
that you can cross-reference it with a value on the stack, in a register,
or the program counter.  The hunk/offset on the same line are produced
when this address is processed via @{"SegTracker" link SegTracker}.
See @{"FindHit" link FindHit} for details as to how to use this information.
@ENDNODE

@NODE Output_SegTrackerName
@TITLE "Enforcer Output: SegTracker Name"

This is the name of the file, as passed to LoadSeg, which was found to
be loaded around the address given.  See @{"FindHit" link FindHit} for details as to how
to use this information.
@ENDNODE

@NODE Output_SegTrackerHunk
@TITLE "Enforcer Output: Hunk"

This is the hunk in the load file that was loaded around the
given address.  See @{"FindHit" link FindHit} for details as to how
to use this information.
@ENDNODE

@NODE Output_SegTrackerOffset
@TITLE "Enforcer Output: Offset"

This is the offset from the start of the hunk that this address is
at within the given load file.  See @{"FindHit" link FindHit} for details as to how
to use this information.
@ENDNODE

@NODE Output_Name
@TITLE "Enforcer Output: Task/Process Name"

This line contains the decoding of the TCB into the TASK name,
the CLI command (if a CLI), and if the hit happened in the SegList
attached to the process, the hunk and offset for the hit.  Note
that this hunk/offset is not produced by @{"SegTracker" link SegTracker}.
@ENDNODE

@NODE Output_TaskName
@TITLE "Enforcer Output: Task Name"

This field contains the task name as stored in the TCB of the task
that caused the @{"Enforcer" link Enforcer} hit.  If the TCB is invalid, it will say so.
@ENDNODE

@NODE Output_CLIName
@TITLE "Enforcer Output: CLI Command Name"

This field will contain the name of the CLI command that caused the
hit if the TCB is a CLI process and there was a command loaded.
If the task is not a CLI process or no command is loaded, this
field will not be displayed.
@ENDNODE

@NODE Output_Alert
@TITLE "Enforcer Output: Alerts"

This output happens when a program or the OS calls the EXEC Alert
function.  @{"Enforcer" link Enforcer} catches these calls and will display the alert
information as seen above.  (With the data and time as needed)
@ENDNODE

@NODE Output_AlertNum
@TITLE "Enforcer Output: Alert Number"

This field contains the alert number that was generated.  Check
the include file exec/alerts.h or exec/alerts.i for details as
to how to decode this number.
@ENDNODE

@NODE Output_ShowPC
@TITLE "Enforcer Output: Show PC"

If the SHOWPC option is turned on, @{"Enforcer" link Enforcer} will dump the 8 longwords
before the program counter and the 8 longwords starting at the PC.

This can be used to help debug programs by being able to look at the
code around the hit by disassembling it.
@ENDNODE

@NODE Output_ShowPC_M8
@TITLE "Enforcer Output: Show PC-$20"

This is the longword at the memory address (PC - $20)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_M7
@TITLE "Enforcer Output: Show PC-$1C"

This is the longword at the memory address (PC - $1C)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_M6
@TITLE "Enforcer Output: Show PC-$18"

This is the longword at the memory address (PC - $18)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_M5
@TITLE "Enforcer Output: Show PC-$14"

This is the longword at the memory address (PC - $14)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_M4
@TITLE "Enforcer Output: Show PC-$10"

This is the longword at the memory address (PC - $10)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_M3
@TITLE "Enforcer Output: Show PC-$0C"

This is the longword at the memory address (PC - $0C)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_M2
@TITLE "Enforcer Output: Show PC-$08"

This is the longword at the memory address (PC - $08)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_M1
@TITLE "Enforcer Output: Show PC-$04"

This is the longword at the memory address (PC - $04)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_P0
@TITLE "Enforcer Output: Show PC+$00"

This is the longword at the memory address (PC)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_P1
@TITLE "Enforcer Output: Show PC+$04"

This is the longword at the memory address (PC + $04)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_P2
@TITLE "Enforcer Output: Show PC+$08"

This is the longword at the memory address (PC + $08)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_P3
@TITLE "Enforcer Output: Show PC+$0C"

This is the longword at the memory address (PC + $0C)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_P4
@TITLE "Enforcer Output: Show PC+$10"

This is the longword at the memory address (PC + $10)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_P5
@TITLE "Enforcer Output: Show PC+$14"

This is the longword at the memory address (PC + $14)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_P6
@TITLE "Enforcer Output: Show PC+$18"

This is the longword at the memory address (PC + $18)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Output_ShowPC_P7
@TITLE "Enforcer Output: Show PC+$1C"

This is the longword at the memory address (PC + $1C)
where PC is the @{"Program Counter" link Output_PC} of the @{"Enforcer" link Enforcer} hit.
@ENDNODE

@NODE Index
@TITLE "Enforcer.guide Index"
Index of all nodes in the Enforcer.guide document:

@{"  68020 Notes                             " link Notes2}
@{"  68030 Notes                             " link Notes3}
@{"  68040 Notes                             " link Notes4}
@{"  Debuggers: Not causing a hit            " link Debuggers2}
@{"  Debuggers: Trapping a hit               " link Debuggers1}
@{"  Detail Example Hit                      " link DetailExample}
@{"  Enforcer                                " link Enforcer}
@{"  Enforcer - Copyright © 1992-1993        " link Copyright}
@{"  Enforcer Beta Testers                   " link Credits_Testers}
@{"  Enforcer Credits                        " link Credits}
@{"  Enforcer Documentation                  " link MAIN}
@{"  Enforcer Output: A0 Register            " link Output_A0}
@{"  Enforcer Output: A1 Register            " link Output_A1}
@{"  Enforcer Output: A2 Register            " link Output_A2}
@{"  Enforcer Output: A3 Register            " link Output_A3}
@{"  Enforcer Output: A4 Register            " link Output_A4}
@{"  Enforcer Output: A5 Register            " link Output_A5}
@{"  Enforcer Output: A6 Register            " link Output_A6}
@{"  Enforcer Output: A7 Register            " link Output_A7}
@{"  Enforcer Output: Address hit            " link Output_Address}
@{"  Enforcer Output: Address Register Dump  " link Output_AddrRegs}
@{"  Enforcer Output: Alert Number           " link Output_AlertNum}
@{"  Enforcer Output: Alerts                 " link Output_Alert}
@{"  Enforcer Output: Bus Error              " link Output_BusError}
@{"  Enforcer Output: CLI Command Name       " link Output_CLIName}
@{"  Enforcer Output: CPU Status Register    " link Output_SR}
@{"  Enforcer Output: D0 Register            " link Output_D0}
@{"  Enforcer Output: D1 Register            " link Output_D1}
@{"  Enforcer Output: D2 Register            " link Output_D2}
@{"  Enforcer Output: D3 Register            " link Output_D3}
@{"  Enforcer Output: D4 Register            " link Output_D4}
@{"  Enforcer Output: D5 Register            " link Output_D5}
@{"  Enforcer Output: D6 Register            " link Output_D6}
@{"  Enforcer Output: D7 Register            " link Output_D7}
@{"  Enforcer Output: Data Register Dump     " link Output_DataRegs}
@{"  Enforcer Output: Data Write             " link Output_WriteData}
@{"  Enforcer Output: Date Stamp             " link Output_DateStamp}
@{"  Enforcer Output: Hunk                   " link Output_SegTrackerHunk}
@{"  Enforcer Output: Offset                 " link Output_SegTrackerOffset}
@{"  Enforcer Output: Program Counter        " link Output_PC}
@{"  Enforcer Output: SegTracker             " link Output_SegTracker}
@{"  Enforcer Output: SegTracker Address     " link Output_SegTrackerAddress}
@{"  Enforcer Output: SegTracker Name        " link Output_SegTrackerName}
@{"  Enforcer Output: Show PC                " link Output_ShowPC}
@{"  Enforcer Output: Show PC+$00            " link Output_ShowPC_P0}
@{"  Enforcer Output: Show PC+$04            " link Output_ShowPC_P1}
@{"  Enforcer Output: Show PC+$08            " link Output_ShowPC_P2}
@{"  Enforcer Output: Show PC+$0C            " link Output_ShowPC_P3}
@{"  Enforcer Output: Show PC+$10            " link Output_ShowPC_P4}
@{"  Enforcer Output: Show PC+$14            " link Output_ShowPC_P5}
@{"  Enforcer Output: Show PC+$18            " link Output_ShowPC_P6}
@{"  Enforcer Output: Show PC+$1C            " link Output_ShowPC_P7}
@{"  Enforcer Output: Show PC-$04            " link Output_ShowPC_M1}
@{"  Enforcer Output: Show PC-$08            " link Output_ShowPC_M2}
@{"  Enforcer Output: Show PC-$0C            " link Output_ShowPC_M3}
@{"  Enforcer Output: Show PC-$10            " link Output_ShowPC_M4}
@{"  Enforcer Output: Show PC-$14            " link Output_ShowPC_M5}
@{"  Enforcer Output: Show PC-$18            " link Output_ShowPC_M6}
@{"  Enforcer Output: Show PC-$1C            " link Output_ShowPC_M7}
@{"  Enforcer Output: Show PC-$20            " link Output_ShowPC_M8}
@{"  Enforcer Output: Special information    " link Output_Decode}
@{"  Enforcer Output: Special Status Word    " link Output_SW}
@{"  Enforcer Output: Stack Dump             " link Output_Stack}
@{"  Enforcer Output: Stack Word             " link Output_StackWord}
@{"  Enforcer Output: Task Control Block     " link Output_TCB}
@{"  Enforcer Output: Task Name              " link Output_TaskName}
@{"  Enforcer Output: Task/Process Name      " link Output_Name}
@{"  Enforcer Output: Write Hit              " link Output_Write}
@{"  Example Enforcer output                 " link Output}
@{"  Famous MKSoft Quotes                    " link Quotes}
@{"  FindHit                                 " link FindHit}
@{"  FindSeg: A SegTracker example           " link FindSeg}
@{"  General Notes                           " link Notes1}
@{"  LawBreaker                              " link LawBreaker}
@{"  Move4K                                  " link Move4K}
@{"  Option: AREGCHECK                       " link Option_AREGCHECK}
@{"  Option: BUFFERSIZE                      " link Option_BUFFERSIZE}
@{"  Option: DATESTAMP                       " link Option_DATESTAMP}
@{"  Option: DEADLY                          " link Option_DEADLY}
@{"  Option: DREGCHECK                       " link Option_DREGCHECK}
@{"  Option: FILE                            " link Option_FILE}
@{"  Option: FSPACE                          " link Option_FSPACE}
@{"  Option: INTRO                           " link Option_INTRO}
@{"  Option: LED                             " link Option_LED}
@{"  Option: NOALERTPATCH                    " link Option_NOALERTPATCH}
@{"  Option: ON                              " link Option_ON}
@{"  Option: PARALLEL                        " link Option_PARALLEL}
@{"  Option: PRIORITY                        " link Option_PRIORITY}
@{"  Option: QUIET                           " link Option_QUIET}
@{"  Option: QUIT                            " link Option_QUIT}
@{"  Option: RAWIO                           " link Option_RAWIO}
@{"  Option: SHOWPC                          " link Option_SHOWPC}
@{"  Option: SMALL                           " link Option_SMALL}
@{"  Option: STACKCHECK                      " link Option_STACKCHECK}
@{"  Option: STACKLINES                      " link Option_STACKLINES}
@{"  Option: STDIO                           " link Option_STDIO}
@{"  Option: TINY                            " link Option_TINY}
@{"  Option: VERBOSE                         " link Option_VERBOSE}
@{"  SegTracker                              " link SegTracker}
@ENDNODE
