|
From: Ivo R. <iv...@iv...> - 2014-05-31 18:58:50
|
I would like to ask what are the possibilities of intercepting a write to a memory address under valgrind, regardless of a tool currently used. For the valgrind port to Solaris, I am investigating whether it is possible to intercept a write to an address and replace it with some hook in the syscall machinery. Every thread has its own address (it is per thread) and the address is not known prior to running the program - it is known before the thread performs some synchronization operation. In particular, I cannot modify source code which contains the write. In x86 assembly it is simple 'movl' from register to a memory location. ---------------------- Motivation is the following: Solaris contains a special libc/kernel synchronization mechanism. A piece of per-thread memory is shared between libc and kernel. It is used for various purposes, one is for 'block-all-signals' flag. Libc prior to certain synchronization operations writes to that memory indicating to the kernel that all signals should be blocked. Eventually a regular syscall is invoked; kernel detects the flag, disables all signals and clears the flag. The problem here is that setting this flag by libc bypasses Valgrind's signal machinery which gets confused by the fact that all signals are disabled in kernel without knowing it (which would be no problem should this went through regular syscall sigprocmask & friends). ---------------------- Thanks in advance for any pointers and suggestions. I. |
|
From: John R.
|
On 05/31/2014 11:58 AM, Ivo Raisr wrote: > I would like to ask what are the possibilities > of intercepting a write to a memory address > under valgrind, regardless of a tool currently used. It would be possible, but unlikely. Every store to memory would have to compare against the address. That's too slow. Instead, perform the comparison only when the result can possibly affect execution, which is at a system call. > <<snip>> > ---------------------- > Motivation is the following: Solaris contains a special > libc/kernel synchronization mechanism. Does this feature of Solaris has a name? Please tell us the name, and include a link to the documentation. > A piece of per-thread memory is shared between libc and kernel. Either the address (or an algorithm to compute it) is known in advance before each thread starts, or the thread performs a system call to learn the address that the OS has chosen. Please document. One likely possibility is that the address is a fixed offset into the thread control block, where libc and the kernel have agreed on the location and layout of that block. > It is used for various purposes, one is for 'block-all-signals' > flag. Libc prior to certain synchronization operations writes to > that memory indicating to the kernel that all signals should > be blocked. Eventually a regular syscall is invoked; > kernel detects the flag, disables all signals and clears the > flag. The problem here is that setting this flag by libc > bypasses Valgrind's signal machinery which gets confused > by the fact that all signals are disabled in kernel without > knowing it (which would be no problem should this went > through regular syscall sigprocmask & friends). The most likely way to implement such a feature in valgrind would be to have a Solaris-specific implementation of every system call that is affected by the special control word. If <stdlib.h> "read()" were affected then there would be a Solaris-specific version of "Int VG_(read)" [currently in coregrind/m_libcfile.c] which would implement the feature: test the word, call sigprocmask() if necessary, etc. It might be necessary to have a Solaris-specific implementation of EVERY system call where valgrind uses sigprocmask, if valgrind's current internal use of sigprocmask is not compatible with the semantics of the Solaris control word. |
|
From: Ivo R. <iv...@iv...> - 2014-06-01 03:18:39
|
>> I would like to ask what are the possibilities of intercepting a write to a memory address >> under valgrind, regardless of a tool currently used. > > It would be possible, but unlikely. Every store to memory > would have to compare against the address. That's too slow. Thank you for confirming my suspicion. > Instead, perform the comparison only when the result can > possibly affect execution, which is at a system call. That's what I had in my sleeve provided the write interception proves unfeasible. >> ---------------------- >> Motivation is the following: Solaris contains a special >> libc/kernel synchronization mechanism. > > Does this feature of Solaris has a name? Please tell us the name, > and include a link to the documentation. It is called 'schedctl' and you can find the header file here: http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/sys/schedctl.h#70 Not much documentation is available, though. The concept is briefly touched here: https://blogs.oracle.com/dave/entry/inverted_schedctl_usage_in_the but it mainly discusses 'sc_preemptctl' flag, not 'sc_sigblock' flag. > Either the address (or an algorithm to compute it) is known in advance > before each thread starts, or the thread performs a system call to > learn the address that the OS has chosen. Please document. The latter - OS provides an address of sc_shared_t (after a corresponding syscall). That piece of memory is then shared between kernel and libc for a particular thread. > One likely possibility is that the address is a fixed offset > into the thread control block, where libc and the kernel > have agreed on the location and layout of that block. Exactly. > The most likely way to implement such a feature in valgrind > would be to have a Solaris-specific implementation of every system call > that is affected by the special control word. If <stdlib.h> "read()" > were affected then there would be a Solaris-specific version of > "Int VG_(read)" [currently in coregrind/m_libcfile.c] which would > implement the feature: test the word, call sigprocmask() if necessary, > etc. It might be necessary to have a Solaris-specific implementation > of EVERY system call where valgrind uses sigprocmask, if valgrind's > current internal use of sigprocmask is not compatible with the semantics > of the Solaris control word. Will investigate. Thank you for responding, I. |
|
From: John R.
|
>> The most likely way to implement such a feature in valgrind >> would be to have a Solaris-specific implementation of every system call >> that is affected by the special control word. If <stdlib.h> "read()" >> were affected then there would be a Solaris-specific version of >> "Int VG_(read)" [currently in coregrind/m_libcfile.c] which would >> implement the feature: test the word, call sigprocmask() if necessary, >> etc. That's the more subtle side, the one for valgrind internal uses. The obvious side is the stuff in coregrind/m_syswrap/priv_syswrap-generic.h and so on, which handles tracking the effects of system calls from emulated user code. |
|
From: Ivo R. <iv...@iv...> - 2014-06-02 18:20:38
|
So after some investigation I would like to continue with this thread. 2014-06-01 4:12 GMT+02:00 John Reiser <jr...@bi...>: > Instead, perform the comparison only when the result can > possibly affect execution, which is at a system call. The dark side here is that execution is affected almost immediately, affecting almost *any* system call, not just few of them. That means not just system calls issued by the client program and intercepted in m_syswrap machinery - also syscalls used internally by valgrind for its housekeeping are affected. So instead of going this murky direction I was thinking whether at least one of the following could be feasible somehow: 1) The control flag "sc_sigblock" is set from just single place in libc. It is a small static function. This means it cannot be intercepted by a simple preload. Nonetheless, valgrind instruments this function before it runs it, like all other code. What would it take to recognize this function as currently instrumented, match the corresponding instruction block against some pattern, and replace the instruction block with something more suitable for our purposes? 2) The control flag is a part of thread control block shared between kernel and libc. Address of this control block is conveyed from kernel to libc as a result of syscall. This means valgrind has the possibility to change this address to whatever it likes. Would it be possible to return some "special" address in the sense that when libc tries to access this address (+ some offset), something happens? I have in mind for example accessing non-mapped page which would result in SIGSEGV being sent to valgrind. Valgrind then does the "right" thing (TM) :-) Now handling SIGSEGV for every access would be probably too heavyweight and I guess fixup from its handling would be too complex. Perhaps there exists another mechanism which I am not aware of? I. |