Swat, a BCPL-oriented debugger




Swat is  a debugger meant  to be used  with the Alto  operating system.
While many of  its features are  BCPL oriented, it  can be used  on any
Alto  program. This  document describes  version 31  of Swat,  which is
compatible with Operating System versions 17 and greater.



1. History


Swat was designed  and built by Jim  Morris and Allen Brown  during the
summer of 1973.  Bob Sproull added the error file mechanism  and parity
error logging during 1976.  Peter Deutsch rewrote the command processor
and  added  the  command  file facility  in  early  1977.   David Boggs
renovated  the  program,  adding  mulitple  proceed  break  points  and
TeleSwat, and Ed Taft added  the help facility in late  1978.  Everyone
agrees that the human interface  is awful.  Each person who  has worked
on Swat has added several more obscure commands while they were at it.



2. How it works


Swat is an  external debugger: with the  exception of a small  piece of
'resident' code in  your address space, it  lives in a  separate space.
When Swat is invoked, the resident saves your state on the file Swatee,
and swaps in  Swat.  References to your  memory from within Swat  go to
the Swatee file.  When you tell Swat to proceed, it saves itself on the
file Swat, swaps  you (the Swatee) in  and resumes you.  Your  state at
the time Swat got control is displayed in a window at the bottom of the
screen.   "AC0", "PC",  etc  are built-in  symbols with  which  you can
manipulate it.



3. Invocation


Swat may be applied to  any program running under the  operating system
after it has  been installed (see  Installation below).  There  are six
ways of getting its attention:

     (1)  Hold down the <control> and <left-shift> keys and then
          press the <Swat> key.

     (2)  Have your program execute the op-code 77400B.

     (3)  Invoke the Resume/S command (see below).

     (4)  Boot the file Dumper.Boot, normally by booting with the "DU"
          keys depressed.

                             ------------
                   Copyright Xerox Corporation 1982


SWAT                        April 10, 1982                            2




     (5)  Type <programName>/! to the Alto command processor.

     (6)  Call the function CallSwat. Up to 2 arguments will be printed
          as BCPL strings.  Thus CallSwat("No more memory")




4. Commands


The command scanner has suffix action symbols, all of which are control
characters  (e.g. ↑C).   "n" is  any BCPL  expression  (see Expressions
below), "$" is escape  except where noted, "cr" means  carriage return,
"lf" means line-feed.  You can abort whatever Swat is doing at any time
and get back  to the top level  command scanner by pressing  the <Swat>
key.


4.1. Help facility

Most debuggers have a terse and obscure command syntax, and Swat  is no
different.  In fact it's worse since Swat doesn't use the  DDT debugger
dialect (it uses a  subdialect of an MIT debugger  dialect--where Allen
Brown grew up).  Typing "?"  prompts you for a command  character which
Swat looks up  in the file "Swat.help".   Responding "?" to  its prompt
gives you a small table of contents for the rest of the help file.


4.2. Displaying cells

        address↑D  prints the contents of n in decimal
        address↑I  prints the contents of n as two 8-bit bytes
        address↑N  prints the contents of n as an instruction
        address↑O  prints the contents of n in octal
        address↑S  prints the contents of n as a pair of characters
        address↑V  prints address in octal and decimal

The last cell printed is called  the open cell.  ↑O, ↑D, ↑I, ↑N,  or ↑S
alone re-prints the open cell  in the appropriate format.  If  you wish
to print out a number of cells, beginning with the open cell, say n$↑D,
n$↑I, etc.  The last cell printed becomes the open cell.

   lf (↑J) opens and prints  the contents of  the next cell  (after the
           open one) in the same mode.

   ↑W      opens and prints the cell before the open cell.

   ↑A      opens and prints the cell pointed at by the open cell.

   ↑E      opens and prints  the cell at  the effective address  of the
           open cell.

The last cell that was opened by any command except LF or ↑W  is called
the last  open cell.   Often you  are stepping  through code,  follow a
pointer with  ↑E or ↑A,  look around, decide  it's not  interesting and
wish to resume  where you were before  following the pointer.   You can
get back to last open cell plus or minus one by:

   $lf ($↑J)       open and print last open cell+1.


SWAT                        April 10, 1982                            3




   $cr ($↑M)       open and print last open cell.

   $↑W             open and print last open cell-1


4.3. Changing cells

The contents  of the  open cell  (if there  is one)  may be  changed by
typing an expression for the new value followed by a cr, lf or ↑W.  A$B
followed by cr, lf or ↑W stores A lshift 8 + B into the open cell.


