|
From: Julian S. <js...@ac...> - 2012-02-19 11:11:17
|
> > The places where the PC appears to be wrong: are these exactly the > > first basic blocks of redirected functions (in the sense of the > > functions defined in eg memcheck/mc_replace_strmem.c) ? > > I just reran with --trace-redir=yes and in all cases where the PC > appeared to be wrong it was a redir translation. From that, I'd guess that the reason is that there's a difference between the PC values baked into the PUTs in the IR, and the value of PC in the guest state, for these specific blocks. eg. suppose the program calls libc.so:malloc for the first time. m_redir knows that a replacement exists (vgpreload_memcheck-amd64-linux.so:malloc) and so it directs VEX to translate the entry point of the replacement instead. The translation will have PUT(offs-PC) = some-address-in-vgpreload_memcheck-amd64-linux.so:malloc for its PC update IR fragments. But remember, the program actually called libc.so:malloc, and so the value stored in guest_state->PC at that point (when the translation is made) is the entry point for libc.so:malloc. For this all to make sense, the translation table (managed by m_transtab) contains a binding (&libc.so:malloc -> this translation), so that subsequent calls by the program to libc.so:malloc lead back to this translation. This, I suspect, has much to do with what you observe. Fun, isn't it :-) Some random comments: ----------------- One way to mostly get what you want is to suppress your optimisation just for the first PUT(IP) = ... in the block (iow, make sure the first is always an 8 byte PUT). After that you should be safe. I don't know if you can do this without changing the the generic interface used by guest_bb_to_IR.c to call the guest-specific insn disassemblers. ----------------- Another way to get what you want is to put the cleverness in the back end instead. In the insn selector, keep track (perhaps in the ISelEnv) of which virtual regs have known constants. Then, when you see "PUT(...) = 64-bit constant", see if you can do it with rTemp = (selected vreg) + small constant *(rBaseblock + offs_IP) = rTemp ----------------- Yet another way to do it is to transform the IR in iropt.c, at some suitable place (not sure where), and essentially do the same as above at the IR level. This would also help other targets where constant generation is expensive, particularly ppc64 and to a lesser extent arm. ----------------- Of course the whole concept of updating the guest IP as we run is a ridiculous inefficiency anyway. At least in principle we should be able to use the IRMarks to construct a mapping table that maps host PCs to guest PCs for any host PC. I would long ago have done this but for the (major) complication of how to establish the host PC (and hence the guest PC) when we are in some helper function called from generated code and want to get a (guest) stack trace. Then we have to have a way to get hold of the return value of the helper function (or, more generally of the outermost helper function if we're in some stack of helper calls) in a way which always works and works across all the supported architectures. So far I haven't figured out how. (Suggestions welcomed). J |