alexis@ccnysci.UUCP (Alexis Rosen) (02/17/89)
I'm astonished that I've only gotten one letter (and no flames) asking "how does this scheme overcome the problem with tail patches, since the problem is a come-from address check?" The answer is, it doesn't. I've got to admit, it was pretty harebrained. Especially the business about going through the trap dispatcher twice. HOWEVER- when I first thought of the idea, I got it right (I think). When I sat down to type it up my mind had wandered (_far_away_). The revised scheme, with better explanation: This method is not 100% general, in that the patch won't always execute. It will execute when it knows that your application called it, otherwise not. This may be a significant restriction, but I think it's still useful. 1) Test if the caller is the application 2) If it is, save the return address off of the stack, and JSR to the original routine 3) Otherwise, JMP to the original routine 4) Return to the caller The tricky part is #1, but since you are writing your application, you have a priori knowledge of where your app lives (usually in the app heap). So it shouldn't be too dificult to tell when to do what. Anything calling from the Application heap is OK. Anything else is verboten. I wonder how useful this would be for INITs and such. After all, they can't always be certain who is calling the trap, but it seems that anything sitting in the application heap or above MemTop should be OK. The system heap is out (that's where Apple's patches go, right?). Also, if the trap you are patching has a true ROM address, it can't have the kind of come-from checking code that tail patches break, so it should be OK to patch regardless of who calls it. (This assumes that Apple won't ship ROMs that have these ugly-but-useful hacks- they only get installed as bug fixes in the System Software). That would seem to leave a lot of room open for INITs. On the other hand, I've never written an INIT that does anything, so I'm not sure... Now, what say you? (this time :-) Alexis Rosen alexis@ccnysci.uucp
tim@hoptoad.uucp (Tim Maroney) (02/18/89)
In article <1285@ccnysci.UUCP> alexis@ccnysci.UUCP (Alexis Rosen) writes: >This method is not 100% general, in that the patch won't always execute. >It will execute when it knows that your application called it, otherwise >not. This may be a significant restriction, but I think it's still useful. > >1) Test if the caller is the application >2) If it is, save the return address off of the stack, and JSR to the > original routine >3) Otherwise, JMP to the original routine >4) Return to the caller > >The tricky part is #1, but since you are writing your application, you have >a priori knowledge of where your app lives (usually in the app heap). So >it shouldn't be too dificult to tell when to do what. Anything calling from >the Application heap is OK. Anything else is verboten. This should work for an application-specific patch. However, no such patch is ever neccessary. Let's say you want to patch SetHandleSize to use what a source at Apple informs me is generally faster: allocate a new handle at the new size, then copy memory, then free the old handle. You can do it with a patch, or you can declare a new routine called MySetHandleSize and call that instead. If you structure the patch as you've mentioned above, the effect is identical; the only difference is that the patching approach is a lot messier, since it requires assembly langauge and mucks about with the OS. >I wonder how useful this would be for INITs and such. After all, they >can't always be certain who is calling the trap, but it seems that >anything sitting in the application heap or above MemTop should be OK. >The system heap is out (that's where Apple's patches go, right?). Also, >if the trap you are patching has a true ROM address, it can't have the >kind of come-from checking code that tail patches break, so it should be >OK to patch regardless of who calls it. (This assumes that Apple won't >ship ROMs that have these ugly-but-useful hacks- they only get installed >as bug fixes in the System Software). That would seem to leave a lot of >room open for INITs. On the other hand, I've never written an INIT that >does anything, so I'm not sure... It's not too useful for INITs. At the very least, you would usually want the patch to work for DAs as well as applications. Usually you want it to be used by the OS internally as well. Suppose that, say, Suitcase only patched appl. traps as you suggest. Then when internal system routines tried to deal with fonts and DAs requested by the user, they wouldn't be able to see them. So I think you have come up with a legal but useless way to do tail patching. I wish Apple would just stop using come-from tests altogether, and if the OS eats another 64K of RAM as a result, big fat hairy deal. Maybe when RAM prices fall again next year.... -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "Gorbachev is returning to the heritage of the great Lenin" - Ronald Reagan
dean@mars.Berkeley.EDU (R. Drew Dean) (02/19/89)
In article <6562@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >... I wish Apple would just stop using come-from tests >altogether, and if the OS eats another 64K of RAM as a result, big fat >hairy deal. Maybe when RAM prices fall again next year.... >Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim No, Tim, why doesn't Apple issue new ROMS, so we don't need these stupid patches to begin with...They already take 60+K of RAM, which is very significant for those of us who have to pay for our own memory, and therefore currently have 1Mb..:-( [As a student who bought an SE in Oct. 87, I couldn't save the money up to buy RAM before all h*ll broke loose....] I suspect, that with a little work, Apple could also plug some security holes in the Resource Manager, as well...Remember that every SE ever shipped has 88Kb of digitized pictures floating in the ROMs. Get your code right, Apple ! Apple -- make new ROMs a upgrade that the user only pays for installation, which should be about $30....(The ROMs are still socketed, right ? If not, foget this idea....) Drew Dean Internet: dean@xcssun.berkeley.edu UUCP: ...!ucbvax!xcssun!dean FROM Disclaimers IMPORT StandardDisclaimer;
alexis@ccnysci.UUCP (Alexis Rosen) (02/19/89)
Tim Maroney remarks that my tail patch method is not terribly useful because you usually want the patch to always be in place. He uses the example of suitcase (actually, that was the first thing I tought of too). To be honest, this reaction doesn't surprise me much, because I think he's right in most cases. There is one exception, though, which is the case for which I developed this technique: parasitic (or symbiotic?) code modules, like XCMDs. In this case, you can't replace a trap for the application by just calling a different routine because you didn't write the app in the first place. This technique overcomes that and lets you monitor or alter a closed application in many ways (in my case, FoxBase, which is remarkably tolerant about parasites...) Anyway, it has proven a useful, if somewhat off-the-wall technique. While I'm comfortable with the compatibility, I still wonder if there's a better (read: faster to code) way... Alexis Rosen alexis@ccnysci.uucp
tim@hoptoad.uucp (Tim Maroney) (02/20/89)
In article <1288@ccnysci.UUCP> alexis@ccnysci.UUCP (Alexis Rosen) writes: > >Tim Maroney remarks that my tail patch method is not terribly useful >because you usually want the patch to always be in place. He uses the >example of suitcase (actually, that was the first thing I tought of too). > >To be honest, this reaction doesn't surprise me much, because I think he's >right in most cases. There is one exception, though, which is the case for >which I developed this technique: parasitic (or symbiotic?) code modules, >like XCMDs. In this case, you can't replace a trap for the application by >just calling a different routine because you didn't write the app in the >first place. Correct; I hadn't considered extensible applications or "gene-spliced" ones (I'm tempted to use the term "benign virus", but presumably the patches you're talking about don't reproduce). Your technique would be useful and legal (enough) in those cases. Sorry for the oversight, and thanks for the idea. -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "Philosophy is the talk on a cereal box Religion is the smile on a dog" -- Edie Brickell, "What I Am"
lsr@Apple.COM (Larry Rosenstein) (02/21/89)
In article <1285@ccnysci.UUCP> alexis@ccnysci.UUCP (Alexis Rosen) writes: > >1) Test if the caller is the application >2) If it is, save the return address off of the stack, and JSR to the > original routine >3) Otherwise, JMP to the original routine >4) Return to the caller > >The tricky part is #1, but since you are writing your application, you have You are looking at this from the wrong point of view. Look at it from the system's point of view. It seems to me that the only time a come-from patch is used is to fix a bug in the ROM (if the bug was in RAM, we would simply release a totally new piece of code). This means: (A) The only traps that would have a come-from patch are ones called by the ROM. If you know (or can convince yourself) that a certain patch is never called from the ROM, then it probably can't have a come-from patch. (B) If you patch a trap and find the return address is not in ROM (ie, the call was not made from ROM), then it should be safe to JSR to the original trap routine. This is similar to test #1 above, except you don't check to see if the return address is in you application, you test to see if it is in RAM. >if the trap you are patching has a true ROM address, it can't have the >kind of come-from checking code that tail patches break, so it should be >OK to patch regardless of who calls it. (This assumes that Apple won't Some system patches don't look at the return address, because the entire trap routine is being replaced (eg, TextEdit). These patches don't look at the return address at all. The only caveat about the above info is that I don't work on system patches, so I don't have the definitive word about them. Also, you can still get into trouble with any patch, tail or not. I had a problem with QUED/M because one of my trap patches called _OSEventAvail. (It turned out that QUED/M patches _OSEventAvail and their patches were not reentrant.) Another problem I had was assuming that anytime a trap is patched the original trap is always called. That is not the case for some of the traps patched by Suitcase and MultiFinder. It is always a good idea with any patch to review the assumptions you are making about how the system works, and how likely those assumptions might be violated. If you make a tail patch, you are assuming that the system won't patch the same trap with a come-from patch. That might be a relatively safe assumption in certain cases, but a bad assumption in others. Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr
bob@accuvax.nwu.edu (Bob Hablutzel) (02/21/89)
> It seems to me that the only time a come-from patch is used is to fix a bug > in the ROM (if the bug was in RAM, we would simply release a totally new > piece of code). This means: > (A) The only traps that would have a come-from patch are ones called by the > ROM. If you know (or can convince yourself) that a certain patch is never > called from the ROM, then it probably can't have a come-from patch. > (B) If you patch a trap and find the return address is not in ROM (ie, the > call was not made from ROM), then it should be safe to JSR to the original > trap routine. This is similar to test #1 above, except you don't check to > see if the return address is in you application, you test to see if it is in > RAM. Lemme jump in here with a question, and a comment... Are Apple people the only people blessed to do come-from patches? Let us assume, for the sake of argument, that I have an application which does come-from patches (very carefully). Am I breaking the rules? Also, if I am not breaking the rules, I would really appreciate it if Apple did not tail-patch. (gotcha!) I know of at least one: the _Open patch in MPW, which seems to be concerned with having too many files open. Why couldn't this be handled in a subroutine? This is MPW 3.0, btw, which I got with my TML II upgrade. MPW 2.0.2 is fine. And, hey, if I'm wrong about this I'll happily eat, er, crow. Bob Hablutzel Wildwood Software BOB@NUACC.ACNS.NWU.EDU
lsr@Apple.COM (Larry Rosenstein) (02/22/89)
In article <10050076@accuvax.nwu.edu> bob@accuvax.nwu.edu (Bob Hablutzel) writes: > >Are Apple people the only people blessed to do come-from patches? Let us >assume, for the sake of argument, that I have an application which does >come-from patches (very carefully). Am I breaking the rules? By definition, a come-from patch means you are looking at the return address to decide whether to do something. In the System's case, these patches fix ROM bugs, and are hard wired with ROM addresses. If you want to do a similar thing, then you will have to hard-wire or somehow figure out what the desired come-from address is for each ROM. So if you are prepared to deal with different ROMs, then I suppose you can do a come-from patch. You are almost guaranteed not to work on new machines. The same cautions about any patch apply in this case. >Also, if I am not breaking the rules, I would really appreciate it if Apple >did not tail-patch. (gotcha!) I know of at least one: the _Open patch in MPW, >which seems to be concerned with having too many files open. Why couldn't this >be handled in a subroutine? This is MPW 3.0, btw, which I got with my TML II I don't know. One reason might be to support tools compiled for an earlier version of MPW. Presumably the MPW people talked to the System Software people and know what they are doing. MPW is not a typical application. It has to hook into the File Manager in several places to provide the appearance that files and windows are the same. It also sets up separate worlds for the tools it runs, etc. Plus the MPW people have the benefits of working for Apple. Doing any kind of patch is a risk, since there are many applications out there that have subtle bugs in them that patches may being out. (There are lots of programs out there that pass the wrong thing to MenuSelect, which screwed me up.) Anytime you want to write a patch you have to weigh the benefits vs. the risks. Some patches are riskier than others. As I said before, you should think carefully about what assumptions your patches are making, and how those assumptions may be violated in the future. The bottom line is that its your machine, and you can do whatever you want with it. A good example of this is my "sure-fire Tetris beating" INIT, which patches the _Random trap and returns the same value each time. (Tetris is much easier if all you get are straight pieces. :-)) Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr
jmunkki@kampi.hut.fi (Juri Munkki) (02/22/89)
In article <10050076@accuvax.nwu.edu> bob@accuvax.nwu.edu (Bob Hablutzel) writes: >Are Apple people the only people blessed to do come-from patches? Yes. I would never write a come-from patch even if I knew it was allowed. The problem is that come-from patches prevent tail-patching. There is a rather complicated way in which apple could allow tail-patching while still doing their own come-from patching. Apple could change SetTrapAddr aj GetTrapAddr so that the actual trap dispatch table is not changed for the come-from patched traps, but the current patch is "told" that someone wants to patch it. The come-from patch could then still do the come-from stuff and it could then safely jsr/jmp to the patched routine. GetTrapAddr should return the address that the come-from patch calls. This way no one will loose, but programmers will be allowed to do tail patching. To illustrate: Before patching After patching _______________ ______________ Program calls a trap Program calls a trap Trap dispatcher calls routine Trap dispatcher calls routine Come-from patch does something Come-from patch does something Come-from patch calls ROM Come-from patch calls new patch. New patch calls ROM... Apple: Please implement this in the next system release... _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._ | Juri Munkki jmunkki@hut.fi jmunkki@fingate.bitnet I Want Ne | | Helsinki University of Technology Computing Centre My Own XT | ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
siegel@endor.harvard.edu (Rich Siegel) (02/23/89)
In article <19886@santra.UUCP> jmunkki@kampi.hut.fi.UUCP (Juri Munkki) writes: >Before patching After patching >_______________ ______________ >Program calls a trap Program calls a trap >Trap dispatcher calls routine Trap dispatcher calls routine >Come-from patch does something Come-from patch does something >Come-from patch calls ROM Come-from patch calls new patch. > New patch calls ROM... Unless I'm mistaken, Radius pulls a trick like this in their display INITs. --Rich Rich Siegel Staff Software Developer THINK Technologies Division, Symantec Corp. Internet: siegel@endor.harvard.edu UUCP: ..harvard!endor!siegel Phone: (617) 275-4800 x305
tecot@Apple.COM (Ed Tecot) (02/25/89)
In article <19886@santra.UUCP> jmunkki@kampi.hut.fi.UUCP (Juri Munkki) writes: >To illustrate: >Before patching After patching >_______________ ______________ >Program calls a trap Program calls a trap >Trap dispatcher calls routine Trap dispatcher calls routine >Come-from patch does something Come-from patch does something >Come-from patch calls ROM Come-from patch calls new patch. > New patch calls ROM... > >Apple: Please implement this in the next system release... The major problem with this is that it will make the trap dispatcher significantly slower. Considering that it is the most executed code in Macintosh, it would probably translate into a significant performance degradation. So I ask, is it worth it? _emt
jmunkki@kampi.hut.fi (Juri Munkki) (02/25/89)
In article <26341@apple.Apple.COM> tecot@Apple.COM (Ed Tecot) writes: >In article <19886@santra.UUCP> jmunkki@kampi.hut.fi.UUCP (Juri Munkki) writes: >>To illustrate: >>Before patching After patching >>_______________ ______________ >>Program calls a trap Program calls a trap >>Trap dispatcher calls routine Trap dispatcher calls routine >>Come-from patch does something Come-from patch does something >>Come-from patch calls ROM Come-from patch calls new patch. >> New patch calls ROM... >> >>Apple: Please implement this in the next system release... > >The major problem with this is that it will make the trap dispatcher >significantly slower. Considering that it is the most executed code in >Macintosh, it would probably translate into a significant performance >degradation. So I ask, is it worth it? Why would it slow down the trap dispatcher? You wouldn't have to change the trap dispatcher. Here's how you would do it... 1. Normally apple patches have jmp instructions directly into the ROM after they check for tail patches. Change this so that they jump into a table of jmp instructions into ROM. This doesn't significantly slow down the system. 2. Change SetTrapAddress so that it first checks to see if the trap needs come-from patching. If it does, don't change the trap dispatch table, but write the new address into a jump table within the system patches. You have to clear the cache in order to safely write into the jump table, but apple has the right to do stuff like this... 3. Change GetTrapAddress so that it first checks if the trap does come-from patching. If it does, return the address that is contained in the jump table. If the routine only has the apple patch, the ROM address will be returned. So, why would this scheme slow down the trap dispatcher? BTW: MacTutor once published the code for the MacPlus trap dispatcher. I looked at it and could see an improvement of 2 cycles... Maybe I was wrong... maybe I should have tried it. _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._ | Juri Munkki jmunkki@hut.fi jmunkki@fingate.bitnet I Want Ne | | Helsinki University of Technology Computing Centre My Own XT | ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
lsr@Apple.COM (Larry Rosenstein) (02/27/89)
In article <19971@santra.UUCP> jmunkki@kampi.hut.fi (Juri Munkki) writes: > 3. Change GetTrapAddress so that it first checks if the trap does >come-from patching. If it does, return the address that is contained in >the jump table. If the routine only has the apple patch, the ROM address >will be returned. No good. A program may do a GetTrapAddress, and JSR directly to that as a way to save time (although I doubt that you save much time at all). GetTrapAddress must therefore return the same address you would jump to by executing the trap. Your approach tries to keep the come-from patch as the "last" patch for the particular trap (ie, the code that gets control first). I don't think you can change the way Get/SetTrapAddress works and still maintain compatibility. Larry Rosenstein, Apple Computer, Inc. Internet: lsr@Apple.com UUCP: {nsc, sun}!apple!lsr AppleLink: Rosenstein1
jmunkki@kampi.hut.fi (Juri Munkki) (03/01/89)
In article <785@internal.Apple.COM> lsr@Apple.COM (Larry Rosenstein) writes: >In article <19971@santra.UUCP> jmunkki@kampi.hut.fi (Juri Munkki) writes: >> 3. Change GetTrapAddress so that it first checks if the trap does >>come-from patching. If it does, return the address that is contained in >>the jump table. If the routine only has the apple patch, the ROM address >>will be returned. > >No good. A program may do a GetTrapAddress, and JSR directly to that as a >way to save time (although I doubt that you save much time at all). >GetTrapAddress must therefore return the same address you would jump to by >executing the trap. > >Your approach tries to keep the come-from patch as the "last" patch for >the particular trap (ie, the code that gets control first). I don't think >you can change the way Get/SetTrapAddress works and still maintain >compatibility. > Oh, but it does work! The code that doesn't get called is only the come-from patch. This code only patches ROM code anyway. If an application gets the trap address and calls it, it is in RAM and won't be affected by the come-from patch. SectRect is one of the come-from patches. It doesn't have any bugs of its own. A buggy routien would have to have two levels of patching. One for the come-from patch and one for the real patch. Since come-from patched traps seem to be simple and short (like SectRect), they do not usually contain any bugs. This way some complex traps would take a little more time (one jsr/rts), but overall you wouldn't loose anything. I'm starting to get the feeling that Apple is afraid to touch the system software in case they introduce new incompatibilities. The only way out is to write a new partly source-compatible OS. Long ROM routines should be broken into several subroutines so that patches replace only one subroutine. If the new apple OS is good and Apple adds some new coprocessors (graphics and signal) as standard hardware on some of their new machines, I might drop the line about NeXT in my signature...I'm not all that enthusiastic about Unix...it seems even harder to patch/change than Mac OS. _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._ | Juri Munkki jmunkki@hut.fi jmunkki@fingate.bitnet I Want Ne | | Helsinki University of Technology Computing Centre My Own XT | ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
bob@accuvax.nwu.edu (Bob Hablutzel) (03/02/89)
> Oh, but it does work! The code that doesn't get called is only the come-from > patch. This code only patches ROM code anyway. Wrong. Come-from patches can patch RAM code also. Trust me. Bob Hablutzel Wildwood Software BOB@NUACC.ACNS.NWU.EDU Disclaimer: I work for myself. If I wanted to say more, I would.
jmunkki@kampi.hut.fi (Juri Munkki) (03/03/89)
In article <10050084@accuvax.nwu.edu> bob@accuvax.nwu.edu (Bob Hablutzel) writes: >> Oh, but it does work! The code that doesn't get called is only the come-from >> patch. This code only patches ROM code anyway. > >Wrong. Come-from patches can patch RAM code also. Trust me. > Oh? Why would they do that? (Is it the MultiFinder patching?) What I should have said is that they patch known code. It doesn't matter if a random program bypasses the come-from code. The only occasion that I can think of is where the come-from patch tries to see if it is called from a vague area in memory (like the system or application heap), but I don't think this is done... _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._ | Juri Munkki jmunkki@hut.fi jmunkki@fingate.bitnet I Want Ne | | Helsinki University of Technology Computing Centre My Own XT | ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
bob@accuvax.nwu.edu (Bob Hablutzel) (03/04/89)
> What I should have said is that they patch known code. It doesn't matter > if a random program bypasses the come-from code. The only occasion that > I can think of is where the come-from patch tries to see if it is called > from a vague area in memory (like the system or application heap), but I > don't think this is done... Wrong again. Can't say who or what or why. Bob Hablutzel Wildwood Software BOB@NUACC.ACNS.NWU.EDU