How do I find out what happened when I get a Method Not Found error?
When you get a Method Not Found error, that usually means that you called an operation on an instance of a class that doesn't define that operation, or you passed in an object that no longer exists. The object in question is what would have been the self parameter if the method was entered successfully. To take a look at this object to try to figure out what went wrong, single step past the RTS until you are back in the code that failed. Then issue the "ip" command and you will see the name of the method that was not found (right before the PC). The object is still at the top of the stack, and you can enter the command "dobj @sp" to dump the object.
Every now and then I get an exception failure. How can I use Telebug to figure out what they mean and why they happened?
Exception debugging isn't an exact science, and you'll usually wind up spending five or ten minutes doing different stack crawls to find the right return address to look at, but here's the basic jist of what's going on.
Exceptions happen when some piece of code calls Fail() to throw an exception. If you're running Telebug, this will land you either at a tst.l d2 instruction inside of Exceptions_Warn, or at a Debugger() statement inside the routine _CommonExceptionHandler. In theory, you can type "exc d0" to get an English description of the exception that occurred. In practice, this command returns "Cannot find attribute" more often than not, which isn't very useful.
What you'll have to do in this case is do a stack crawl to find the routine that called Fail to determine the type of exception it failed with. You need to be careful because you could be in supervisor mode because you're in the exception handler. In this case, if you do a stack crawl, you'll be looking at the supervisor stack, which is probably (but not definitely) not where the return addresses for your call chain are. You can compare sp with the value returned by usp. If the two are the same, you're looking at the right stack. If they're different, you'll have to execute a usc (user stack crawl) instead of a normal sc command to get the right stack.
You might see something like this:
# Exceptions_Warn I 0E08A90C # +0084 * TST.L D2 sc CallerPC Caller A6 Link Params I 0E06D948 # UserActor_Main+00FA 0001F66C D400 001F 0000 0000 FFFF I 0E13490A # TouchTool_TouchTarget+0010 0001F640 D440 00BF 0000 0000 D400 I 0E144206 # Viewable_Touch+0060 0001F614 8400 0773 D440 00BF 0E06 I 0E056A62 # Icon_Tap+003C 0001F600 8400 0773 D440 00BF D440 I 0E05689E # Icon_Action+004C 0001F5C4 8400 0773 D440 00BF 8400 I 0E14376A # Viewable_SetSuperview+0016 0001F504! 8400 0773 8400 0773 D440 I 0E1436F2 # _SetSuperviewAndOrigin+014C 0001F4D8 8400 07F2 8700 2000 0000 I 0E14358A # _AboutToHideOrShow+0044 0001F4A4 8400 07F2 0000 0001 0000 I 0E1406CA # Viewable_EachSubview+0036 0001F470 8400 07F2 0E14 34D2 0001 I 0E0B6856 # Card_AboutToShow+002E 0001F3E0! 8400 07F2 0E14 062C 0001 I 0E11AC68 # TextField_AdjustSize+0010 0001F384! 8400 25C1 8400 25C1 8400 I 0E117222 # TextFormatter_LineHeight+0012 0001F310! 8400 0D81 0000 0000 0E0B I 0E08A90A # Exceptions_Warn+0082 0001F310! 8400 264F D440 00D7 0E11
This would suggest that TextFormatter_LineHeight failed, or some routine that was called by TextFormatter_LineHeight.
From time to time I get a "Cleaning up" message for apparently no reason at all. Sometimes, I'll get an announcement afterwards that tells me I'm getting low on memory. When I look in the storeroom, I have over 200K of main memory left, so I think I've got plenty of space available. What's going on here?
Whenever you get a cleaning up message followed by an announcement that says that memory is getting low, that almost always means that you ran out of transient memory. You can verify that this is the case if you're plugged into Telebug. In this situation, you will stop at a Debugger statement inside of _WellKnownReset. The problem with running out of transient memory is that unless you've set up an exception handler, the device does a reset, and by the time you're at the debugger break, you don't know what routine was executing when you ran out of memory. If you find yourself at _WellKnownReset, you can look at the exception and exceptionReason fields of the user actor (by doing dobj iUserActor), to see what caused the reset. In the case of running out of transient memory, the exception value is 1, for cannotAllocateMemory, and the exceptionReason should be 5, which is the slot number for the transient RAM metacluster.
I would like to use "GetObj" to look at objects with ID's like $B400000C, but when I try to do this MacsBug complains that it is "unable to access that address". Lower addresses, like those starting with $8... seem to be fine, but the $B... ones just won't make it. Why can't I see certain objects?
If the object doesn't exist, or the object's context is not the current context, then the dcmd will usually just respond with "object not found" (or something to that effect). Sometimes, though, in trying to find an object that doesn't exist the dcmd will dereference an address that is invalid, causing Macsbug to issue the message about being "unable to access that address". Also, if Magic Cap is not the current application then you're almost certain to get this response from the dcmd. (Macsbug shows the current application, so you can see if you're inside Magic Cap or not)
An object ID starting with `B' represents a package object. In order to get at it with GetObj (or its many macros, such as dobj, do0, do1, etc) the package's context must be the current context. You can tell if a package context is current by issuing the `con' command and noting whether any package clusters are listed. Note that if you interrupt the system when it is "at rest" (i.e. just sitting there) then the package context will practically never be the current context. There are a few ways to pop into Macsbug while your package context is current. One way is to but a debugger break in one of your methods. Another is to put a breakpoint on one of your methods. Yet another way is to press on a package viewable, and while still holding the mouse button down, break into Macsbug. In any of these cases, the system will switch to your context as part of dispatching to your method. Another way, less deterministic, is to tap something that you know will run some of your code and break into the debugger as soon as you can (via the interrupt switch or Programmers' Key).
Where does Telebug keep its parsed symbols? I've pasted new symbols into the ROMEquates file, but the old symbols are still being used. How do I get rid of the old symbols?
The parsed symbols are stored by Telebug in the resource fork of the ROM equates file it is using. Load time for Telebug decreases dramatically when the pre-parsed symbols can be read directly instead of parsing the whole file.
You can't erase selected symbols, but you can erase all of them at once by deleting the resources. A quick way to do this is to quit Telebug and then execute the following in MPW:
echo "delete 'Regs';" | rez -a -o "{MagicTelebugFolder}"ROMEquates
The next time you start Telebug it will reparse the symbols and save new resources.
Is there a way to load the Telebug savestate of a RAM card into the Magic Cap simulation on the Mac?
What you need to do is use the save command in Telebug instead of savestate. You can then use the "Insert card into slot" command in Magic Cap to open this file. The syntax for the save command is:
save fileName 04000000 00100000
The first number is the base address for a PCMCIA card in slot one. (To save the image of a card in the second slot on an Envoy, use 08000000.) The second number is the size of the image you're saving. The number used in this example is the size for a one meg card. Both numbers are in hex.
Note that the default size for simulated PC cards is 600K, which is smaller than a typical PC card. You can change the default size the simulator uses with the "Set Simulated PC Card Size" item in the Magic menu.