|
From: Jeremy F. <je...@go...> - 2003-08-19 06:13:58
|
On Mon, 2003-08-18 at 06:47, Steve G wrote:
> I suppose an approach might be something like this: Each
> time a signal is about to be delivered, check the mask. If
> any unblocked signal (besides the one about to be
> delivered) has a user defined signal handler, fake
> delivering a signal to it and only note the addresses it
> wanted to read data from or write data to and what the
> access type is (read or write). Don't let it actually
> write, reading is ok since its non-destructive. Then after
> faking a signal to all user defined handlers, check the
> list each time the current signal handler accesses a memory
> location. Only read/write or write/write collisions matter.
> The list gets thrown away at the end of the signal handler.
So you're saying speculatively run the signal handler without side
effects? I think that's pretty tricky. For one, it may have a read
which depends on one of its earlier writes. Even more tricky, it may
write to memory with a syscall, which would be hard to make
side-effect-free.
I think a helgrind-like algorithm would be more appropriate:
For each memory location, maintain a state. There are 4 states:
1. untouched
2. private - only touched by mainline code or a handler for a
particular signal, but not both
3. read-shared - only ever read by mainline and signal handlers
4. RW-shared - both read and written by mainline and signal
handlers
In RW-shared state, it keeps a set of signal handlers which touch the
memory location. If any code touches a location in RW-shared state, it
must have that set of signals blocked, otherwise it reports an error.
The tricky part is trying to determine if a given instruction is being
run as part of a signal handler or not. Entering the signal handler is
pretty obvious, since Valgrind has to go to some effort to deliver a
signal to a thread. Detecting when the application leaves the handler
is more tricky. If the handler does a normal return it's easy enough,
but if it longjmps out of the handler it's harder to tell. I think the
sure-fire way which works in both cases is to detect when ESP goes above
the signal stack frame - this will happen in both the longjmp and
sigreturn cases.
The other potentially tricky thing to handle is recursive signals. I
need to think about it more - it may just fall out in the algorithm
above. I think if you consider the mainline code to also be a
particular form of signal handler (SIGMAIN) then it comes out naturally.
J
|