home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.atari.st.tech
- Path: sparky!uunet!mnemosyne.cs.du.edu!nyx!ilepore
- From: ilepore@nyx.cs.du.edu (Ian Lepore)
- Subject: Re: Using Setexec() [a bit of help needed]
- Message-ID: <1992Aug18.002702.7663@mnemosyne.cs.du.edu>
- Sender: usenet@mnemosyne.cs.du.edu (netnews admin account)
- Organization: University of Denver, Dept. of Math & Comp. Sci.
- References: <1992Aug17.083005.6390@aber.ac.uk>
- Date: Tue, 18 Aug 92 00:27:02 GMT
- Lines: 224
-
- Organization: Nyx, Public Access Unix at U. of Denver Math/CS dept.
- X-Disclaimer: Nyx is a public access Unix system run by the University
- of Denver for the Denver community. The University has neither
- control over nor responsibility for the opinions of users.
-
- Using your example code, your call to set the interupt s/b:
-
- Setexc(2, BusError);
-
- But, since BusError() appears later in the code, you'll also need to add
- an "extern void BusError();" before the Setexc() call, or move the BusError()
- routine earlier in your code. That handles the C-syntax part of your
- question, but the full answer is longer...
-
- Depending on your compiler (you didn't say which one you're using), you
- may need to declare BusError() using a keyword such as _interupt. If your
- compiler doesn't support that keyword, there's a good chance you won't be
- able to write the BusError() routine in C. When the routine gets control,
- the machine will be in supervisor mode. Trying to use printf() in supervisor
- mode will probably lead to a crash.
-
- The best fix is to use signal(SIGSEGV, handler_function) if your library
- includes a signal-handling system. If it doesn't, here's some assembler
- code which you should be able to adapt to your purposes:
-
- ----------- cut here ----------------
- ;*************************************************************************
- ;*
- ;* EXHANDLR.S - Machine exception handler.
- ;*
- ;* This module hooks exception vectors 2, 3, 4, 5, 8, and 102 to catch ^C,
- ;* null pointer de-referencing, and so on. When an exception occurs, the
- ;* handler routine cleans the exception info off the supervisor stack,
- ;* forces the machine back to user mode, and does a longjmp() through
- ;* the jump buffer specified during the init call.
- ;*
- ;* This code can be assembled with MadMac or Sozobon's JAS.
- ;*
- ;* Typical usage is:
- ;*
- ;* RESTART_PROGRAM:
- ;*
- ;* if (0 != (exception = setjmp(exception_handler))) {
- ;* exh_remove_handler(); /* prevent ugly recursions */
- ;* if (exception > 0)
- ;* printf("Exception %d has been handled.\n", exception);
- ;* else
- ;* printf("Process termination has been handled.\n");
- ;* goto RESTART_PROGRAM; /* or exit() or Pterm() here */
- ;* }
- ;* exh_init_handler(exception_handler);
- ;*
- ;* The salient points are to install the setjmp() before the init_handler
- ;* call, and to be sure and remove the handler as the first thing right
- ;* after a return from longjump, to prevent recursion if another exception
- ;* happens while you're handling the first exception. If you are going
- ;* to take some restart action instead of terminating the program during
- ;* exception handling, be sure to re-install the setjmp() and the
- ;* exception handler before getting into your main logic again.
- ;*
- ;* Remember that the processor termination handler catches ALL
- ;* terminations, not just ^C, so if your program has exit() calls all
- ;* over the place, plan to get control if one of them is used to exit
- ;* the program. As of now, I don't know of a good way of catching only
- ;* ^C terminations but not exit() terminations. (Other than replacing
- ;* your library exit() routine with something that removes the handlers
- ;* and then continues by calling _exit(). Not all libraries support a
- ;* two-tiered exit/_exit system, dLibs does.)
- ;*************************************************************************
-
- .globl _exh_init_handler ;* export our name
- .globl _exh_remove_handler ;* export our name
- .globl _longjmp ;* import name of library routine
-
- .bss
-
- oldex2: .ds.l 1 ;* old exception vector 2 contents
- oldex3: .ds.l 1 ;* old exception vector 3 contents
- oldex4: .ds.l 1 ;* old exception vector 4 contents
- oldex5: .ds.l 1 ;* old exception vector 5 contents
- oldex8: .ds.l 1 ;* old exception vector 8 contents
- oldex102: .ds.l 1 ;* old exception vector 102 contents
- ex_jmpbuf: .ds.l 1 ;* pointer to jmp_buf for longjmp
-
- .text
-
- ;*****************************************************************************
- ;* the exception handlers...
- ;*****************************************************************************
-
- newex2: ;* Exception 2 - address error
- moveq.l #2,d0
- addq.l #8,sp ;* (clean extra 8 bytes off the stack)
- bra.b cleanex
- newex3: ;* Exception 3 - bus error
- moveq.l #3,d0
- addq.l #8,sp ;* (clean extra 8 bytes off the stack)
- bra.b cleanex
-
- newex4: ;* Exception 4 - illegal instruction
- moveq.l #4,d0
- bra.b cleanex
-
- newex5: ;* Exception 5 - divide by zero
- moveq.l #5,d0
- bra.b cleanex
-
- newex8: ;* Exception 8 - privilege violation
- moveq.l #8,d0
- bra.b cleanex
-
- newex102: ;* Exception 102 - ^C (Pterm) handler
- move.w #-32,d0 ;* (DOS uses -32 for a ^C return code,
- bra.b do_ljump ;* so we'll do the same.)
-
- cleanex:
- addq.l #6,sp ;* Remove exception SR and PC,
- do_ljump:
- ;* and.w #$DFFF,sr ;* force machine back to user mode.
- .dc.w $027C ;* JAS doesn't understand the SR reg...
- .dc.w $DFFF ;* these two lines are AND.W #$DFFF,SR
- move.w d0,-(sp) ;* Stack exception code.
- move.l ex_jmpbuf,-(sp) ;* Stack address of jump buffer.
- jsr _longjmp ;* Execute longjmp() function.
-
- ;*****************************************************************************
- ;* the init routine, installs handlers...
- ;*****************************************************************************
-
- _exh_init_handler:
-
- move.l 4(sp),d0
- beq punt
- move.l d0,ex_jmpbuf
-
- pea newex2
- move.l #$00050002,-(sp)
- trap #13 ;* Setexc(2,&newex2)
- addq.l #8,sp
- move.l d0,oldex2 ;* Save old vector.
-
- pea newex3
- move.l #$00050003,-(sp)
- trap #13 ;* Setexc(3,&newex3)
- addq.l #8,sp
- move.l d0,oldex3 ;* Save old vector.
-
- pea newex4
- move.l #$00050004,-(sp)
- trap #13 ;* Setexc(4,&newex4)
- addq.l #8,sp
- move.l d0,oldex4 ;* Save old vector.
-
- pea newex5
- move.l #$00050005,-(sp)
- trap #13 ;* Setexc(5,&newex5)
- addq.l #8,sp
- move.l d0,oldex5 ;* Save old vector.
-
- pea newex8
- move.l #$00050008,-(sp)
- trap #13 ;* Setexc(8,&newex8)
- addq.l #8,sp
- move.l d0,oldex8 ;* Save old vector.
-
- pea newex102
- move.l #$00050102,-(sp)
- trap #13 ;* Setexc(102,&newex102)
- addq.l #8,sp
- move.l d0,oldex102 ;* Save old vector.
- punt:
- rts ;* All done, return to caller.
-
- ;*****************************************************************************
- ;* the remove routine, de-installs handlers...
- ;*****************************************************************************
-
- _exh_remove_handler:
-
- move.l oldex2,-(sp)
- move.l #$00050002,-(sp)
- trap #13 ;* Setexc(2,oldex2)
- addq.l #8,sp
-
- move.l oldex3,-(sp)
- move.l #$00050003,-(sp)
- trap #13 ;* Setexc(3,oldex3)
- addq.l #8,sp
-
- move.l oldex4,-(sp)
- move.l #$00050004,-(sp)
- trap #13 ;* Setexc(4,oldex4)
- addq.l #8,sp
-
- move.l oldex5,-(sp)
- move.l #$00050005,-(sp)
- trap #13 ;* Setexc(5,oldex5)
- addq.l #8,sp
-
- move.l oldex8,-(sp)
- move.l #$00050008,-(sp)
- trap #13 ;* Setexc(8,oldex8)
- addq.l #8,sp
-
- move.l oldex102,-(sp)
- move.l #$00050102,-(sp)
- trap #13 ;* Setexc(102,oldex102)
- addq.l #8,sp
-
- rts
-
- end
-
- --------- cut here ----------------
-
- That's the code I use to trap unexpected errors in the HCC compiler piece.
- It's appropriate for simple things like issuing a message, closing files,
- and exiting the program. It is *NOT* appropriate for complex handling such
- as recovering from the bus error and continuing processing.
-
- --
- - Ian
- (void *) where prohibited by law
-
-