Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!zaphod.mps.ohio-state.edu!usc!apple!ntg!dplatt From: dplatt@ntg.com (Dave Platt) Newsgroups: comp.sys.mac.programmer Subject: Re: Toolbox Patching Keywords: patch Message-ID: <772@goblin.ntg.com> Date: 29 May 91 18:37:56 GMT References: <1991May28.163618.8353@crash.cts.com> <13613@dog.ee.lbl.gov> Organization: New Technologies Group, Inc. Palo Alto CA Lines: 85 In article <13613@dog.ee.lbl.gov> osborn@ux1.lbl.gov (James R Osborn) writes: >Just what exactly is the preferred method for applying a >tail patch to a Toolbox routine? There is NO preferred method for tail-patching. It should not be done. > I've read all sorts of >stuff that waves its (metaphorically speaking) hands and >never explicitly says how to do it. That's because you shouldn't. The reason is as follows. The Mac startup code installs a bunch of patches, to correct bugs in the ROM toolbox routines and to add new functionality. Usually, these patches operate by replacing the affected routine... when you call the modified trap, the patch code is executed instead of the code in the ROM. However, there are cases in which it's undesirable to install this sort of patch... usually because the bug is buried deep in the middle of a large routine, and it would be necessary to replace an entire multi-kilobyte routine to fix the bug. Instead, the Toolbox maintainers examine the code in error, find a trap that _it_ calls, and then install a head patch in that (secondary) trap. The secondary patch checks the stack to see where it's being called from. If it's called from any location other than the location of the bug, it does nothing... it just jumps to the original trap-handler. If it was called from the routine that has the bug, it runs some code which corrects the effect of the bug somehow, and then branches to the original trap-handler. Now... consider what happens if _you_ install a tail-patch to the secondary trap. If that trap is called from the buggy code, then your patch takes control, does something, and then calls the routine it had superceded... which, in this case, will be the secondary bug-fixing patch. This patch will check to see whether it was called from the location where the bug exists. The answer will be "no"... because it was called from _your_ patch. The result? If you install a tail-patch on a trap that Apple is using as a secondary bug-fixer, then you will _disable_ Apple's bug fix! The machine on which you're running will probably exhibit odd symptoms, due to the fact that a necessary patch has been partially or completely disabled. >Here is something that I have done that worked but seems >incredibly unelegant and kludgey: > >using an init (this part seems ok to me): > >load the patch routine into the system heap with the init >DetachResource it >HNoPurge it >HLock it >save original trap address in the patch routine's header >set the trap address to point at the patch > >then in the patch: > >the patch routine gets passed the appropriate arguments > for the trap being patched >do my preprocessing, whatever it is >set trap address to original trap address (from header) >call trap, passing appropriate arguments, and saving > result (if necessary) >set trap address back to this patch >return result (if necessary) This is the traditional way to do a tail patch. >Why did I do it this way? Because I used C and was too lazy >to figure out how to call the trap routine directly myself >using assembly. I presume the preferred method is to push >the appropriate arguments onto the stack (pascal fashion) >and then JSR to the original trap? As I say, there is _no_ preferred method. It's a technique which should not be used. -- Dave Platt VOICE: (415) 813-8917 Domain: dplatt@ntg.com UUCP: ...apple!ntg!dplatt USNAIL: New Technologies Group Inc. 2468 Embarcardero Way, Palo Alto CA 94303