[comp.sys.mac.programmer] Patching a trap question

mnkonar@manyjars.SRC.Honeywell.COM (Murat N. Konar) (09/26/89)

In article <6582@hubcap.clemson.edu> mikeoro@hubcap.clemson.edu (Michael K O'Rourke) writes:
>I know how to get a trap address and set a new address for the trap.  However,
>how can i get it to jump to my routine first and then let my routine decide 
>whether or not to pass the event or whatever on to the old routine that was  
>originally pointed to by the trap?  Now please keep in mind that i know
>absolutely no assembly language.  Is it possible to do this in C or Pascal?
>The responses that i got last time said that assembly was the only way.

What I do is write the patch in Pascal, compile it to a PROC resource 
(exactly what you call it is unimportant).  Then I use DisAsm3 (avilable
at ftp sites) to disassemble the patch, find the epilogue (the part where
the procedure cleans up after itself and returns).  I'm not going to go
into just what this looks like; for a real good explanation check out
Scott Knasters "How To Write Macintosh Software."  Anyhow, I find the
epilogue and note what assembly instructions are involved and write
a similar epilogue (using inline assembly) that leaves the stack in
the same state as it was when entered (except for data modifications)
and then JMPs to the real routine (never a JSR). Then I recompile the
patch proc with the inline code inserted. 

(Gawd, I hope you can follow that!) 

This method will only work for stack based traps.  Some trap routines
are register based and need glue.  I haven't played with any of those
yet.

____________________________________________________________________
Have a day. :^|
Murat N. Konar        Honeywell Systems & Research Center, Camden, MN
mnkonar@SRC.honeywell.com (internet) {umn-cs,ems,bthpyd}!srcsip!mnkonar(UUCP)

mikeoro@hubcap.clemson.edu (Michael K O'Rourke) (09/26/89)

I asked this question a few months ago, but thought i'd try it again to see if iget any more helpful answers this time.

I know how to get a trap address and set a new address for the trap.  However,
how can i get it to jump to my routine first and then let my routine decide 
whether or not to pass the event or whatever on to the old routine that was  
originally pointed to by the trap?  Now please keep in mind that i know
absolutely no assembly language.  Is it possible to do this in C or Pascal?
The responses that i got last time said that assembly was the only way.

Thanx,
Michael O'Rourke


Michael O'Rourke
Clemson Unversity 


=========================================================================
| Disclaimer:  I don't need one. Who'd sue a poor college student?      |
|-----------------------------------------------------------------------|
| "If you're doing business with a religious son-of-a-bitch, get it in  |
|  writing.  His word ain't worth shit.  Not with the good lord telling |
|  him how to fuck you on the deal." -- William S. Burroughs            |
=========================================================================

pwp@shamash.cdc.com ( HOUFAC) (09/27/89)

In article <6582@hubcap.clemson.edu> mikeoro@hubcap.clemson.edu (Michael K O'Rourke) writes:
>how can i get it to jump to my routine first and then let my routine decide 
>whether or not to pass the event or whatever on to the old routine that was  
>originally pointed to by the trap?  Now please keep in mind that i know
>absolutely no assembly language.  Is it possible to do this in C or Pascal?
>The responses that i got last time said that assembly was the only way.

I haven't used this technique in an actual trap patch, but it ought to work 
for any stack-based trap.  It lets you call the routine that is pointed to
by a procPtr.


The trick is to define a procedure with the same calling sequence as the trap,
but with one additional parameter.  This parameter is of type procPtr. The
body of the procedure consists of inline code to pop this last parameter from
the stack and "JSR" to it.

In your patch code, you'd simply pass all the parameters to this  routine,
with the address of the original trap code as the final parameter.

Of course, this may cause trouble for traps that are already patched. (See 
Scott Knaster's book, "How to Write Macintosh Software", appendix B, for
details of the problem.)  For that case, you're probably better off
with Murat Konar's technique of cleaning up the stack and "JMP"ing to the
original address.
 
Sample code follows.
 
--Pete Poorman
  pwp@shamash.cdc.com

--------------------------------------------------------------

program testcall;
 uses
  AddOneUnit;

 var
  i: INTEGER;
  AddOnePtr: procPtr;

 procedure callAddOne (var i: integer; addr: procPtr);
 inline
  $205F,	{ MOVE.L (SP)+,A0 }
  $4E90;	{ JSR      (A0)        }

begin
 writeln('In main program...');
 i := 0;
 CallAddOne(I, @AddOne);
 if i = 1 then
  WriteLn('It Worked!')
 else
  writeln('It failed, how sad...');
end.

--------------------------------------------------------------

unit AddOneUnit;
interface
 procedure AddOne (var i: integer);
implementation
 procedure AddOne (var i: integer);
 begin
  writeln('Hi there from AddOne!');
  i := i + 1;
 end;
end.