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 <pa@mjolner.com> and University of Aarhus, Denmark <datpete@daimi.au.dk> [demime 0.98b removed an attachment of type application/octet-stream which had a name of sigcontext.c] _______________________________________________ darwin-kernel mailing list | darwin-kernel@lists.apple.com Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/darwin-kernel Do not post admin requests to the list. They will be ignored.