Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!wuarchive!gem.mps.ohio-state.edu!usc!henry.jpl.nasa.gov!elroy.jpl.nasa.gov!zardoz!dhw68k!thecloud From: thecloud@dhw68k.cts.com (Ken McLeod) Newsgroups: comp.sys.mac.programmer Subject: Re: Tail patches Message-ID: <27484@dhw68k.cts.com> Date: 8 Nov 89 15:45:12 GMT References: <1459@sequent.cs.qmc.ac.uk> Reply-To: thecloud@dhw68k.cts.com (Ken McLeod) Organization: Wolfskill & Dowling residence; Anaheim, CA (USA) Lines: 53 In article <1459@sequent.cs.qmc.ac.uk> jeremyr@cs.qmc.ac.uk (Jeremy Roussak) writes: > >I hope the net will pardon my ignorance, but I have seen a few comments >recently about "tail patching" of traps and have a couple of questions: > >1. What exactly are "tail patches"? >2. If they are what I suspect they are, why are they bad? "Tail" patches call the original routine as a subroutine call, after which control returns to the patch code again. In pseudocode, they'd look something like this: TailPatchProc() Call(originalRoutineAddr); MessWithResult(); end This type of patch can and does break, and tech note #212 specifically warns against it. Some of Apple's patches check the return address on the stack when they're called; this address will be at the "MessWithResult" line in the above example (as opposed to in the routine the Apple patch is looking for.) Suppose, for example, you wanted to patch CopyBits to act differently IF AND ONLY IF it was being called from routine X. To do that, you might look at where CopyBits is going to return to after it's done and compare that address to the known address (or range) in routine X. If CopyBits has been "tail-patched" somewhere along the way, your patch will be broken: the return address will NEVER match your assumption. Now, when CopyBits DOES get called from routine X, the patch doesn't catch it, and depending on why the patch was written in the first place, the Mac may find the nearest cliff to jump over. GoodPatchProc() DoEverythingFirst(); move.l oldRoutineAddr,A0 jmp (A0) end // we never get here! // A much better way to write patches is to do everything you need to BEFORE calling the original trap. When you're ready, you JMP directly to the old routine, so that the original return address remains intact. Usually, this sort of patch only needs to alter parameters on the stack, or some external variable, so that the original routine will return the desired result. If the patch must wait to see what the original routine is returning, then it's time to think about a) writing your own replacement routine, or b) finding a better place to patch into. A lot of people make the mistake of patching GetNextEvent instead of using the jGNEFilter mechanism, for example. Disclaimer: All I know is what I read in technotes... :-) -- ========== ....... ============================================= Ken McLeod :. .: UUCP: ...{spsd,zardoz,felix}!dhw68k!thecloud ========== :::.. ..::: INTERNET: thecloud@dhw68k.cts.com //// =============================================