Wack - The Extensible Amiga Local and Remote Debugger (c) Copyright 1992-1993 Commodore-Amiga, Inc. All rights reserved. This software is provided as-is and is subject to change; no warranties are made. All use is at your own risk. No liability or responsibility is assumed. Table of Contents ----------------- 1. Introduction 2. Glossary 3. Starting Wack 4. Basic Wack Commands 5. Wack Command Documentation 5a. Miscellaneous Commands 5b. Memory Commands 5c. Exec and DOS Commands 5d. Intuition Commands 5e. Graphics and Layers Commands 6. ARexx Commands 7. External Wack Commands 8. Remote Debugging Via Envoy 9. Remote Debugging Via SAD 10. Description of Files 1. Introduction ------------ Wack is a local and remote debugger for the Amiga. Originally used internally at Commodore by the software engineering department, it has grown to be potentially useful to other developers as well. Wack can be used to analyze the same machine it is run on, or it can be connected remotely via an Envoy networking link to another Amiga running a small Wack-server program, or via a serial cable to another Amiga which uses SAD. SAD is a V39 and higher ROM feature which provides a low-level protocol for debuggers to connect serially to an Amiga. When SAD is running, it takes over the target machine. There are a number of ways to launch SAD mode, including a small program to trigger it from either of the mouse ports. Wack allows the operator to read and write the memory of the target system, as well as disassemble code, and analyze a great many system structures. Through its ARexx macro language and the ability to add additional functions written in any programming language, you can extend Wack to display, analyze, and control features private to projects you may be developing. 2. Glossary -------- Here are simple explanations for a few terms which should help understanding the rest of this documentation. HOST The host is the computer on which the Wack command window is running. In the simplest case, Wack can be used to explore the same system on which the command window is running, but Wack can also connect to a second Amiga, allowing remote debugging. TARGET The target is the computer being analyzed or explored by Wack. In the simplest case, the target is the same machine as the host. However, Wack supports remote debugging, in which the host talks to a target machine in one of two ways (Envoy or SAD). ENVOY Envoy is Commodore's Amiga peer-to-peer networking system. Wack supports remote debugging over Envoy, which is to say if you have two machines connected by an Envoy network, you may run the Wack command window on one machine (the host) in order to examine the behavior of another machine (the target). When Wack is connected to a target machine via Envoy, the target machine continues to run normally. SAD SAD is a low-level serial debugging link built into the ROM of every Amiga running V39 or higher (Amiga OS Release 3 or higher). Wack knows how to use the SAD protocols in order to talk to a target machine connected via a serial cable. In order for Wack to communicate via the SAD mechanism, the target machine must be "frozen". There are a number of ways to freeze the target to allow debugging, and Wack has a command to allow the target machine to resume normal operation when debugging is done. FRAME A frame is a small amount of memory on the target computer. By default, a frame is sixteen bytes long, but this can be changed. Wack dumps or disassembles memory one frame at a time. A few other functions may operate on frame-sized units. CURRENT ADDRESS Wack allows you to navigate and browse the memory of the target system. It does this by maintaining a "current address", which is the last address you looked at or went to. Many commands take an optional address parameter. If you leave out that parameter, the current address is used, otherwise the address you specify will be used by that command. ENFORCER Enforcer is a Commodore utility which uses the MMU (memory management unit) available on most 68020 and higher systems. Enforcer traps and reports on accesses to memory regions that programs are not normally supposed to touch. Naturally, when browsing through memory there is a risk that one might stumble on such a memory region, thus causing "enforcer hits" (reports of access violations). Wack normally prevents access to those areas of memory it knows should not be touched, thereby preventing Enforcer hits due to casual or careless navigating. (Wack does have an option to remove this feature, permitting access to any memory, but re-introducing the risk of causing an enforcer hit). SEGTRACKER SegTracker is a Commodore utility which tracks where every program on a computer ended up getting loaded. Wack can use SegTracker running on the target system in order to correlate symbols from an executable containing debugging information available on the host to the actual addresses at which that program was loaded on the target. 3. Starting Wack ------------- The command syntax for starting Wack is: Wack TARGET,PUBSCREEN/K,FROM/K TARGET specifies the target machine to debug. If this argument is omitted, then Wack will debug the machine is it run on. To debug a machine running the WackServer Envoy server program, specify that machine's network name as the TARGET parameter. To connect via serial link to a machine via the SAD link, specify the serial port unit number to use. PUBSCREEN is the name of the public screen on which you wish the Wack window to open. If omitted, Wack will open on the default public screen (normally the Workbench). FROM specifies the startup file that Wack should execute. When Wack starts, it normally reads and executes rexx:startup.wack, which can contain ARexx commands to configure Wack to your liking. Normally, Wack's menu structure and any command bindings to ARexx scripts or to external Wack modules are made in the startup file. You can use the FROM keyword to specify an alternate startup file, or you may specify "FROM nil:" to specify that no startup file should be read. 4. Basic Wack Commands ------------------- Here is a brief introduction to the commands you may wish to play with when first using Wack. * help Type help to display a list of topics for which help is available. You can then type "help memory", for example, to see help on the commands you can use to view and manipulate memory on the target system. * quit Type quit to exit from Wack, closing the Wack window and cleaning up everything. * (go to address) Type the hex address you wish to see, to go to that address and show a frame of memory (which is normally 16 bytes) at that address. * (show next frame) The "show next frame" command will display the next frame of memory. Type <.> (period,return) to show the next frame. * (show previous frame) The "show next frame" command will display the previous frame of memory. Type <,> (comma,return) to show the previous frame. * (disassemble frame) This command disassembles the next frame of memory, showing 680x0 code. Type <;> (semicolon,return) to disassemble a frame's worth of memory. * (show tasks) To get an idea of the structure scanning abilities of Wack, type "tasks" to see a list of all the tasks on the target system. 5. Wack Command Documentation -------------------------- This section explains each Wack command. Wack is in general not case sensitive, though some of the arguments that represent items on the target Amiga's system lists may be searched for in a case-sensitive manner. Words shown in all capitals are keywords and must be typed exactly as shown. Round brackets "()" enclose optional parameters or keywords. Vertical bars separate exclusive keywords. If an optional address argument shown as "(address)" is omitted, the current address is used. 5a. Miscellaneous Commands ---------------------- HELP ( MISC | CONFIG | MEMORY | EXEC | INTUITION | GRAPHICS ) Provide help on Wack commands. Help is available on six different categories of command. "HELP" alone or with an unknown argument provides general help information, including a list of the help categories. ? ( MISC | CONFIG | MEMORY | EXEC | INTUITION | GRAPHICS ) The question mark symbol is a synonym for "HELP". QUIT The "QUIT" command exits the Wack session. ABOUT The "ABOUT" command shows version and author information for Wack. CLS The "CLS" command clears the Wack window. PROTECT ( ON | OFF ) Normally, Wack prevents you from reading or writing to areas of memory that are considered invalid. This helps ensure system stability and removes the risk of Wack or its remote server causing an Enforcer hit if Enforcer is running on the target system. If you wish to be able to access these areas of memory, you can use "PROTECT OFF" to turn off this protection. "PROTECT ON" restores protection against accessing invalid addresses. "PROTECT" alone shows the current state of this feature. You should not be running Enforcer on the target system if you wish to use the "PROTECT OFF" feature. CAPTURE ( filename ) ( OFF ) ( APPEND ) The "CAPTURE" command allows you to capture all Wack output to a file. This is convenient for keeping a record of your debugging session, or for subsequent review or searching. Type "CAPTURE filename" to begin capturing to the specified file. "CAPTURE filename APPEND" will begin capturing, but will append to the specified file's existing contents instead of replacing it. "CAPTURE OFF" will end capturing to that file. CONTEXT When connected to the target Amiga via SAD, the "CONTEXT" command will display the execution context of the target machine. This information includes the way in which SAD was triggered (a call to Debug(), a crash, or an NMI), and a dump of the data, address, and control registers of the CPU. The context command first sends a delete keystroke (ASCII 127) to the connected machine. This can be used to force a machine which is in the process of crashing (flashing power LED) to drop into SAD and establish a link with Wack. See the section on connecting via SAD for more details. When running locally or connected via Envoy, this command does not work. The "CONTEXT" command sets the spare address pointer to point to the remote system's program counter. GO When connected to the target Amiga via SAD, the "GO" command instructs the target machine to resume execution. This command is useful since when the target is operating under SAD, normal operation is halted. When running locally or connected via Envoy, this command does not work. CALL ( address ) This causes wack (or the remote SAD or Envoy server) to call a function at the specified address, or the current address if none is specified. No parameters are set up. A0/A1/D0/A1 are scratch. Any return value from the function is ignored. This function should be used very carefully, as it can easily crash the machine being debugged. SYSTEM command The "SYSTEM" command instructs Wack to execute the specified command as an Amiga shell command. For example "SYSTEM dir" would display the current directory in the Wack window. RX script The "RX" command instructs Wack to execute the specified script as an ARexx script. For example "RX foo.rexx" would run the foo.rexx script. Normal ARexx searching rules apply, and the default extension for Wack ARexx scripts is ".wack". RXS commands The "RXS" command instructs Wack to execute the specified arguments as ARexx commands. For example "RXS print 17*5" would display "85" in the Wack window. CONFIGURATION COMMANDS PROMPT string The "PROMPT" command allows you to configure the Wack command prompt. The string is taken literally, with the following substitutions: *N or \N: newline *T or \T: tab *C or \C: current address (in hex) The default prompt is "\n=> ". SETDUMP ( WORD | LONGWORD ) ( WIDE | NARROW ) ( ASCII | NOASCII ) The "SETDUMP" command allows to configure the way in which memory dumps are read and displayed, to best suit your needs and the window widths. The "WORD" and "LONGWORD" options control whether memory is to be read by word or by long word. The default setting is to read by long word. Certain hardware areas must be read in appropriate-sized units. Note that if your frame size is an odd number of words, the last two bytes will be read as a word, not a long word. Thus, if you set the frame size to 2 by using the ":2" command, all the reads will be by word. The "NARROW" option inserts a space after every eight hex digits, while the "WIDE" option inserts a space after every four hex digits. The "ASCII" and "NOASCII" options control whether the ASCII version of the memory is displayed beside the hexadecimal output. "SETDUMP" alone shows the current state. Note that "SETDUMP WIDE ASCII" produces output which is more than 80 columns wide. BINDCONSTANT label ( address ) The "BINDCONSTANT" command is used to create a new Wack command which evaluates to the specified (or current) address. For example, if you type "BINDCONSTANT ROMstart F80000", you would create a symbol called "ROMstart", whose value was F80000". Typing a symbol (in this case, typing "ROMstart") would set the current address to the value of the symbol. Also, the "WHERE" and "WHEREIS" commands take advantage of defined symbols to tell you where you are with respect to the nearest defined symbol. You may wish to use this command in your startup.wack file to set up commands for frequently-needed constants. SET label ( address ) The "SET" command is a convenient synonym for the "BINDCONSTANT" command. BINDALIAS newcommand oldcommand The "BINDALIAS" command allows you to create synonyms for existing Wack commands. For example, if you use the "EXECBASE" command frequently to show the contents of the ExecBase structure, you could type "BINDALIAS EB EXECBASE" to create a new command, "EB", which performs the same function as "EXECBASE". You may wish to use this command in your startup.wack file to set up aliases for frequently-used commands. BINDSYSTEM command shellprogram ( arguments ) The "BINDSYSTEM" command allows you to define a new Wack command which executes a shell program with the specified arguments. For example, if you type "BINDSYSTEM freemem avail total", then typing "freemem" would display the total amount of memory on the host system (the output of the shell command "avail total"). You may wish to use this command in your startup.wack file to set up convenient names for frequently-used shell commands. BINDRX command rexxscript ( arguments ) The "BINDRX" command allows you to define a new Wack command which executes an ARexx script with the specified arguments. For example, if you type "BINDRX lvo ShowLVO", then typing "lvo" would run the ShowLVO ARexx script. You may wish to use this command in your startup.wack file to tie ARexx extensions to Wack into Wack itself. BINDXWACK command shellprogram ( arguments ) The "BINDXWACK" command allows you to define a new Wack command which executes a specially-written shell program designed to be an external extension to Wack. That program will be invoked, passing an additional argument of "WACKPORT=Wack's ARexx port's name". The program can use the Wack ARexx port to issue commands to Wack, allowing you to extend Wack with C or any other language of your choice. See the section on External Wack Commands. Any "BINDXWACK" commands would typically be placed in your startup.wack file, so Wack always comes up configured with your extensions. ADDMENU header Along with the "ADDITEM" and "ADDSUBITEM" commands, the "ADDMENU" command allows you to customize the menus of the Wack window. The "ADDMENU" command creates a menu panel whose title is as specified. For example, "ADDMENU Intuition" would create a menu header whose title was "Intuition". ADDITEM header item command ( key ) The ADDITEM command creates a menu item for the menu strip of Wack's window. If a menu panel with the specified header is found, the item will be added to that panel, otherwise a new panel will be created first. The specified item name will be used in the menu. The command you supply is the command which will be executed when that menu item is chosen. The optional key argument allows you to specify a menu command-key for this item. For example, ADDITEM Intuition "Show IntuitionBase" ibase I would create a menu item entitled "Show IntuitionBase" in the Intuition menu. This item would issue the Wack "ibase" command, and would have a keyboard equivalent of right-Amiga-I. ADDSUBITEM header item subitem command ( key ) The "ADDSUBITEM" command is similar to the "ADDITEM" command, but is used to create a menu subitem of the specified menu item in the specified menu panel. 5b. Memory Commands --------------- Typing when at the Wack prompt displays the current memory frame. address Typing a hexadecimal address at the Wack prompt sets Wack's current address to that address, and shows a frame of memory there. For example, typing "F80000" would show the first frame of the system ROM. . The period key allows you to advance to the next frame of memory, and show that frame. For example, assuming the default frame size of 16 bytes, and assuming the current address is F80000, typing "." would show the frame of memory starting at address F80010. You can type multiple periods to show multiple frames. For instance, typing "..." would show the next three frames of memory. , The comma key allows you to back up to the previous frame of memory, and show that frame. For example, assuming the default frame size of 16 bytes, and assuming the current address is F90000, typing "." would show the frame of memory starting at address F8FFF0. You can type multiple commas to show multiple frames. For instance, typing ",,," would show the three previous frames of memory, in reverse order. > The greater-than key allows you to advance to the next word of memory and show a frame of memory starting there. For example, assuming the current address is F80000, typing ">" would show the frame of memory starting at address F80002. You can type multiple greater-thans to skip multiple frames. For instance, if the current address is F80000, typing ">>>" would show the frame of memory beginning at F80006. Note that unlike the period key, typing multiple greater-thans will not show the intermediate frames, only the result. < The less-than key allows you to back up to the previous word of memory and show a frame of memory starting there. For example, assuming the current address is F90000, typing "<" would show the frame of memory starting at address F8FFFE. You can type multiple less-thans to skip multiple frames. For instance, if the current address is F90000, typing "<<<" would show the frame of memory beginning at F8FFFA. Note that unlike the comma key, typing multiple less-thans will not show the intermediate frames, only the result. ; The semicolon key allows you to disassemble a frame of memory at the current address. Typing multiple semicolons will disassemble that many frames of memory. +offset The plus key is used to increase the current address by a specified offset. For example, typing "+100" will advance the current address by 100 hex bytes, and display a frame of memory starting there. -offset The plus key is used to decrease the current address by a specified offset. For example, typing "-100" will back up the current address by 100 hex bytes, and display a frame of memory starting there. =value The equals key is used to set the byte, word, or long word at the current address to the specified hexadecimal value. The size of the write is determined by the number of hexadecimal digits you supply. Here are some examples: "=FF" sets the current byte to hexadecimal FF. "=00FF" sets the current word to hexadecimal FF. "=000000FF" sets the current long word to hexadecimal FF. :framesize The colon key is used to set the frame size. Normally, the frame size is 10 hex bytes. Typing ":40" would set the frame size to 40 hex bytes, which would take four lines per frame to display. A frame size of zero (":0") means that no frame is displayed when at a particular address. This is useful when writing to areas of the system that cannot be safely read from, such as custom chip write-registers. [ The open square-bracket key is the indirection function. This instructs Wack to set the current address to the long word stored at the current address. This is very useful in list or structure traversal. Multiple open square-brackets can be typed to perform multiple consecutive indirections. Wack keeps a large stack of the indirections performed, so they can be undone with the close square-bracket (undo-indirection) feature. The open square-bracket key is special in that it may be followed by an additional command on the same line. For instance, typing "[task" would perform an indirection and then show the task at the resulting address. ] The close square-bracket key is the undo-indirection (exdirection) function. This instructs Wack to set the current address to the address before the most recent indirection operation. This is very useful in list or structure traversal. Multiple close square-brackets can be typed to perform multiple consecutive exdirections. The close square-bracket key is special in that it may be followed by an additional command on the same line. For instance, typing "]task" would undo the last indirection and then show the task at the resulting address. { The open brace-bracket key is the BCPL-indirection function. It evaluates the value stored at the current address as a BCPL pointer (BPTR) and sets the current address to that value. Multiple open brace-brackets can by typed to perform multiple consecutive BCPL-indirections. BCPL-indirections share the same stack as regular indirections, and can be undone with the close square-bracket key. The open brace-bracket key is special in that it may be followed by an additional command on the same line. For instance, typing "{process" would perform a BCPL-indirection and then show the process at the resulting address. DEC hexvalue The "DEC" command is used to convert the specified hexadecimal value to decimal. For example, "DEC 4A" produces an answer of 74. HEX decvalue The "HEX" command is used to convert the specified decimal value to hexadecimal. For example, "HEX 74" produces an answer of 4A. BPTR bcplpointer The "BPTR" command is used to evaluate a BCPL pointer, which basically consists of multiplying by four. FIND ( hexvalue ) The "FIND" command is used to locate the specified hexadecimal word or long word between the current address and the find-limit (see the "LIMIT" command). If the limit is zero (the default), a range of 1K is searched. If the limit address is less than the current address, the search proceeds backwards. If a hexadecimal value is specified, the search begins at the current address. If the hex value is omitted, the last value used will be reused, and the search will commence just past the current address, which means that consecutive "FIND" commands will find successive occurrences of the target pattern. The "FIND" command determines whether to search by word or by long word based on the number of hexadecimal digits supplied. / ( hexvalue ) The slash key is a synonym for the "FIND" command. LIMIT ( address ) Sets the limit for the "FIND" operation to the specified address (or the current address, if none is specified). If the limit is set to zero, then the search limit will be set to 1K after the start address of any search. STACKLIMIT ( address ) The "STACKLIMIT" command sets up search boundaries based on the stack of the task at the specified address (or the current address, if no address is given). The current address will be set to the task's SPReg value, and the limit will be set to the task's SPUpper value. WHERE ( address ) The "WHERE" command can be used to identify the nearest symbol less than or equal to the current or the specified address. This is useful in determining where in the target system's memory you are. Symbol definitions come from several places. The "BINDCONSTANT" and "SET" commands can be used to define symbols, and the "BINDHUNKS" and "BINDSYMBOLS" commands may also be used to define symbols. WHEREIS ( address ) The "WHEREIS" command is similar to the WHERE command, except that it performs an indirection on the current or specified address. That is, it looks up the address stored at the current or specified address in the symbol table. ! Wack maintains a "spare address" pointer, which is set by certain functions which locate system structures. Typing "!" swaps the current address with the spare address. For example, typing "AWINDOW" displays the address of the active window and sets the spare address pointer to point at that window. Subsequently typing "!" sets the current address to point to the active window. The exclamation point is special in that it may be followed by an additional command on the same line. For instance, typing "!window" after "awindow" in the above example would go to and show the active window. SHOWHUNKS ( module ) If SegTracker is running on the target machine, then the "SHOWHUNKS" command may be used to show the base addresses of all the hunks of the specified module, or of all modules if no specific module is supplied. Module names are compared using a tail-anchored case-insensitive comparison against the module names known to SegTracker (which are generally the CLI command names). That is, "SHOWHUNKS myprog" would match "Work:Tools/MyProg" but not "Work:Tools/MyProg.command". BINDHUNKS ( module ) This command is similar to "SHOWHUNKS", except that instead of displaying the base addresses of the hunks, "BINDHUNKS" creates Wack symbols for the base addresses of all the hunks of the specified module, or of all modules if no specific module is supplied. Following this, the "WHERE" and "WHEREIS" commands may be used to obtain hunk and offset information for any interesting address. This command requires that SegTracker be running on the target machine. As an example, "BINDHUNKS myprog" would create symbols for the hunk-offsets of "myprog". BINDSYMBOLS symbolfile ( module ) This command uses SegTracker on the target machine to locate the base addresses of the hunks of the specified module, then reads the specified symbol file (normally, a matching version of the executable having symbols compiled into it), and creates a Wack symbol equal to the resolved value of each symbol found in the symbolfile. The result is that Wack can learn the full symbols of a module already running on the target machine. This can be very useful for figuring out where one is with the "WHERE" and "WHEREIS" commands. If the module name is omitted, the file-name part (up to the first period) of the symbolfile name is used to find the module on SegTracker's list. The module parameter can be used to give a precise name when the symbolfile name is significantly different to use. As an example, typing the command "BINDSYMBOLS Work:Sources/MyProg.debug myprog" would create Wack symbols for all symbols defined in Work:Sources/MyProg.debug based on the actual location of the "myprog" program on the target machine. 5c. Exec and DOS Commands --------------------- EXECBASE This command shows selected fields from ExecBase. This command sets the spare address pointer to ExecBase. NODES ( address ) This command shows the address, node type, priority, and name of every Exec Node on the same list as the specified (or current) address. An asterisk denotes the current node. The name pointer is validated before printing, so the command is somewhat usable on MinNodes as well. SEM ( address ) This command shows the Exec SignalSemaphore at the specified (or current) address. SEMS ( address ) This command shows all the Exec SignalSemaphores on the List at the specified (or current) address. TASKS This command shows a one-line summary for every task in the system, including the task's address, priority, status, signals being waited on, and the task name and process CLI command name, if any. TASK ( address | name ) The "TASK" command displays a detailed dump of an Exec task. If no argument is given, the task at the current address is displayed. Alternately, you may specify the address of the task you wish to display. The final option is to specify part or all of the task's name. The first task whose task name or process CLI command name partially matches the specified name will be shown. SP INTERRUPTS The "INTERRUPTS" command shows the Exec interrupt vectors. INTS The "INTS" command is a synonym for the "INTERRUPTS" command. PORTS The "PORTS" command shows information on all Exec MsgPorts on the Exec port list, including address, name, SigTask, and signal bit. DEVICES The "DEVICES" command shows a summary of every Exec device, including its address, priority, version/revision, and name. DEVS The "DEVS" command is a synonym for the "DEVICES" command. LIBRARIES The "LIBRARIES" command shows a summary of every Exec library, including its address, priority, version/revision, and name. LIBS The "LIBS" command is a synonym for the "LIBRARIES" command. RESOURCES The "RESOURCES" command shows a summary of every Exec resource. RES The "RES" command is a synonym for the "RESOURCES" command. REGIONS The "REGIONS" command shows information on each memory region known to Exec. MEMORY The "MEMORY" command shows all memory headers in the system. Note that this command can potentially produce a very large amount of output. MEM The "MEM" command is a synonym for the "MEMORY" command. MODULES The "MODULES" command shows a summary of every Exec resident module, including its address, priority, version, and name. MODS The "MODS" command is a synonym for the "MODULES" command. DOSBASE The "DOSBASE" command displays selected fields of the dos.library DOSBase structure. This command sets the spare address pointer to DOSBase. DOSLIST The "DOSLIST" command shows the dos.library device/volume/assign list. PROCESS ( address | name ) The "PROCESS" command displays a detailed dump of a DOS process. If no argument is given, the process at the current address is displayed. Alternately, you may specify the address of the process you wish to display. The final option is to specify part or all of the process's name. The first process whose task name or process CLI command name partially matches the specified name will be shown. If the specified process turns out to be only a task, then only the task-related fields will be displayed. PROC The "PROC" command is a synonym for the "PROCESS" command. 5d. Intuition Commands ------------------ IBASE The "IBASE" command shows selected fields from the public part of the IntuitionBase structure. This command sets the spare address pointer to IntuitionBase. ASCREEN The "ASCREEN" command shows the address of Intuition's active screen. This command sets the spare address pointer to the active screen. AWINDOW The "AWINDOW" command shows the address of Intuition's active window. This command sets the spare address pointer to the active window. SCREEN ( address ) The "SCREEN" command displays the most important fields of the screen at the current or specified address. WINDOW ( address ) The "WINDOW" command displays the most important fields of the window at the current or specified address. WFLAGS ( address ) The "WFLAGS" command displays the Window Flags, MoreFlags, and IDCMPFlags fields using descriptive labels for each bit set. The window at the current or specified address is used. FIRSTGAD The "FIRSTGAD" command displays the address of the first gadget of the window at the specified or current address. This command sets the spare address pointer to the first gadget of the window. GADGET ( address ) The "GADGET" command displays the gadget at the current or specified address. GADGETS ( address ) The "GADGETS" command displays the list of gadgets beginning with the gadget at the current or specified address. MENU ( address ) The "MENU" command displays the Menu header at the current or specified address. MENUS ( address ) The "MENUS" command displays the list of Menu headers beginning with the Menu header at the current or specified address. ITEM ( address ) The "ITEM" command displays the MenuItem or SubItem at the current or specified address. ITEMS ( address ) The "ITEMS" command displays the list of MenuItems or SubItems beginning with the one at the current or specified address. REQUESTER ( address ) The "REQUESTER" command displays the Intuition Requester at the current or specified address. REQ ( address ) The "REQ" command is a synonym for the "REQUESTER" command. PROPINFO ( address ) The "PROPINFO" command shows the PropInfo structure at the current or specified address. IMAGE ( address ) The "IMAGE" command shows the Image structure at the current or specified address. ITEXT ( address ) The "ITEXT" command shows the IntuiText structure at the current or specified address. CLASS ( address ) The "CLASS" command shows the Boopsi Class structure at the current or specified address. OBJECT ( address ) The "OBJECT" command shows the Boopsi object structure at the current or specified address. LISEMS The "LISEMS" command shows the LayerInfo and Layer semaphores for all screens and windows in the system. 5e. Graphics and Layers Commands ---------------------------- GFXBASE The "GFXBASE" command shows many of the interesting fields of the GfxBase structure. This command sets the spare address pointer to GfxBase. VIEW ( address ) The "VIEW" command shows the View structure at the current or specified address. VEXTRA ( address ) The "VEXTRA" command shows the ViewExtra structure at the current or specified address. VIEWPORT ( address ) The "VIEWPORT" command shows the ViewPort structure at the current or specified address. VP ( address ) The "VP" command is a synonym for the "VIEWPORT" command. VIEWPORTS ( address ) The "VIEWPORTS" command shows a list of ViewPort structures beginning with the one at the current or specified address. COP The "COP" command shows the current copper list, excluding the color table. COPPER The "COPPER" command shows the current copper list, including the color table. COPINIT The "COPINIT" command shows the graphics copinit copper list. LINFO ( address ) The "LINFO" command shows the LayerInfo structure at the current or specified address. LAYER ( address ) The "LAYER" command shows the Layer structure at the current or specified address. 6. ARexx Commands -------------- You can invoke ARexx scripts directly from within Wack (see the "RX" and "RXS" commands). As well, you can create new Wack command names whose function is to invoke ARexx scripts (see the "BINDRX" command). The "BINDRX" commands are typically placed in your startup.wack file so that Wack always opens configured to your liking. Wack is an ARexx command host which allows an ARexx program to issue any valid Wack command, and also gives access to a family of Wack primitives that can be used to browse the target system. The ARexx port name is of the form "wack.n", where "n" is the invocation number. Summary of ARexx commands supported by Wack: CURRENTADDR - Return and optionally set current address SPAREADDR - Return and optionally set spare address VERSION - Return Wack version PRINT - Print string to Wack window READBYTE - Read byte at current or specified address. Result is in hex unless "decimal" is specified. READWORD - Read word at current or specified address. Result is in hex unless "decimal" is specified. READLONG - Read long at current or specified address. Result is in hex unless "decimal" is specified. READBLOCK - Read block of memory into supplied buffer READSTRING - Read string at current or specified address. READBSTR - Read BSTR at current or specified address. WRITEBYTE - Write a byte to current or specified address. Byte is taken to be hex unless "decimal" is specified. WRITEWORD - Write a word to current or specified address. Word is taken to be hex unless "decimal" is specified. WRITELONG - Write a long to current or specified address. Long is taken to be hex unless "decimal" is specified. WRITEBLOCK - Write buffer into memory FINDLIBRARY - Return address of specified library CONNECTION - Return type of connection to target CONTEXTADDR - Return context address CALL - Call a function Error codes: An ARexx error of 10 generally signifies a bad argument to a command. An ARexx error of 5 generally signifies object not found, or similar. CURRENTADDR ( address ) The "CURRENTADDR" ARexx command is used to retrieve and optionally change the current address pointer, which is used by Wack for data displays and as the default address for most commands that accept an address. The result string is set to the value of the current address. If the optional address argument is provided, the current address is then set to this value. SPAREADDR ( address ) The "SPAREADDR" ARexx command is used to retrieve and optionally change the spare address pointer, which is set by certain Wack commands as a convenient bookmark. The result string is set to the value of the spare address. If the optional address argument is provided, the spare address is then set to this value. VERSION The "VERSION" ARexx command is used to retrieve the Wack version number string. The result string will be of the form "Wack 40.123". PRINT ( string ) The "PRINT" ARexx command is used to print a text-string into the Wack window. READBYTE ( address ) ( DECIMAL ) The "READBYTE" ARexx command is used to read a byte value on the target machine. The byte at the specified or current address will be read. Normally, the result string will be in hexadecimal, unless the "DECIMAL" keyword is supplied, in which case the result string will be the decimal value. READWORD ( address ) ( DECIMAL ) The "READWORD" ARexx command is used to read a word value on the target machine. The word at the specified or current address will be read. Normally, the result string will be in hexadecimal, unless the "DECIMAL" keyword is supplied, in which case the result string will be the decimal value. READLONG ( address ) ( DECIMAL ) The "READLONG" ARexx command is used to read a long word value on the target machine. The long word at the specified or current address will be read. Normally, the result string will be in hexadecimal, unless the "DECIMAL" keyword is supplied, in which case the result string will be the decimal value. READBLOCK ( address ) buffer size The "READBLOCK" ARexx command is used to read a block of memory from the target machine into a supplied buffer. The block will start at the specified or current address, and will be 'size' bytes long. 'address', 'buffer' and 'size' must be in hexadecimal. READSTRING ( address ) The "READSTRING" ARexx command is used to read a string on the target machine. The string beginning at the specified or current address will be returned as the result string. READBSTR ( address ) The "READBSTR" ARexx command is used to read a BSTR-style string on the target machine. The string beginning at the specified or current address will be returned as the result string. Note that the address to specify is an actual address, not a BPTR. WRITEBYTE ( address ) value ( DECIMAL ) The "WRITEBYTE" ARexx command is used to write a byte value into the target machine. The supplied value will be written to the specified or current address. The value you specify is assumed to be a hexadecimal value, unless the "DECIMAL" keyword is supplied, in which case the value you specify is assumed to be in decimal. WRITEWORD ( address ) value ( DECIMAL ) The "WRITEWORD" ARexx command is used to write a word value into the target machine. The supplied value will be written to the specified or current address. The value you specify is assumed to be a hexadecimal value, unless the "DECIMAL" keyword is supplied, in which case the value you specify is assumed to be in decimal. WRITELONG ( address ) value ( DECIMAL ) The "WRITELONG" ARexx command is used to write a long word value into the target machine. The supplied value will be written to the specified or current address. The value you specify is assumed to be a hexadecimal value, unless the "DECIMAL" keyword is supplied, in which case the value you specify is assumed to be in decimal. WRITEBLOCK ( address ) buffer size The "WRITEBLOCK" ARexx command is used to write a buffer into the memory of the target machine. The block will start at the specified or current address, and will be 'size' bytes long. 'address', 'buffer' and 'size' must be in hexadecimal. FINDLIBRARY ( libraryname ) The "FINDLIBRARY" ARexx command is used to find the address of the specified library on Exec's library list. The full name in correct case must be given, for example "FINDLIBRARY intuition.library". The result string will be the address of the library, if found. CONNECTION The "CONNECTION" ARexx command is used to retrieve type of connection established to the target machine. The result string will be of the form: - "Local" (when Wack is running directly on the target machine.) - "Envoy foo" (when Wack is connected via Envoy to a machine named foo.) - "SAD 3" (when Wack is connected via SAD over the host's serial.device unit 3.) CONTEXTADDR The "CONTEXTADDR" ARexx command returns the address of the SAD context structure. The result string is the address of the context structure, or zero if not found. If the target machine is connected other than through SAD, the result is zero as the context address is not supported in that case. CALL ( address ) The "CALL" ARexx command causes wack (or the remote SAD or Envoy server) to call a function at the specified address, or the current address if none is specified. No parameters are set up. A0/A1/D0/A1 are scratch. Any return value from the function is ignored. This function should be used very carefully, as it can easily crash the machine being debugged. 7. External Wack Commands ---------------------- In addition to extensions via ARexx, Wack provides a method whereby you can write additional Wack commands in languages such as C. One major advantage over ARexx is that you can easily write modules to dump structures private to your particular project. Handling structure offsets in ARexx is awkward at best. The basic principle is that you can create a shell program, and bind one or more Wack commands to it. When those Wack commands are issued, your shell program is invoked, passing any fixed arguments you established when the command was bound, any arguments that were typed alongside the command, and the name of Wack's command port. The address of that command port can be used like a library base, and Wack functions may be called LVO-style with the port as the base address. The "BINDXWACK" command allows you specify the new command name you would like to create, as well as a shell program to run, and any fixed arguments you wish to pass to it. For instance, the command "BINDXWACK showdata work:WackShow data" states you would like to create a Wack command "SHOWDATA" which invokes the shell program called "work:WackShow" passing the argument "data". If you invoke it by typing, "showdata f80000", the actual command line will be: work:WackShow WACKPORT=wack.1 data f80000 The fact that "BINDXWACK" supports a fixed argument to be passed allows you to combine the code to handle multiple commands into a single module, and use the fixed argument to tell which one was invoked. The actual instance argument can then be operated on. "BINDXWACK" commands are typically be placed in your startup.wack file, so Wack always comes up configured with your extensions. The program you supply to handle the command would typically use ReadArgs() to parse the arguments, and perform FindPort() on the Wack port, placing the result in a variable called WackBase. Prototypes and pragmas are supplied which allow the following Wack functions to be invoked: NAME Wack_VPrintf() - Printf-style command to print into Wack window. Wack_Printf() - Varargs stub for Wack_VPrintf(). SYNOPSIS void Wack_VPrintf( STRPTR fmt, ULONG *arglist ); void Wack_Printf( STRPTR fmt, ... ); FUNCTION These functions display text, printf-style, into the Wack window. NAME Wack_ReadCurrAddr() - Retrieve the Wack current address pointer. SYNOPSIS APTR Wack_ReadCurrAddr( void ); FUNCTION This function returns the value of the Wack current address pointer. NAME Wack_WriteCurrAddr() - Change the Wack current address pointer. SYNOPSIS APTR Wack_WriteCurrAddr( APTR newaddr ); FUNCTION This function changes the Wack current address pointer to the specified value. NAME Wack_ReadSpareAddr() - Retrieve the Wack spare address pointer. SYNOPSIS APTR Wack_ReadSpareAddr( void ); FUNCTION This function returns the value of the Wack spare address pointer. NAME Wack_WriteSpareAddr() - Change the Wack spare address pointer. SYNOPSIS APTR Wack_WriteSpareAddr( APTR newaddr ); FUNCTION This function changes the Wack spare address pointer to the specified value. NAME Wack_ReadByte() - Read a byte from the target machine's memory. SYNOPSIS UBYTE Wack_ReadByte( APTR address ); FUNCTION This function reads and returns one byte at the specified address of the target machine's memory. NAME Wack_ReadWord() - Read a word from the target machine's memory. SYNOPSIS UWORD Wack_ReadWord( APTR address ); FUNCTION This function reads and returns one word at the specified address of the target machine's memory. NAME Wack_ReadLong() - Read a long word from the target machine's memory. SYNOPSIS ULONG Wack_ReadLong( APTR address ); FUNCTION This function reads and returns one long word at the specified address of the target machine's memory. NAME Wack_ReadBlock() - Read a block from the target machine's memory. SYNOPSIS Wack_ReadBlock( APTR address, APTR buffer, ULONG size ); FUNCTION This function reads a block of memory at the specified address of the target machine's memory, 'size' bytes long into 'buffer'. NAME Wack_ReadPointer() - Read a pointer from the target machine's memory. SYNOPSIS APTR Wack_ReadPointer( APTR address ); FUNCTION This function reads and returns the pointer at the specified address of the target machine's memory. This function is actually the same function as Wack_ReadLong(), just prototyped suitably for pointer retrieval. NAME Wack_ReadBlock() - Read a block of the target machine's memory. SYNOPSIS void Wack_ReadBlock( APTR address, APTR buffer, unsigned long size ); FUNCTION This function reads a block of memory from the target machine's memory, at the specified address and of the supplied size. The result is placed into the buffer you supply. NAME Wack_WriteByte() - Write a byte to the target machine's memory. SYNOPSIS void Wack_WriteByte( APTR address, unsigned long data ); FUNCTION This function writes the specified byte value into the specified address of the target machine's memory. NAME Wack_WriteWord() - Write a word to the target machine's memory. SYNOPSIS void Wack_WriteWord( APTR address, unsigned long data ); FUNCTION This function writes the specified word value into the specified address of the target machine's memory. NAME Wack_WriteLong() - Write a long word to the target machine's memory. SYNOPSIS void Wack_WriteLong( APTR address, unsigned long data ); FUNCTION This function writes the specified long word value into the specified address of the target machine's memory. NAME Wack_WriteBlock() - Write a block into the target machine's memory. SYNOPSIS Wack_WriteBlock( APTR address, APTR buffer, ULONG size ); FUNCTION This function writes a block of memory at the specified address of the target machine's memory, 'size' bytes long from 'buffer'. NAME Wack_WritePointer() - Write a pointer to the target machine's memory. SYNOPSIS void Wack_WritePointer( APTR address, APTR data ); FUNCTION This function writes the specified pointer value into the specified address of the target machine's memory. This function is actually the same function as Wack_WriteLong(), just prototyped suitably for writing pointers. NAME Wack_FindLibrary() - Locate a library on the target machine. SYNOPSIS struct Library *Wack_FindLibrary( STRPTR library ); FUNCTION This function attempts to locate the named library on the target machine, returning its address if found, or zero if not found. NAME Wack_ReadString() - Read a string from the target machine's memory. SYNOPSIS ULONG Wack_ReadString( STRPTR address, APTR buffer, unsigned long maxlen ); FUNCTION This function reads a string from the target machine's memory, at the supplied address and whose length does not exceed the specified maximum. The result is placed into the buffer you supply. NAME Wack_ReadBSTR() - Read a BCPL string from the target machine's memory. SYNOPSIS ULONG Wack_ReadBSTR( STRPTR address, APTR buffer, unsigned long maxlen ); FUNCTION This function reads a BCPL-style string from the target machine's memory, at the supplied address and whose length does not exceed the specified maximum. The result is placed into the buffer you supply. Note that the supplied address is a regular pointer, not a BPTR. NAME Wack_ReadContextAddr() - Return the SAD context address. SYNOPSIS APTR Wack_ReadContextAddr( void ); FUNCTION This function returns the address of the SAD context, if the target machine is connected via SAD. If the target machine is connected in some other way, then this function will return zero. NAME Wack_Call() - Call a function on the target machine SYNOPSIS ULONG Wack_Call( APTR addr ); FUNCTION This function causes wack (or the remote SAD or Envoy server) to call a function at the specified address. No parameters are set up. A0/A1/D0/A1 are scratch. Any return value from the function is ignored. This function should be used very carefully, as it can easily crash the machine being debugged. When writing external Wack commands, great care must be taken because there are potentially two address spaces (that of the host and that of the target), and this can be confusing. The problem is made worse in that many bugs may not appear when Wack is run locally. Here are some examples to illustrate. struct Window *window; /* Assume window is the address of some window in the * target machine. We want to read the IDCMPFlags. * * WRONG WAY: * * idcmpflags = window->IDCMPFlags; /* WRONG */ * * This yields the contents of the long word in the * host whose address matches the address of the actual * IDCMPFlags field on the target. * * RIGHT WAY: */ idcmpflags = Wack_ReadLong( &window->IDCMPFlags ); /* This time we've been careful to actually read the * value from the target. Alternately, if you need * to peruse the window a lot, you could do: * * struct Window winbuffer; * * Wack_ReadBlock( window, &winbuffer, sizeof( struct Window ) ); * idcmpflags = winbuffer.IDCMPFlags; */ Here is a list walker that correctly reads nodes from the target machine. Assume that MyThing is a custom structure beginning with a Node. struct MyThing { struct Node mt_Node; /* other stuff here */ } struct List *list; /* points to list in target machine */ struct MyThing *curr; struct MyThing *succ; struct MyThing buffer; for ( curr = Wack_ReadPointer( &list->lh_Head ); succ = Wack_ReadPointer( &curr->mt_Node.ln_Succ ); curr = succ ) { Wack_ReadBlock( curr, &buffer, sizeof( struct MyThing ) ); /* Do what you need to buffer.mt_fields */ } The basic idea should be apparent from these examples. Unfortunately, it does clutter up the coding somewhat, but in time you get the hang of it. Again, if you accidentally read stuff from the host machine's memory, you may not notice if Wack is not running over a remote link. 8. Remote Debugging Via Envoy -------------------------- Envoy is Commodore's Amiga peer-to-peer networking solution. If two Amigas are connected via Envoy, then Wack can be used to remote debug from one machine to the other. First, on the target machine, the WackServer program should be run. This program sits in the background awaiting network transactions from the Wack debugger, and services those transactions on demand. Its role is primarily to perform low-level reads and writes into the target machine's memory and communicate the results back to the host. For example, say we wanted to debug a machine called "amy". On amy, you would first type: run WackServer Later, from another machine, you would type: Wack amy and Wack would be connected to amy via an Envoy link. In order to successfully debug a remote machine via Envoy, that machine needs to be substantially healthy. That is to say, certain kinds of crashes may preclude Envoy-based remote debugging if the WackServer program or the Envoy software is taken out of commission. Nevertheless, this form of remote link is very convenient and powerful. 9. Remote Debugging Via SAD ------------------------ SAD is a low-level serial link supported by Exec in the Amiga V39 and higher ROM, corresponding to Release 3 and higher of the Amiga OS. SAD completely takes over the target machine, and because of that and because it is low-level, SAD can be used to debug even a relatively scrambled Amiga. SAD can be invoked on the target machine in one of three ways: Calling Debug(): If a program on the target machine calls the exec.library Debug() function, then the target machine will attempt to establish a SAD link over the serial port. If after about ten or twenty seconds no SAD host responds, the call to Debug() will return. Guru-in-progress: At the beginning of a software failure on the target computer, the power LED blinks for about three seconds. If during that interval the target computer receives a "delete" keystroke (ASCII 127) via the serial port at 9600 baud, the target Amiga will drop into SAD mode. The Wack "CONTEXT" command sends this delete keystroke, and thus can be used to "catch" a crashing Amiga. If the target Amiga is not otherwise consuming serial input, the delete keystroke can be sent and is buffered on the target computer, which means that computer will be caught if ever it crashes. NMI: An Amiga can be configured so that a level-7 interrupt (NMI) triggers SAD. This would permit the addition of a hardware "SAD button" to drop the computer into SAD at the press of a button, permitting debug-on-demand. Normally, this feature is not enabled, and the NMI-interrupt-handler does nothing (i.e., performs an RTE instruction). To enable the NMI-SAD routine, look at the level-7 interrupt vector. If it points to an RTE instruction, increment it by two bytes. That is, the NMI-SAD handler immediately follows the do-nothing RTE instruction. Note that many Amigas (primarily A500 and A2000s) get spurious NMI interrupts, in which case the NMI technique may not work for you. The key issue then is since SAD takes over the target Amiga, how does one drop a running Amiga into SAD as needed. Six executables are provided, one for the left, middle, and right mouse buttons of mouse ports zero and one. Running the appropriate executable, then clicking that mouse button will trigger SAD, freezing the target machine. The Wack "GO" command can be used to resume normal execution on the target machine. Alternately, when debugging your own code, you can insert calls to exec.library/Debug() at appropriate points. Note that using Wack in SAD mode hogs the serial port, which you may also be using for debug-text output. If you trigger SAD, you have ten or twenty seconds to get Wack up and responding to it before the target machine will give up waiting and resume. 10. Description of Files -------------------- This is the directory structure of the Wack package: tools (dir) DoSAD.0L DoSAD.0M DoSAD.0R DoSAD.1L DoSAD.1M DoSAD.1R demos (dir) arexxdemo.wack ShowLVO.wack ShowMember.wack ShowStructure.wack StructureOffset.rexx xwackdemo xwackdemo.c startup.wack Wack Wack.doc WackServer wack_pragmas.h wack_protos.h Wack The Wack debugger itself. Wack.doc This file. startup.wack Example ARexx startup configuration file. Place in rexx:. WackServer Program to run on target machine for Envoy connection. wack_protos.h Prototypes for functions to be called by Wack extension programs. wack_pragmas.h Pragma definitions for functions to be called by Wack extension programs. DoSAD.#? Programs to trigger a call to Debug() and thus enter SAD mode in response to one mouse button or another. arexxdemo.wack Example Wack ARexx script which prints the name, version, and revision of a library at the current or specified address. StructureOffset.rexx Underlying script to parse the 3.1 Structure.offsets file to determine the offset of a given structure's member. Used by ShowMember.wack, Member.wack, and IsA.wack. ShowMember.wack This script considers the current or specified address to be a structure of the type you specify, and displays the specified member. Uses the supplied StructureOffset.rexx script and the structure offsets file. ShowStructure.wack This script shows all members of the specified structure type at the current or specified address. This script allows you to dump any public system structure, even if Wack does not actually know it. Uses the supplied StructureOffset.rexx script and the structure offsets file. ShowLVO.wack ARexx script to determine the actual address that a particular library LVO will jump to. Uses the include:pragmas/#?_pragmas.h. xwackdemo.c Source code to an example Wack extension program. xwackdemo Example Wack extension program to print the name, version, and revision of a library at the current or specified address. rwfile.c source code to an example Wack extension program. rwfile Example Wack extension program to read a block of memory into a file, or write a file into memory.