Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!samsung!uunet!cbmvax!mks From: mks@cbmvax.commodore.com (Michael Sinz) Newsgroups: comp.sys.amiga.programmer Subject: Re: Creating a 'Front-End' For Library Functions Keywords: system integrity, libraries, SetFunction Message-ID: <22681@cbmvax.commodore.com> Date: 25 Jun 91 16:10:55 GMT References: <1991Jun25.084622.13642@clinet.fi> Reply-To: mks@cbmvax.commodore.com (Michael Sinz) Organization: Commodore, West Chester, PA Lines: 74 In article <1991Jun25.084622.13642@clinet.fi> dix@clinet.fi (Risto Kaivola) writes: >In a recent project I've had to create a front-end for certain dos.library >functions, meaning that first I patch a piece of code so that it will jump >to the library routine in question, and then change the library jump vector >so that it will jump to my code. So far, no problem (provided, of course, >that I remember to call the appropriate cache-handling library routines). >But when I'm finished, and want to remove the front-ends, and thus return >the system to the state in which it was earlier on, problems arise. >Obviously, I can't just return the library jump vector to its earlier state, >and then free the memory allocated for my code. If I did that, I would >take the chance that the system crashes when some task is executing off >non-allocated memory, and some other task allocates this memory block then >placing its data in this block. The possible solutions I've thought of are >as follows: The problem with removing a setfunction are more complex that what you have stated. There is at least one additional case that is very hard to even think about: What if another application does the same sort of thing? So, in general, it is best to not setfunction the system. If you absolutely must setfunction the system, you should make sure part of the setfunction stays around. The method I have used in the past was to have a structure much like below... Note that once installed, it stays there for good and all that is needed is the FP_NewVec is set up/removed at the right time and that programs are not in your code. struct FunctionPatch { struct SignalSemaphore FP_Semaphore; /* The semaphore */ ULONG FP_OldVec; /* Storage for old address */ ULONG FP_NewVec; /* Storage for new address */ UWORD FP_Code[?]; /* Storage for the code */ char FP_Name[30]; /* Storage for semaphore name */ } Then, I setup the semaphore and add it to the public list (as long as it is not there already) If it is already there, I grab the semaphore, make sure no one else it using it (FP_NewAdd) and install my new address there. In installing the semaphore, I sefunction the code below which is stored in FP_Code[] and store the old return address in FP_OldVec. FP_OldVec: dc.l 0 FP_NewVec: dc.l 0 FP_Code: move.l FP_OldVec(pc),-(sp) ; Set up for old routine move.l FP_NewVec(pc),-(sp) ; Set up for new routine bne.s FP_Patch ; If not NULL patch, skip addq.l #4,sp ; Ignore the patch... FP_Patch: rts ; Either jump to the patch ; which returns to the real ; one or just jump to the real ; one (stack magic) The above code would be different if the patch would happen after the real routine: FP_OldVec: dc.l 0 FP_NewVec: dc.l 0 FP_Code: move.l FP_NewVec(pc),-(sp) ; Set up for new routine bne.s FP_Patch ; If not NULL patch, skip addq.l #4,sp ; Ignore the patch... FP_Patch: move.l FP_OldVec(pc),-(sp) ; Set up for old routine rts ; Jump to the real thing ; and then, if there was a ; patch, to the patch. /----------------------------------------------------------------------\ | /// Michael Sinz - Amiga Software Engineer | | /// Operating System Development Group | | /// BIX: msinz UUNET: rutgers!cbmvax!mks | |\\\/// Programming is like sex: | | \XX/ One mistake and you have to support it for life. | \----------------------------------------------------------------------/