|
From: KJK::Hyperion <no...@li...> - 2004-03-05 20:18:24
|
At 01.14 02/03/2004, Jeremy Fitzhardinge wrote:
>Well, the thing which Valgrind ideally wants is two complete address
>spaces: one for the client, and one for Valgrind.
are you 100% sure of what you're saying? if I understand correctly, at
least the JIT compiler needs to run in the same process as the client.
Otherwise we'd have an insane amount of inter-process memory copying, which
doesn't exactly come for free
>The idea is that the Valgrind should be able to control all the activity
>in the client address space, control execution, inject generated code,
>etc. We can't get that with the Unix memory model, but maybe we can use
>the (otherwise very painful) cross-address space features of Windows to
>get this effect.
this sounds like good news, finally. Is there an updated technical
overview? last time I looked, it said Valgrind didn't do multithreading
>Does this mean that if we translate this code into the instrumented code
>cache, then things will care because the EIP isn't within the
>kernel/user/gdi.dll?
no, this shouldn't be a problem, it only hurt full virtualization. The
kernel-mode windowing and graphics code does call back to user-mode, but it
only does so through a well-defined entry point - one of the entry points
Valgrind will have to catch anyway not to lose control
Apropos, some details for the other Windows guys:
- the entry points (exported by ntdll.dll) are:
- KiRaiseUserExceptionDispatcher
- KiUserApcDispatcher
- KiUserCallbackDispatcher
- KiUserExceptionDispatcher
KiUserApcDispatcher will always be hit at least once per thread, as an
APC is queued to all threads to run the initialization code. We won't need
to do special handling of any of them, though. We'll just switch to the JIT
upon entering one of them. The first thread entering the JIT will
initialize it, the others will spin until initialization is done. We could
detect new threads by checking the flat address of their TEB against an
internal table, or by allocating a TLS slot and checking for its value
(NULL -> new thread)
- the entry points above aren't enough. Some control transfers happen
outside of them - luckily there aren't many. I've counted three:
ZwContinue, ZwSetContextThread and ZwVdmControl. The first two are easy,
the third is a mistery. I know it causes control transfers to and from V86
virtual machines, but how does it do that is not known - luckily, only
NTVDM uses it
- catching system calls is a mess. Hooking system calls directly in
kernel mode, as dangerous as it is, is the best way for several reasons. I
don't like how that strace for Windows does it, though. To signal a call
I'd raise an exception: it's semantically correct, so it will work well
with existing (and future) code
>Also, is this code running in Ring 3, or a privileged level?
in normal processes, all code runs at ring 3. Well, winsrv.dll (in the
CSRSS process) has a couple of functions (in user-mode memory) that run in
kernel-mode, in kernel-mode threads created by win32k.sys, but it's the
only instance I know of. Well, the PsCreateSystemThread function *is*
documented in the driver writing documentation, and it *could* be used to
create kernel-mode threads in any process, but I'd be surprised if anyone
used it on a process that isn't System. And even in that case it isn't
something Valgrind can possibly control, and it won't be commonplace
|