4.4. Searching

   n↑=     searches from the open  cell+1 for a cell whose  contents is
           n.  Prints and opens that cell.

   n$↑=    searches from  the open  cell+1 for  a cell  whose effective
           address is n.  Prints and opens that cell.

A search terminates at the  end of memory (location 176777b --  the I/O
area  is not  touched) and  can take  quite a  while: abort  by hitting
<swat>.  The  argument for a  search command is  defaulted to  the last
value searched for if omitted.


4.5. Running the program

   ↑P      resumes the program, i.e. proceeds.

   address↑G resumes the program at address, i.e. goes there.

   <procName>$<e1>$...$<en>↑C calls the BCPL procedure  "procName" with
           parameters  <e1>,...,<en> (n<6).   If  you wish  one  of the
           arguments to be a  BCPL-format string, merely enclose  it in
           quotes.  Thus OpenFile$"Com.Cm."↑C  will return a  stream on
           the file.   AC2 is  assumed to contain  a legal  stack frame
           pointer and 'procName' will  allocate a new frame on  top of
           it.   Often AC2  is not  valid (e.g.,  Swat  interrupted the
           program in the middle of allocating a frame), and  calling a
           procedure at this point may not work.  Most of the time Swat
           can detect this and warn you.

   ↑U      restores the user's  screen.  Hitting the <swat>  key brings
           back Swat.

   ↑K      forces the user program to  abort, just as if you  had typed
           <left-shift><swat> while it was running.


4.6. Break Points

A  Break point  can  be referred  to by  its  address or  by  the index
assigned  by Swat  when  the break  point  was set.   When  printing or
deleting a breakpoint, Swat  reaches out into the user's  address space
to check that the break is still there.

   address↑B       sets a break at address

   ↑B              set a break at the open cell


SWAT                        April 10, 1982                            4




   0$address↑B     deletes the break at address

   proceedCnt$address↑B sets a multiple-proceed break point at address.
                   The breakpoint will take effect when it has been hit
                   proceedCnt  times,  and  then  it  will  be deleted.
                   Passing  through  a  multiple  proceed  break  point
                   without stopping takes about 200 us.

   index$↑B        deletes the break with index index

   0$$↑B           deletes all breaks

   $$↑B            prints all broken locations.

   $↑P             removes the current break and proceeds.

   address$$↑P     sets  a one-shot  break  point at  address  and then
                   proceeds.   A one-shot  break point  is one  that is
                   removed after it is hit.

   stackIndex$↑P   sets a  break at  a BCPL return  point in  the stack
                   somewhere and proceeds from the present  break.  The
                   parameter n  specifies the  frame number,  where the
                   most recent (top) frame is 0.  Thus if ↑T  typed out
                   0:GOO+56 1:HAM+5,  1$↑P would set  a break  at HAM+6
                   and proceed.


4.7. Stack Study

See Chapter  10 of  the BCPL manual  and section  4.8 of  the Operating
System manual for the details of a BCPL stack.

   ↑T      prints the current PC  and all return addresses in  the call
           stack (symbolically),  until an  inconsistency in  the stack
           (usually  signaling  its end)  is  encountered.   After each
           return  address  is  listed  the  parameters  passed  to the
           procedure that will be returned to.  "2: 43752 137 0 Foo+45-
           -(14 177777)" means the  2nd most recent frame at  43752, of
           length 137 is procedure Foo in bank 0, called with arguments
           14 and -1 (fine point: 14 and 177777 are the first two local
           variables  in Foo's  frame,  which Foo  could  have modified
           before  Swat was  called, in  which case  they won't  be the
           values passed at call time).

   n↑T     traces a stack beginning with the frame at location n.

   index↑F prints the parameters of the nth latest stack frame and sets
           the pseudo symbol "$" (not escape) equal to the base of that
           frame.    If   ↑T   displayed   something    like   0:FOO+3,
           1:BLETCH+10,...  Type 1↑F  to see  the parameters  that were
           passed to BLETCH.   $ is set to  the base of  BLETCH's frame
           (i.e., $ points  at the frame's  back link: the  first local
           variable is in $+4.


SWAT                        April 10, 1982                            5




4.8. Symbol table

   ↑Y      prompts you for the name of a symbol file.  Type the name of
           the subsystem that's running.  If it can't find a  file with
           the name you typed, Swat appends ".syms" to it and  looks up
           the resulting file  name before reporting failure.   If BLDR
           created  the file  FOO.RUN it  also created  FOO.SYMS, which
           gives the locations of  all the static names.   Only statics
           can be used in  Swat.  There are permanent  built-in symbols
           for the interesting  page-1 and high memory  locations, BCPL
           runtime routines, and the user's state variables (AC0-3, PC,
           etc.).


