dlyons@Apple.COM (David A. Lyons) (07/25/90)
Apple IIgs Debugging Tips and Techniques
compiled by David A. Lyons, Apple II Developer Technical Support
July 18, 1990
(July 23: corrected "InstallNDA is new for 5.0" to "RemoveNDA is new
for 5.0, and be careful about removing DAs. Otherwise this document
is what I handed out as the A2-Central Developers Conference.)
General Techniques
In a Desktop-based program that normally displays the super-hires
graphics screen, write debugging messages to the text screen at
selected points in your program (using the Text Tools, for example).
Then in the event loop, test the mouse position (it appears in the
"where" field of the event record after a GetNextEvent or TaskMaster
call). If the mouse is in the upper left corner of the screen switch
to the text screen using the QuickDraw II call GrafOff. If the mouse
is anywhere else, switch back to the graphics display with GrafOn.
(Reported by Ron Lichty; technique by Allan Bell, Australia)
Check for errors on all toolbox calls that allocate memory. Have a
scheme for dealing with low-memory situations. See Apple IIgs
Technical Notes #51, 52, 56, and others, and read about the System
Software 5.0 Out Of Memory Queue handling introduced (Apple IIgs
Toolbox Reference Volume 3).
Make sure the Bank register is set right. If you're writing code
that all fits into a single 64K bank, you may want to always keep
your data inside your code segment and use PHK PLB. If your data
is in a separate segment, this is bad (you may not discover it right
away, because two segments can wind up in the same bank most of the
time, especially if they happen to be small).
Use safety checks possible in your development environment. For
example, if you use macros to allocate direct-page locations, use
assemble-time error messages to check the amount of direct-page space
you're using. If it exceeds 256 bytes, complain during assembly;
this will be a lot more fun than trying to figure out why your code
mysteriously crashes.
Watch out for uninitialized storage locations! Random values may
allow your code to work a lot of the time, so suspect this problem
especially if your code works right sometimes and fails other times.
(Developer Technical Support provides "Pointer Check" routines for
use with APW C. See Sample Code volume 2.)
Tips for using GSBug
(Thanks to Tim Swihart for some of these GSBug tips.)
Break into your application at a strategic toolbox call, such as
TaskMaster, by using the GSBug commands SetTBrk and TBrkIn. When
you hit r to resume your application, you will automatically drop
into GSBug when you hit the selected call. At that point you can
disassemble pieces of your code, start single-stepping it with s,
or whatever. You can usually even hit Apple-Ctrl-ESC to enter your
favorite CDA (see below).
Here's a way to trace your program's code for handling a particular
menu item. Set a tool break on TaskMaster. Resume your code and let
it break on the TaskMaster call. Type s to display the super-hires
screen, and click and hold the mouse button on the menu bar. Press
space to execute the TaskMaster call. Select a menu item and release
the mouse. At this point, you are still in GSBug, and TaskMaster has
just returned. Press T to display the text screen, and press space
to step through your code.
Debugging a Classic Desk Accessory is hard, because the stack is
normally in $00/01xx when a CDA executes. GSBug is not able to
trace code reliably while the stack pointer is in this range.
Here's something you can do instead, if you really need to trace
that CDA code: break into the application at a convenient point
(like at a TaskMaster call), set D=0 and start Stepping from the
CDA's entry point (one way to determine the entry point is with
Nifty List--try c018.5000i to find the right block in memory, and
use ;c to display the name and entry points).
Debugging a New Desk Accessory with GSBug was hard in the past,
because the debugger could not receive any keystrokes while an NDA
window was in front. With GSBug 1.5, just push down the CapsLock
key, and all is well (the NDA does not receive any keystrokes while
CapsLock is down and GSBug 1.5 is installed.)
Type off in GSBug to see the top 23 lines of your code's "Real" text
screen. Type on to get the GSBug screen back.
If you get really fancy, you can build the strings (used in the
SetMileStone and DebugStr calls) on the fly and imbed the values
of key variables into them to further simplify locating the bug.
If your development languages supports imbedding names or other
info about your source into your object, use them. This helps you
find routines at debug-time.
Nifty List Techniques
Nifty List is a Classic Desk Accessory by Dave Lyons. It's
Shareware, and you can download it from GEnie or America Online,
among other places. If he ever happens to be right in the same room
with you, be sure to ask him for a copy.
Here are a few things I do when I'm debugging some code with Nifty
List handy.
Pop into Nifty List and type V to see if you've really started up
all the tools you think you have, and make sure the Work Area
Pointers are valid (most tools use their WAPs for the address you
pass to the startup routine; the Control Manager is currently an
exception). Most of the other tool sets have valid handles or 0 for
their WAPs. This is not guarnateed, but it's a useful sanity check
while you're writing an application. (A few tool sets share the same
work areas. Don't worry; it's normal for the Window Manager and
Event Manager to share, and for QuickDraw II and QuickDraw II
Auxiliary to share, for example.)
Use the new Nifty List 3.0 \addfree and \check commands in Big
Brother module to detect accidental memory stomping.
Use c018.1000i to locate the static code segments in your application
("Info on handles with owner $10xx and memory manager attributes
$C018").
Use 0/0;w to dump info about your window, including the pointer to
the Content Draw routine. Make sure the content-draw routine does
not assume that the Bank or D registers are set on entry! If it
changes them, make sure it puts them back.
If your window doesn't update right, check your content draw
routine--you must not assume you are the frontmost window, so using
FrontWindow to see what window you're supposed to draw in is wrong.
Use GetPort instead, because TaskMaster sets the QuickDraw port to
your window before it calls your update routine.
Explore the toolbox by making toolbox calls directly from the Nifty
List command line.
When you Crash
When you crash, look on the stack for return addresses to see how
you got there. Sometimes things went so weird this is impractical,
but it often helps. Nifty List's ;s command looks for RTS and RTL
addresses for you automatically. (An "RTL address" is a sequence of
3 bytes on the stack that is the address of the last byte of a JSL
instruction your program has executed, but which has not yet
returned.)
Check the Direct page register on a crash--by comparing against the
WAPs for tools, you can often determine which toolset was in control
of the machine when it crashes (that doesn't mean it isn't your
fault, but it gives you a clue about where to look!).
Logic Analyzers
Logic Analyzers are hardware that hooks up to your computer and
watches what's going on. They're pretty expensive, and you don't
need one for most debugging problems. For certain types of problems,
though, they come in very handy. For example, if you have found a
particular byte of memory that gets changed for no reason, but your
best efforts to find out what piece of code is actually changing
that byte have failed, a logic analyzer can help. (Debugging code
that gets called during interrupts can be impossible to debug with
GSBug. If you can step through the code outside the interrupt
environment, great--if that's impossible, consider using a logic
analyzer.)
The general idea is to tell that logic analyzer to "trigger" on a
particular event (a read or write of a particular byte in memory)
and then to record what happens after that (storing everything that
the processor does, or just selected operations). This happens
quickly, and then you can scroll through the resulting list to see
exactly what happened in the next thousand or more clock cycles.
Trick: include accesses to known ROM locations to help you trigger
the analyzer at particlar spots in your code (STA $FF0000, $FF0002,
$FF0004, etc).
Here is some specific information about HP logic analyzers used for
debugging on the Apple II Family. The HP 16500 provides more
sophisticated trap specification end specification of which
instructions to store when a trap is in effect. This provides for
more trace mileage out of the 1024 instructions that can be traced
than is possible on the HP 1630G, also used at Apple. Also, the
16500 works just like the 1650A for a lot of things.
You can call the HP Customer Information Center at 1-800-752-0900,
extension779E. Their catalog says that if they don't have an answer
they'll put you in touch with someone who does.
Also, the software for using these analyzers with the 65816 or 65C02
is available direct from us at Apple along with instructions for
wiring the PODs accordingly. There are a couple of San Francisco
area companies who rent these machines (see below).
If you prefer to rent or lease the models, HP should be able to put
you in contact with a vendor in your area that could do this.
Engineers at Apple using these systems are very happy with them and
generally prefer the touch screen capability of the 16500 model.
(Hey, this isn't an endorsement, it's just information!)
Also, an in-circuit emulator for the IIe and IIgs is manfactured by
the Western Design Center, Inc. At the 1989 A2-Central Apple II
Developer's conference Andrew Hall demonstrated this ICE system,
called the Toolbox Design System, and stated that they would be open
to rentals of the system. You can contact The Western Design Center
at 2166 East Brown Rd., Mesa, AZ 85213, (602) 962-4545.
These HP Logic Analyzer units should be rentable through the
following companies:
Continental Resources McGrath RentCorp
1575 McCandless Drive 2500 Grant Avenue
Milpitas, CA 95035 San Lorenzo, CA 94580
(408) 263-1775 (415) 276-2626
(Thanks to Dan Strnad of DTS for this information on HP logic
analyzers)
--
David A. Lyons, Apple Computer, Inc. | DAL Systems
Apple II Developer Technical Support | P.O. Box 875
America Online: Dave Lyons | Cupertino, CA 95015-0875
GEnie: D.LYONS2 or DAVE.LYONS CompuServe: 72177,3233
Internet/BITNET: dlyons@apple.com UUCP: ...!ames!apple!dlyons
My opinions are my own, not Apple's.