GSBug -- Current Version 1.6b20 Version 1.6b20 (DAL) Added new GS/OS call name SetStdRefNum, call number $203A. Fixed the version string so it doesn't say "Apple Confidential." Version 1.6b19 (DAL) To automatically load a templates file at boot time, it must be named GSBug.AutoTemp (in the System.Setup folder). If you use LoadTemp without a pathname, it still defaults to GSBug.Templates. Version 1.6b18 (DAL) Versions with 6.0 stuff included are now 1.6bxx; without 6.0 stuff is still 1.5bxx. LoadTemp command no longer returns a bogus error after successfully loading a templates file. Also, if you type LoadTemp with no pathname, it uses */System/System.Setup/GSBug.Templates. Turned off high bits on the GSBug.Setup file pathname, so you don't get a strange error while booting from an AppleShare server. KNOWN BUG: Don't put a breakpoint on an imbedded name. If you do, the name can get overwritten when the breakpoint is removed. Version 1.5b17 (DAL) Now supports inline imbedded procedure names (as generated by the name and procname macros in M16.Debug, for example). These show up in disassembly and as the operands of JSRs and JSLs. OSBreaks trigger regardless of call class now. For example, you can SetOSBrk for either Open or OpenGS, and either one will cause a break. Changed named-resource call names to begin with RM (RMLoadNamedResource, etc). When GSBug notices a toolbox call being made in other than full 16-bit mode, it displays a a warning dialog (using TLTextMountVolume). Hitting ESC at that dialog cancels future warnings until you reload GSBug. When GSBug notices a toolbox call being made with Decimal mode on, it stops cold at a BRK $F8, rather than letting things get completely baked before crashing. Fixed one old reference to $010100 to store $C0 instead of $80. Interrupts should reliably use $100..1C0 for stack space now. Added 5 blanks to end of 'TRACE ' message so it completely overwrites the 'SINGLE STEP' message. Version 1.5b16 (DAL) No such thang. Version 1.5b15 (DAL) Option-space now works reliably to bypass a memory-protect range, including a tool call. (This is an old feature, but keyboard translation normally prevented it from working!) In trace mode, Space and ESC now kill "awainting RTx" mode. Fixed "n" command so it won't crash if nobody has called DebugSetHook. Having tool breaks on calls which get made indirectly by GSBug no longer cause a crash. You can break on NewHandle now, for example. In Breakpoint subscreen, Space maps trigger count from 0 to 1 and from nonzero to zero. Tab moves between the address and count fields (easier than hitting arrows). In the memory-protect subscreen, Tab moves between columns. Added $01/FC00.FFFF (OS system service calls) to the memory protect list. Changed the default trace-window setting to center-screen. Changed the EmulStack value from $80 to $C0 (trying to get rid of some unpredictable crashes, probably caused by AppleTalk running out of stack space). This means you can safely trace a program while the stack is in the $01C1..01FF range, and that interrupts use $0100..01C0. GSBug now takes a whole bank, minimizing its effect on where things are located in memory relative to each other, and ensuring that tool breaks work reliably (tool calls never break if they come from the same bank the debugger is in). Note that templates do work; you can ignore the garbage error you still get from loadtemp. Version 1.5b14 (DAL) Versions 1.5b12 and b13 were never officially released. 1.5b14 is fine, except that I make no guarantees about the Template commands. I think they work, but you'll get a funky error message from loadtemp. When you let a JSL execute in real time (including a tool call), the debugger temporarily changes the owner ID of its own handle to match the owner of the handle containing the code you're debugging. This way MMStartUp returns the appropriate memory ID, instead of always returning the debugger's ID. DebugSetHook(nil) now removes the hook. The 1K bank 0 segment GSBug allocates now has the same ID as the debugger (was previously always $80xx). Fixed OS breaks to work after return from ProDOS 8 (added a Notify Proc to re-trap the OS vectors). Changed the "_" command so that if you don't type a number, it's like typing zero. For example, if you have a template called "Template" which displays an informational message, you can type "_Template" instead of "_Template 0". DP:xxx command dumps 16 bytes from DP to the command line. Tool call $0CFF DebugGetInfo(word):long. Word=0 returns the current value of the program counter (useful from a procedure called by the N command). Note that real-time counted breakpoints don't work for JMP() ($6C), JMP(,X) ($7C), JML() ($DC), and JSR(,X) ($FC). With Monte's help, located the misplaced CLI that was causing the X command used on a JSR to accidentally return with the Bank register set to the debugger's bank, and the Stack set to the Interrupt-time stack. Version 1.5b11 (DAL) You can use SetOSBrk and ClrOSBRK with call names now. Class-1 names all end in GS to distinguish them from their class-0 siblings. Examples: SetOSBrk #1 SetOSBrk _Create SetOSBrk #2001 SetOSBrk _CreateGS The debugger now changes its own handleUs memory ID during a real-time JSL to match the code being stepped. For example, now you can step over an MMStartUp and get the expected ID returned (the application's instead of the debugger's). Changed 'D' command to 'I' so it doesn't interfere with typing a hex number that starts with a D. The I command toggles the 'ignore REP/SEP instructions mode' when disassembling. Changed parsing for the P (Print screen) command so that it just beeps if there are any characters after the P. (Typing 'put' intead of 'out' can no longer hang your system.) Put the help screen for MP mode back in. The solid flashing cursor in MEM, MP, and BP no longer flashes. In exchange for this, special characters (like braces) that happen to be in Inverse don't flash while you're in the subscreens. Added pseudo tool call $0BFF=DebugSetHook (one Long parameter). The N ("neat- o") command calls this hook. Removed a conditional hard-coded increment of $004002 when X-ing a JSR. Added REP #$30 on the two tool-dispatcher-intercept routines. Making tool calls in other than full native mode is still not a good idea. Fixed real-time breakpoints for most 1-byte instructions and all 16-bit load immediate instructions. Previously, they crashed when used with a count greater than one. Please note that */System/System.Setup/GSBug.Setup is *already* loaded automatically (has been for quite a while). Version 1.5b10 (DAL) Stepping in emulation mode should be much more reliable now, although it isn't perfect (in particular, one place where there's a window of vulnerability is using X on a JSR in emulation mode, but if you have the I bit set in your P register there's no problem). Having the stack in $01xx works much better now, whether you're in emulation or not. This works by frequently stuffing a $80 into $01/0100 (EMULSTACK, the location the interrupt manager and other things used to set the $01xx stack when needed). If you trace code that actually uses the $01/0100 value to set the stack pointer, you still have a problem, since your program will start using the part of the stack that gets toasted on every interrupt. You can now type in GSBug even if the Event Manager is on but keyboard interrupts are off. Previously this would leave you dead in the water. Files created with CSave now have a real filetype/auxtype assignment ($5A/0005). Fixed DebugStr to return no error (previously it was returning the high two bytes of the caller's address as an error). Took out code that was checking $C020 (not SLOTREG at $C02D) to see if the printer slot was switched in. Makes no sense anyway, because a printer can legitimately be either an internal or external slot. Brought the list of Toolbox call names up to date for System Software 5.0.3 (see changes below). Added tool set names (for example, $0002 is Memory Manager). For some time, you've been able to use SetTBrk with a tool set number, to force a break on every call to that tool set. Now you can do it by name, too. Examples: SetTBrk #2 SetTBrk _Memory Manager ShowBrks Saved about 900 bytes by removing many extra copies of the string "Unknown". Obsolete call names removed: 1522 TEInsertPageBreak 2022 TEGetHooks 2122 TESetHooks 2222 TEGetDefProc Call names corrected: 0D02 RemoveFromOOMQueue 2115 SelectIText 1021 VDKeyGetKRCol 1121 VDKeyGetKGCol 1221 VDKeyGetKBCol Call names added: 3603 ReleaseROMResource 3703 ConvSeconds 010A SANEBootInit 020A SANEStartUp 030A SANEShutDown 040A SANEVersion 050A SANEReset 060A SANEStatus 090A FPNum 0A0A DecStrNum 0B0A ElemNum 5D0E TaskMasterContent 5E0E TaskMasterKey 1713 GetDeviceName 1813 PrGetPrinterSpecs 1913 PrDevPrChanged 1A13 PrDevStartup 1B13 PrDevShutDown 1C13 PrDevOpen 1D13 PrDevRead 1E13 PrDevWrite 1F13 PrDevClose 2013 PrDevStatus 2113 PrDevAsyncRead 2213 PrDevWriteBackground 3013 PrDevIsItSafe 2022 TEOffsetToPoint 2122 TEPointToOffset 2222 TEGetDefProc 2322 TEGetRuler 2422 TESetRuler 2522 TEScroll 2622 TEGetInternalProc 2722 TEGetLastError 2822 TECompactRecord 0123 MSBoot 0223 MSStartUp 0323 MSShutDown 0423 MSVersion 0523 MSReset 0623 MSStatus 0923 SetBasicChan 0A23 SetMIDIMode 0B23 PlayNote 0C23 StopNote 0D23 KillAllNotes 0E23 SetRecTrack 0F23 SetPlayTrack 1023 TrackToChan 1123 Locate 1223 SetVelComp 1323 SetMIDIPort 1423 SetInstrument 1523 SeqPlayer 1623 SetTempo 1723 SetCallBack 1823 SysExOut 1923 SetBeat 1A23 MIDIMessage 1B23 LocateEnd 1C23 Merge 1D23 DeleteTrack 1E23 SetMetro 1F23 GetMSData 2023 ConvertToTime 2123 ConvertToMeasure 2223 MSSuspend 2323 MSResume 2423 SetTuningTable 2523 GetTuningTable 2623 SetTrackOut 2723 StartMIDIDriver 2823 StopMIDIdriver 04FF DebugVersion 06FF DebugStatus 09FF DebugStr 0AFF SetMileStone Tool Set Names (You can use these with SetTBrk.) 0001 Tool Locator 0002 Memory Manager 0003 Misc Tools 0004 QuickDraw 0005 Desk Manager 0006 Event Manager 0007 Scheduler 0008 Sound Tools 0009 ADB 000A SANE 000B Integer Math 000C Text Tools 000E Window Manager 000F Menu Manager 0010 Control Manager 0011 Loader 0012 QuickDraw Aux 0013 Print Manager 0014 Line Edit 0015 Dialog Manager 0016 Scrap Manager 0017 Standard File 0019 Note Synth 001A Note Seq 001B Font Manager 001C List Manager 001D ACE 001E Resource Manager 0020 Midi 0021 Video Overlay 0022 Text Edit 0023 MIDI Synth 00FF Debugger GS/OS Call Names Brought the list of GS/OS call names up to date for System Software 5.0.3. Removed this call: $000E ExpandPath (becuase there's no class-0 version) Added these class-1 call names: $2029 Quit $2033 FSTSpecific $2034 AddNotifyProc $2035 DelNotifyProc $2036 DRename $2037 GetStdRefNum $2038 GetRefNum $2039 GetRefInfo What It Doesn't Do Yet Note--sometimes the debugger gets mysteriously disconnected from the Apple-Ctl-ESC vector. If you can reproduce this, let me know. Some of the help screens are incompelete or inaccurate. Templates currently limited to 64K. If template file >64K, it gets left open by accident. Breakpoints don't work quite right in bank-switched memory, either (it doesn't store the original instruction into the right bank?). Should show OS call names on a JSL $E100B0 (examine stack if stepping, and look for a PEA $xxxx in a disassembly). The debugger chains into the tool-dispatcher vectors its own way. It should use the standard method defined in GS Technical Note #87. Will implement pseudo Tool calls to set and clear debugger breakpoints under program control. May make the MEM locations labelable (and save labels in the config file). "Handle" template partially implemented? Unload should call UserShutDown on self (under ProDOS 8, just beep instead). Make sure that "\" for changing display modes is documented. Documentation The GSBug manual from APDA of 3/16/89 seems to be the latest there is. All features not covered there should be in these release notes. History This part of the document details all changes made to the debugger from version 1.3b1 to 1.5b8. Bug Fixes: Real Time Tool Breaks - The mechanism for using tool breaks real time has been modified, the old method never worked quite right, what used to happen was that when a tool break was to occur, the stub in the dispatch vector would simply jump into the debugger, this would cause the stack and processor not to be set as if they came from an interupt, and the next exit of the debugger would cause code execution to start at an inapropriate case, also the actual tracing of a tool break would also cause the debugger to improperly save the current registers, so that the stack/direct page and processor status might come back damaged from a tool break. The stub has been modified to now enter the debugger with a break instruction instead of jumping to the front. This seems to solve all real time tool break problems. Error tool breaks - These also did not work well, and did not seem to be used by anyone anyway, so they have been removed to make room for OSBreaks. Version 1.5b3: % display code was fixed so that the '*' would properly be displayed in front of any toolbox glue that is detected. % Fixed template data display so that if the data being displayed crosses a bank boundry, the data is properly followed into the new bank. % Modified the IN command so that it respects trigger counts of 0 and does not insert real time breaks. Version 1.5b5: % Added Glue tool break support. Now toolbreaks work for regular and glue tool breaks. ErrorBreaks do not work for glue as they do not make a lot of sense. % Made debugger work even when a DA window is open. See new features below. % Added keyClick so that you hear whenever the system draws a key from the event queue. Also, cleaned up some comments. Version 1.5b6: % Added new DebugStr toolcall that can be used to get more from the debugger. Version 1.5b7: % Added support for real time conditional breaks. % Added OSBreaks. % Fixed the Debugger tool calls (like DebugStr ) so that they use the proper tool numbers (they had the toolset number in the high byte instead of the low byte) Documentation for them should also be right. Version 1.5b8: % Added a debugger version and status call to the debugger tools. % Enhanced the OSBreak facility. % Removed the keyclicks because Dave complained. Version 1.5b9: % Fixed some bugs. New Features: DebugStr: This feature is designed to allow developers to better know where in their program the debugger was entered. The way this feature works is that if you want to enter the debugger programatically you can now also pass a string to the debugger which will be printed on the bottom line of the screen when the debugger is entered. The way this mechanism works is a fake tool call that the debugger now supports. Since this looks like a normal tool call it can be easily called by any high level language as well as by assembly language. This toolcall called DebugStr takes a single parameter, a pointer to a pascal string. When the tool call is made the debugger is entered as if you had put a break into your code, but the string you passed is displayed on the screen and the program counter has been bumped passed the tool call jsl. This way you can simply resume execution with two simple keystrokes (with the init version hit 'R' ). Calling this new feature might look something like this PushLong #DebugStr ldx #$09FF jsl >$E10000 ... DebugStr str 'You are about to do blah.' from pascal the same would be achieved by doing this... DebugStr('You are about to do blah.'); I would recommend that assembly language users use a macro to make the toolcall and call it _DebugStr. MPW IIGS Pascal users could use the following to define the debugstr routine: Procedure DebugStr(theString:str255); INLINE $09FFA2, $E1000022; This call will also work when being called via the glue vector. NOTE: Since this call is only available when the debugger is loaded you will ALWAYS want to be sure to remove ALL calls to the debugger before releasing your program (or even using it on machines that do not have a debugger installed). SetMileStone: SetMileStone operates exactly the same way as debugstr except that the debugger is not actually entered. This will allow tracking of random crashes by allowing you to call the SetMileStone routine with milestones that have been met. Any time the debugger is entered via a BRK instruction or thru the keyboard, the last string passed via the SetMileStone call will be displayed. The toolcall number for SetMileStone is $0AFF, the MPW IIGS Pascal interface might look like this: Procedure SetMileStone (theString:str255); INLINE $0AFFA2, $E1000022; DebugVersion, DebugStatus: These calls are added so that an application can identify the version of the debugger that is loaded and thus know what calls can be made to the debug tool. Currently, these calls are identical and return the same result. The DebugStatus call returns non-zero for true (as opposed to $FFFF which most people might want...) other than that these calls act the same as any other toolbox status or version call, each call requires a word space on the stack for the result which is on the top of the stack when the call completes. If a debugger is loaded that does not support this feature you will get a standard tool locator error. For version 1.5b8 the version number returned is $158F .As you might expect, this number will change as the debugger version changes and it will always go up, never down. Glue Snypher: Glue snypher is a routine that can recognize high level language tool calls that are made with the standard glue entry, when a call to glue is detected while disassembling an instruction the call to glue will be replaced with *_TooName in a manner similar to how real tool calls now work. Glue snypher is also used by the memory protect feature, if a glue call is detected while the standard toolbox memory protect range is on, the glue call will be treated as if it were a JSL >$e10000. All glue entries MUST be a JSL to one of 3 standard types of glue that are shown below: ToolGlueType1 LDX #$ToolNum JSL >$E10004 ... RTL ToolGlueType2 LDX #$ToolNum JML CommonCall ... CommonCall JSL >$E10004 ... RTL ToolGlueType3 LDX #$ToolNum JMP CommonCall If any other types of glue calls are used, they will not be properly detected. Glue Breaks: In addition to glue snypher further support was added for high level languages by extending the tool break support to the glue vector ($E10004). Since error conditions are treated differently with glue (The second RTL ain't mine no more...) it seems unreasonable to also support error breaks via the glue vector. OSBreaks: OSBreaks work very much the same way that tool breaks work with three exceptions. First, instead of breaking on a tool call they will break on a call to the OS. Next, you can NOT specify an OS break by name, only by number. Lastly, they are not supported in trace mode, only in real time mode. To use OSBreaks you simply type setOSBrk #xxxx where xxxx is the number of the OS routine that you want to break on. This number is matched exactly when an OS call is made, so if you do not know if the target call is class 0 or class 1 you must set the break for both calls. OSBreaks are supported via both vectors, inline and stackbased. The following is a list of commands that operate on OS breaks and what they do. SetOSBrk - adds a number to the OS break list ClrOSBrk - Removes a given number from the OS break list ClrAllOSBrk - Removes all numbers from the OS break list OSBrkIn - enables real time scanning for OS breaks OSBrkOut - disables real time scanning of OS breaks ShowBrks - lists all tool and OS breaks currently set. DA Debugging support: In the past it has always been difficult to debug certain new desk accessories because they accept keystrokes, and keep the debugger from receiving them. I have added a patching mechanism to the system event call that is installed when the debugger is installed that fixes this problem. The way this feature now works is that if the caps lock key is down no keyboard events get passed to system event (and then to any open DA's) and the debugger will always get them. A side effect of this is that when the debugger screen is not active applications will get the same keystroke events if the CAPS LOCK key is down. As a gentle reminder of this feature, when installed, it will make your GS speaker click whenever a key is processed by getNextEvent. The debugger used to click on every keystroke, regardless of the state of the CAPS LOCK key. Dave complained enough that the debugger was changed to only click when keys are pressed if the CAPS LOCK key is down. New Template types: We have added support for a few more data types in templates, these are mainly for use with GS/OS strings, but can also be used for any word length string. they are: InputStr: This type will read the next word of data and treat it as a length word for string data that follows. The entire contents of the string will be displayed. OutputStr: Similar to InputStr except that the first word is a buffer length and the second word is the string length. After the string is displayed the debugger will skip to the end of the buffer to find the next byte of data to process. RealTime Conditional Breakpoints: The debugger now supports conditional real time breakpoints. In the past when a breakpoint was entered in the breakpoint list and you used the IN feature to make them work real time, the trigger count that you entered was ignored. Now, If you the trigger count is supported the same way it is supported in trace mode, that is, if you insert a real time breakpoint with a count higher than 1 it will break on the Nth execution of the opcode at that location. NOTE: Currently the following opcodes are not supported as real time conditional breakpoints: JSL(mem), JSR(mem), JSR(mem,x), JMP(mem), JMP(mem,x), RTI. In addition to supporting a count value for real time break points, the debugger now also allows a simple conditional statement to be used instead. The debugger allows only one conditional statement at a time, but as many of the breakpoints can use it as you want. To enable the conditional statement (henceforth called IF) simply type an "i" when entering a breakpoints trigger value instead of a hex digit. To set the current IF use the command SetIF. the syntax of the SetIF command is as follows: SETIF {width} {Spec1}{Operator}{Spec2} Legal {width} values W for word B for byte Legal {Operator} values = for is equal to # for is NOT equal to < for is less than > for is Greater than or equal to Legal {Spec1} and {Spec2} values are A,X,Y,S,D,P,B for the corresponding register $BBXXXX as the address of a value in memory #$XXXX as a hexidecimal constant ({SPEC2} only) Some examples of IFs SETIF W A<#$0101 (Break if the word in is less than #$0101) SETIF B $021234=$034321 (Break if the bytes at $02/1234 and $03/4321 are the same.) NOTE: Currently only long addresses are supported.