Re: MacOSX signal handling
Re: MacOSX signal handling
- Subject: Re: MacOSX signal handling
- From: Peter Andersen <email@hidden>
- Date: Sat, 06 Apr 2002 02:34:49 +0200
Eric Albert wrote in reply to my original posting
(
http://lists.apple.com/mhonarc/unix-porting/msg00206.html):
>
Peter Andersen wrote:
>
>
> Is there no way to get to the register contents (and preferably modify
>
> it before returning from signal handler)??
>
>
I'll second Peter's questions -- I'm trying to do much the same thing, and
>
running into exactly the same problems. I suppose I could grovel through
>
the kernel sources to figure out just what its private data structure is,
>
but that's definitely not ideal.
>
>
I did note a message from Matt Watson on darwin-development from a bit
>
over a year ago that implied that a siginfo_t structure might be defined
>
soon...but that was before 10.0, and we still don't have them. How are
>
other folks dealing with ports that require intricate signal handling?
Not surpricing, I fully agree (:-)
I have replied the darwin-kernel list, and I am excited to hear the opinion
on this matter from you darwin-kernel folks.
Your reply, Eric, (the only one I got) convinced me that this was actually
missing in the current API. And I too do not like to dig up the private
structure from the kernel and use this (subject to change).
However, a clever colleague of mine suggested a general mechanism that can
be used if the signal context is polite enough (:-) to give at least the
program counter for the trapping instruction. In the MacOSX case, this is
just what you get (and ALL that you get!).
In short the principle goes as follows:
1. Set up the usual signal handler.
2. Inside this signal handler, save the PC indicating the origin of the
signal
3. Then (here comes the trick) modify the given sigcontext's PC by letting
it point to a routine you supply. I call this the "wrapper".
4. Now simply return from the signal handler.
Because of (3) the program continues execution at your "wrapper".
But besides this different program counter, the state of the machine
will be exactly as when the signal occurred.
5. Inside your "wrapper" you can now read all registers as they looked
when the signal occurred. You will have to write this routine in
assembler to avoid the standard C prologue to change anything before
you get your hands at it. If you set up a new stack frame, you can even
call a C routine to do the actual work of handling the signal (e.g.
switching on the signal number, reading and/or modifying register
contents). You could pass this C routine a pointer to the saved state.
6. When control returns to the wrapper, you restore all registers from the
context (thus also writing back any registers that were changed inside
the context by the C routine).
7. The final step is to set the return address of the wrapper to the
original PC as saved by (2) and then returning to your code.
This suggestion sounded so good that I have now made an implementation of it
in a modified version of my original program
(
http://lists.apple.com/mhonarc/unix-porting/msg00206.html).
The program is attached. Beware that it is only slightly tested - I have not
checked all registers, condition codes etc. Also I do not know if there is
more state that should be saved.
But it seems to work. You can compile it in a terminal as it follows, and
run it. Try hitting Control-C (which sends the SIGINT signal). As you can
see I only look at the SP (=GPR1) from within the handler, but it makes its
way all through the code (:-):
==========
[localhost:~] % cc --save-temps -O3 -o sigcontext sigcontext.c
sigcontext.c:88: warning: ANSI C forbids newline in string constant
[localhost:~] % ./sigcontext
Stack in main: 0xbffffa20
Going into infinite loop. Send me a signal using 'kill' (or simply ^C).
^C
MySignalCatcher:
Signal 2 caught at PC=0x1a58
[returning through MySignalWrapper]
MySignalHandler:
Signal number from signal_context: 2
PC from signal_context: 0x1a58
The stack pointer at signal time: 0xbffffa20
Type 'q' to quit; anything else to continue:
Returning from signal handler. Will continue infinite loop. Send more
signals!
^C
MySignalCatcher:
Signal 2 caught at PC=0x1a58
[returning through MySignalWrapper]
MySignalHandler:
Signal number from signal_context: 2
PC from signal_context: 0x1a58
The stack pointer at signal time: 0xbffffa20
Type 'q' to quit; anything else to continue: q
[localhost:~] %
==========
As you can see in the attachment, it requires quite a bit of assembler code
to implement this. I have to save ALL registers (and not only the callee
saves) since the code that the signal originates from has no knowledge of
the wrapper being (magically) "called".
I will test this a bit more, and will post corrections, if severe problems
occur.
However, as Eric and I stated initially, it seems strange why this
sigcontext in darwin does not supply us with this information (saving us
from trouble like this)?????
---
Sincerely,
Peter Andersen,
Mjxlner Informatics A/S <email@hidden> and
University of Aarhus, Denmark <email@hidden>
[demime 0.98b removed an attachment of type application/octet-stream which had a name of sigcontext.c]
_______________________________________________
darwin-kernel mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/darwin-kernel
Do not post admin requests to the list. They will be ignored.