4.9. Save/Restore

See 'Resumable files' below for more details:

   ↑L      prompts you for  a file name on  which it saves  the current
           Swatee.

   ↑Q      prompts you for a file name which it installs as the current
           Swatee.


4.10. The Spy Facility

The spy can be used to estimate where the time is going on a percentage
basis.  It samples the PC every 30-milliseconds.

(1)   Type ↑X and Swat will  display how much user memory it  needs for
      the metering code and tables.

(2)   Probe around to find a block of storage of the required size, and
      tell Swat by typing

                n↑X

      where n is the first word of the block.

(3)   Proceed to run the program.

(4)   Once Swat gets control again you can type

                $↑X

      to display the results and terminate the spying activity, or

                $$↑X

      to display the results so far and continue the spying.


4.11. Miscellaneous

   $↑Y     Prompts  for  the name  of  a (text)  file  from  which Swat
           commands  should  be taken.   Reading  will  continue across
           "proceeds" from breakpoints, but will be aborted if  Swat is
           invoked by the keyboard (<control><left-shift><swat>)  or by
           the standard break-point trap (77400B).


SWAT                        April 10, 1982                            6




   $$↑Y    Puts  Swat  into  TeleSwat  server  mode.   The  keyboard is
           ignored: to  regain local control  hit the <Swat>  key.  For
           more  on TeleSwat  see the  sections on  Address  Spaces and
           TeleSwat.

   n↑R     Prints the value of R or S register n.  You must have  a RAM
           for this to work.

   $↑R     Prints all of the R and S registers.

   $$↑Z    Repeats  the  message  that  was  displayed  when  Swat  was
           invoked.  This is sometimes  useful if an error  message has
           scrolled away as a result of poking around.

   $↑Z     Prints  statistics on  the symbol  table and  virtual memory
           caches.  This is mostly of interest to Swat maintainers.


4.12. Address Spaces

↑Z  prompts  for the  target address  space.  Swat  can treat  any file
created by  OutLd, any  bank of memory,  and any  host in  the internet
(with the  host's cooperation)  as the Swatee:  the address  space into
which you peer with Swat.  The syntax for address spaces is:

filename            this is 'Swatee'  for normal debugging, but  can be
                    any file created by OutLd (sysOut files (↑L) are in
                    this category), or Dumper.

Bank0               Swat itself.

Bank1...3           the extended memory banks.  These are only legal on
                    AltoII XMs.  No check is made that a  bank actually
                    exists.   If  it  doesn't,  or  if  it  hasn't been
                    written into since the Alto was powered up, you are
                    likely to get parity errors.

[host]              a  host  that  implements the  server  half  of the
                    TeleSwat protocol  (usually another  Swat).  [host]
                    can  be  either  a name:  [Boggs],  or  an internet
                    address:   [3#241#].   The   square   brackets  are
                    required: this is how Swat decides that you  mean a
                    [host] rather than a file.


4.13. Examples

X↑O↑D            prints the value of X in octal, then decimal.

func+3↑N lf lf   prints instructions 3, 4, and 5 of func.

1↑O7             sets location 1 to 7.

label↑B          sets a break at label

7562↑B           sets a break at location 7562B

SQRT$16↑C        calls the (user) function SQRT (the returned  value is
                 printed)


SWAT                        April 10, 1982                            7




label+3↑G        transfers to the third instruction after label.

0↑T              prints the PC

0↑F              prints the parameters of the most recent call

2↑F              prints  the  parameters  of  the  third  most recently
                 called procedure; then

$↑O              prints the saved stack pointer (frame!0)

$+1↑0            prints the return address (frame!1)

$+6↑O            prints  the  first  local  (if  the  procedure  has  2
                 parameters).



5. Expressions


Expressions are as in BCPL with the following exceptions

    '         means exclusive OR
    \         means REMAINDER
    |         means LSHIFT for positive arguments, RSHIFT for negative
    ~         means NOT


A string of digits is interpreted as octal unless suffixed by a "."

$ (not  escape) is  the base  of the  last opened  stack frame  (see ↑F
above).  Initially it is the last frame.

↑<static name>, "↑"  followed immediately by  a static name,  means use
the address of the static, not its value, even if it is a procedure- or
label-type static.

. is the last opened cell

PC is  the address of  the cell  containing the user  PC.  This  is the
address at which Swat will resume Swatee when you say ↑P.

AC1,...,AC3 are the addresses of the user's accumulators.

CRY is the address of the user's carry bit.

INT = on = non zero if interrupts where on when the Swat trap happened.

No function calls in expressions.

No relational operators (e.g. EQ)

No conditional expressions

No lv operator (well...see ↑<static name> above)


SWAT                        April 10, 1982                            8




5.1. Examples
.-1↑O       prints the cell before the currently open cell.

.+1↑O       is like line-feed.

AC1↑O6      sets AC1 to 6

PC↑O72
↑P          is like 72↑G

PC↑O lf lf lf lf  prints the PC and the AC's

The  conventions for  expression  evaluation are  not  truly BCPL-like.
"F↑0" will print the  first instruction of F  if BLDR thought it  was a
procedure or  label, but print  the contents of  static cell F  if BLDR
thought it was a variable.  If F started life as a variable, but  had a
procedure assigned to it you must call it by "@F↑C" instead of "F↑C".



6. Resumable Files


The file Swatee is a snapshot of a running program and can be saved for
subseqent resumption or examination.   You can create a copy  of Swatee
by using COPY or, if you are in Swat, typing ↑L and giving a file name.
This  copies Swatee  to  the named  file and  appends  some information
internal to Swat -- the current symbol table and break point data.

There are several ways to restart resumable files:

     1)  Press the boot button while holding down the keys for the
         file.

     2)  Type the command (it is interpreted by the Exec)

                              RESUME file

              If "file" is omitted Swatee is assumed.

                              RESUME/S file

              writes file onto Swatee and invokes Swat.

     3)  While in Swat, type ↑Q and give a file name. The  file is
         copied  onto Swatee  and Swat's  internal  information is
         restored to  whatever was  saved by  the ↑L  command that
         created the file.   If the file  was created in  some way
         other than  ↑L, the internal  information is reset  to an
         empty state.



