alexis@ccnysci.UUCP (Alexis Rosen) (02/15/89)
I've been thinking about this for a couple of days now. Here's my scheme. Does anyone see any flaws? Procedure MyPatch SetTrapAddress to original trap address Trap to original trap using A-line instruction SetTrapAddress back to @MyPatch (&MyPatch for C people) Fixup stack and return It seems very simple. The only trick is that you have to store the original trap address in code-relative space (stick it after the end of the patch code). This is not a difficult thing to do, though it will break in a virtual-memory system (by that point there will have to be legitimate ways to do this anyway). So, what's the verdict? Alexis Rosen alexis@ccnysci.uucp
tim@hoptoad.uucp (Tim Maroney) (02/16/89)
In article <1272@ccnysci.UUCP> alexis@ccnysci.UUCP (Alexis Rosen) writes: > >I've been thinking about this for a couple of days now. Here's my scheme. >Does anyone see any flaws? > >Procedure MyPatch >SetTrapAddress to original trap address >Trap to original trap using A-line instruction >SetTrapAddress back to @MyPatch (&MyPatch for C people) >Fixup stack and return Nope, doesn't work. Imagine that GetResource checks to see if it's being called from GetFontInfo by looking at the return address. The reason you have to avoid tail patching is because if you just call the old GetResource from inside your patch of GetResource, the return address is inside your patch instead of inside GetFontInfo. Your approach has exactly the same problem. When your patch code calls the trap, the return address is inside your code, not inside GetFontInfo, the real caller. -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "Its failings notwithstanding, there is much to be said in favor of journalism in that by giving us the opinion of the uneducated, it keeps us in touch with the ignorance of the community." -- Oscar Wilde
grg@berlin.acss.umn.edu (George Gonzalez) (02/16/89)
I've thought about this problem too. Here's a scheme that might work. RealTrapAddr := GetTrapAddress( TheTrap ); SetTrapAddress( TheTrap, OurHookProc ); PokeLong( @MyTailPatch, SingleStepInterruptVector ); proc OurHookProc; ; gets called by the trap dispatcher. bset #TrapBit,XXX(SP) ; set single step trap bit in ret flags PushL RealReapAddress ; a registerless "jump" RTS ... the trap code runs, then when it returns, the CPU does a single step trap to your tail patch: proc MyTailPatch ... do my post processing... bclr #TrapBit,YYY(SP) ; turn off single stepping RTE Besides the obvious problem of being able to patch only one trap at a time, and needing different XXX and YYY offsets for 68000 and 68020+, this idea *might* just work.
fjo@ttrdf.UUCP (Frank Owen ) (02/17/89)
in article <1272@ccnysci.UUCP>, alexis@ccnysci.UUCP (Alexis Rosen) says: > > Procedure MyPatch > SetTrapAddress to original trap address > Trap to original trap using A-line instruction > SetTrapAddress back to @MyPatch (&MyPatch for C people) > Fixup stack and return Nope, Nope, Nope. This won't work. If the trap you are patching looks at what routine has called it by examining the return address on the stack, (Multifinder's GetNextEvent does this), it will appear as if only one routine (your patch) has ever called it. This may screw up the normal functioning of the original trap. (It would screw up Multifinder's GNE, for example.) -- Frank Owen (fjo@ttrdf) 312-982-2182 AT&T Bell Laboratories 5555 Touhy Ave., Skokie, IL 60077 PATH: ...!att!ttrdf!fjo
holland@m2.csc.ti.com (Fred Hollander) (02/17/89)
In article <1272@ccnysci.UUCP> alexis@ccnysci.UUCP (Alexis Rosen) writes: > >I've been thinking about this for a couple of days now. Here's my scheme. >Does anyone see any flaws? > >Procedure MyPatch >SetTrapAddress to original trap address >Trap to original trap using A-line instruction Apple uses come-from patches to patch ROM in traps that are called by buggy traps rather than replacing the entire trap. They check the return address to see if they should act. The trap address doesn't matter. At this point, the patch will still see your code as the return address and will not execute the bug fix. >SetTrapAddress back to @MyPatch (&MyPatch for C people) >Fixup stack and return >So, what's the verdict? A legal tail patch will check the return address and if in RAM, there wouldn't be a come-from patch, so it's safe to execute your patch. If you just want to check the results of the trap, you can call the original trap yourself, execute your code, then jump to the original trap address, where it will now see the callers return address (in ROM). The only drawback is that the trap gets called twice which why it's referred to as a come-again patch :). > >Alexis Rosen >alexis@ccnysci.uucp Fred Hollander Computer Science Center Texas Instruments, Inc. hollander@ti.com The above statements are my own and not representative of Texas Instruments.
tim@hoptoad.uucp (Tim Maroney) (02/17/89)
In article <293@berlin.acss.umn.edu> grg@berlin.acss.umn.edu (George
Gonzalez) suggests a legal way to do tail patching using single stepping.
It's very clever, and it gives me nightmares just thinking about it.
As George pointed out, only one trap can use this at a time. That in
itself is enough to disqualify it, since the old trap code that you call
might itself call another patched trap.
What if a debugger is on? That's bound to interfere with any software
use of the trace mode bit of the status register.
What about speed? Trace mode is generally quite slow.
What about compatibility across processor lines?
It's one of the more intriguing suggestions I've heard here, but really,
it's too weird to go into production quality software.
--
Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim
"What's the ugliest part of your body?
Some say your nose, some say your toes,
But I think it's your mind."
-- Frank Zappa
amanda@lts.UUCP (Amanda Walker) (02/17/89)
grg@berlin.acss.umn.edu (George Gonzalez) writes:
I've thought about this problem too. Here's a scheme that might work.
RealTrapAddr := GetTrapAddress( TheTrap );
SetTrapAddress( TheTrap, OurHookProc );
PokeLong( @MyTailPatch, SingleStepInterruptVector );
proc OurHookProc; ; gets called by the trap dispatcher.
bset #TrapBit,XXX(SP) ; set single step trap bit in ret flags
PushL RealReapAddress ; a registerless "jump"
RTS
Besides the obvious problem of being able to patch only one trap at a time,
and needing different XXX and YYY offsets for 68000 and 68020+, this idea
*might* just work.
It's a pretty clever idea, although it would be real annoying to try
and debug (since most debuggers like to use the Trace feature for,
well, tracing...). You can solve the processor problem by checking
CPUflag when you install the patch.
This is probably unworkable in general, though, for two reasons: only
one patch can use the mechanism at a time, and it might not work in
environments where the processor is not running in supervisor mode,
such as A/UX, MacOS with a virtual memory INIT, the prophesied MacOS
rewrite, etc...
But definitely clever :-)...
--
Amanda Walker ...!uunet!lts!amanda / lts!amanda@uunet.uu.net
InterCon, 11732 Bowman Green Drive, Reston, VA 22090
--
Calm down; it's only ones and zeros...
pratt@boulder.Colorado.EDU (Jonathan Pratt) (02/18/89)
In article <293@berlin.acss.umn.edu> grg@berlin.acss.umn.edu (George Gonzalez) writes: (about making legal tail patches) >I've thought about this problem too. Here's a scheme that might work. > > RealTrapAddr := GetTrapAddress( TheTrap ); > SetTrapAddress( TheTrap, OurHookProc ); > PokeLong( @MyTailPatch, SingleStepInterruptVector ); > > proc OurHookProc; ; gets called by the trap dispatcher. > bset #TrapBit,XXX(SP) ; set single step trap bit in ret flags > PushL RealReapAddress ; a registerless "jump" > RTS ... > proc MyTailPatch > ... do my post processing... > bclr #TrapBit,YYY(SP) ; turn off single stepping > RTE Am I missing something? This doesn't make sense to me. RealTrapAddr is set to the address of some trap routine, most likely one that obeys a pascal calling convention. There are no return flags once a trap routine has been called. At least in the Plus, the trap dispatcher disposes of them immediately. Am I wrong to think that this strategy hinges on trap routines using RTE's, which of course they don't? Jonathan /* Jonathan Pratt Internet: pratt@boulder.colorado.edu * * Campus Box 525 uucp: ..!{ncar|nbires}!boulder!pratt * * University of Colorado * * Boulder, CO 80309 Phone: (303) 492-4293 */
brecher@well.UUCP (Steve Brecher) (02/18/89)
In article <293@berlin.acss.umn.edu>, grg@berlin.acss.umn.edu (George Gonzalez)
suggests a way to do non-interfering tail patches by setting the trace trap
bit in the PSW on the stack.
This won't work because the trap dispatcher discards the old PSW and returns
with an RTS -- it does not return with an RTE.
--
brecher@well.UUCP (Steve Brecher)
dwt@well.UUCP (dwt) (02/19/89)
There seems to be a lot of smoke about Tail patches but when it all boils down, there is only one real answer. If Apple does it, IN MY OPINION, it must be possible, non-breakable in future and above all sanctioned. So, if you can find out how Apple does it, understand how it is being done and, MOST IMPORTANTLY, emulate their method EXACTLY, you should be OK! To that end I would strongly advise people to purchase the MacApp source listings to MacApp 2.0 and follow their nose. NO GUARANTEES ON MY PART. THIS IS NOT AN OFFICIAL MESSAGE OF ANY SORT. It appears a workable solution to me and whats more I couldn't post it if I wanted to but check it out and maybe this blather about No, it can't be done or Yes, it can be done will subside to a dull roar. Wow! Am I gald I got that off my chest. . . -- David W. Taylor, Detail Software, San Anselmo, CA 94960 (415) 453-0712 {pacbell,lll-winken,hoptoad,hplabs,apple}!well!dwt