7. TeleSwat


Swat implements a simple Pup protocol, TeleSwat, by which it  can treat
a machine anywhere in the internet as the Swatee (with the  consent and
cooperation of  the other  machine).  The Swatee  is made  receptive to


SWAT                        April 10, 1982                            9




control  from  the  network by  typing  $$↑Y.   The  controlling Swat's
attention is directed at it by specifying the Swatee's  network address
as the target virtual memory  (see the ↑Z command).  When you  tell the
Swatee to  proceed (↑P, ↑G,  ↑U), you loose  control: your  Swat starts
probing the Swatee  once per second, but  if the Swatee  never returns,
you must get help from someone at the other end.  Each time a packet is
sent, the cursor  is inverted to let  you know something  is happening.
Executing  the  opcode  77412b is  equivalent  to  CallSwat(string1 [],
string2 []) followed by $$↑Y.



8. Desperation Debugging


If the resident is broken so you can't  use <Left-Shift><Control><Swat>
to get to Swat to see  what went wrong, then you are  desperate.  Press
the boot button  while holding down the  keys for the  file Dumper.Boot
(the OS and InstallSwat conspire to make this be "DU"  normally).  This
writes the  existing memory onto  Swatee with the  exception of  page 0
which is  lost (Dumper lands  in page  0 when you  boot it).   Also the
display word (420b) is cleared.  Finally, Swat is invoked.



9. Error Message Printing


Swat  contains  some  facilities to  aid  in  printing  error messages.
Because the Swat  resident is almost always  present when a  program is
running, an error message can be printed by simulating a  Swat "break,"
and letting the Swat program decipher the error specification and print
a reasonable message.

If Swat is invoked by the 77403b trap instruction, the contents  of AC0
are taken to be a  pointer to a BCPL string  for a file name; AC1  is a
pointer  to  table [  errCode%ClearBit;  p1; p2;  p3;  p4....  ], where
errCode  (0  le  errCode le  32000.)  is  an error  code,  the  p's are
"parameters," and  ClearBit is  either 100000b  (clear the  Swat screen
before printing the message) or 0 (do not clear).

The intended use is with a BCPL procedure like:
        let BravoError(code, p1, p2, nil, nil, nil) be
           [
           code = code%UserClearScreenBit
           (table [ 77403B; 1401B ])("bravo.errors", lv code)
           // do a "finish" here if fatal error
           ]

The error messages file is a sequence of error messages, searched  in a
dumb fashion.  An error message is:

a. An unsigned decimal error number (digits only)
b. Followed optionally by:
        C       Always clear the screen before printing the message
        M       (see below)
        L       Log the error via the Ethernet.
c. Followed by a <space>.
d. Followed by text for the message, including carriage returns, etc.
   If you wish to refer to a parameter, give:


SWAT                        April 10, 1982                           10




        $
        followed by a digit to specify the parameter number (1-9)
        followed optionally by "!<offset>" which treats parameter as a
                number, adds offset to it, and sets parameter to the
                contents of the resulting address (i.e. a vector ref).
        followed by a character to say how to print the parameter:
                O = octal
                D = decimal
                S = string (parameter is pointer to BCPL string)
        (example: $1D will print parameter 1 in decimal)
   The quote character is <escape>.
e. Followed by $$.


After  the message  is typed,  if M  was specified,  the  message "Type
<control>K to kill, or <control>P to proceed." is typed out.



10. Parity Error Information


When the Alto detects a parity error, Swat is usually invoked  to print
a message about  the details of the  error.  It then attempts  to "log"
the error with an  Ethernet server responsible for  keeping maintenance
information.  If the  server is not operating,  or if your Alto  is not
connected to an Ethernet with  such a server, simply strike  the <Swat>
key, and the familiar "#" will appear.

In many  cases, you  will want  to continue  execution of  your program
after a parity error is detected.  Simply type <control>P to Swat.



11. Installation


Get  the file  InstallSwat.Run.   Then invoke  it to  create  Swat (the
debugger),  Swatee (the  swap file  for the  user's memory  image), and
Dumper.Boot (the desperation debugger invoker).  InstallSwat.Run may be
deleted after it has been run once.  Use the Exec's BootKeys command to
discover the keys to depress for Dumper.Boot; normally they are "DU".

InstallSwat.run is the Swat program.   When invoked it, it hooks  up to
the current operating system,  initializes itself, and then  OutLds all
of core including  the OS (suitably  Junted and slightly  patched) onto
the file Swat.

There are two global switches, /D and /X.  /D installs Swat  in "debug"
mode.  In  this mode Swat  goes into TeleSwat  looking at bank  0 (i.e.
Swat  itself)  when  anything  untoward  happens,  such  as  finishing,
trapping, calling Swat, calling SysErr, or getting a parity  error.  If
debug  mode  is  not  set,   Swat  will  try  to  recover   from  these
catastrophies  rather  than  go into  TeleSwat.   When  in  debug mode,
hitting the <Swat>  key does not force  control back to the  top level,
and <left-shift><control><Swat> forces Swat into TeleSwat.

/X installs Swat in "extended memory" mode, for debugging IFS and other
systems  built on  the IFS  base.  In  this mode,  Swat is  prepared to


SWAT                        April 10, 1982                           11




follow  address pointers  which  lead to  inter-bank  jump instructions
(code statics and stack return addresses).



12. Caveats


1.  Swat has about  1k of resident code  in high memory.  This  code is
not changed when new subsystems come in.  Therefore re-boot if it seems
to  be in  a bad  state.  Swat  can get  itself into  a bad  state too.
SYSINing (↑Q) Swatee is a very effective general purgative;  ignore the
warning message - its doing exactly  what you want it to.  If  all else
fails, make sure you  have a clean copy  of the OS, and  then reinstall
Swat by running InstallSwat.run.

2.  Instructions 77400B - 77777B are used by Swat.  The actions of some
of these (e.g. 77401B) are  published; you get what you deserve  if you
use the unpublished ones.  Location 567B (in the trap vector) is used.

3.  Interrupt channel 8 (00400B)  is used by the resident  for keyboard
interrupts  (getting  to  swat  via  a  <control><left-shift><swat> key
combination).

4.  A program fetching data from a broken location will get 774xxB.

5.   While most  interrupt routines  are reasonably  polite  and always
resume the interrupted code where it left off, the politeness of Swat's
keyboard  interrupt is  entirely  in the  hands  of the  person  at the
controls.  If he re-starts by saying ↑P, all goes well; but he  may say
↑G or ↑C.  Therefore

     a) You should disable the keyboard interrupt by anding 77377B into
         453B  during  critical   sections  of  code  (once   they  are
         debugged).

     b) Expect occasional anomalies after ↑C or ↑G is used.

6.  The mappings between  symbols and addresses are naive  about BCPL's
block structure.

     a)  If  a symbol  is  defined twice  or  more you  get  the lowest
         address.

     b) An address is mapped into a procedure name plus  a displacement
         for  symbolic  type out  (e.g.  for ↑T).   If  procedure  A is
         defined  inside procedure  B, most  of B's  addresses  will be
         typed as if they were A's.

7. If a disk error prevents swapping, the offending disk  control block
and label are displayed in the "boot-lights" manner.

8.  Locations 700b  through 707b  are used  to save  the  machine state
before each swap.

9.  If  a file  created  on a  different  disk is  resumed  by booting,
invoking Swat may  not work because Swat  and Swatee may not  reside at
the same disk addresses  on the different disks.  This  difficulty does
not occur if the  Exec's RESUME command is  used, since it will  fix up
the addresses before resuming it.