|
From: Jeremy F. <je...@go...> - 2005-01-20 01:04:17
|
On Thu, 2005-01-20 at 00:00 +0000, Julian Seward wrote: > Who writes wrap_before_func? That has to understand the baseblock layout > and also the calling conventions to extract esp and retaddr, and so is going > to be machine specific. It's part of the core. It isn't a per-wrapper piece of code, it's a helper (ie, called something like VG_(wrapper_before_helper), and would be a pretty small piece of assembler). The actual wrapper functions are ordinary-looking pieces of C. > That will change drastically .. the new JIT (1) translates multiple BBs > at a time, Well, the BB's we're talking about here are 1) the first BB of a function and 2) the BB at the return address. Under normal circumstances, they're not going to get coalesced with other BBs anyway, I would have thought. But we're going to need a mechanism to inhibit BBs from being coalesced anyway, I think (for debugger support). > and (2) actually doesn't do translation chaining as I could > not think of a clean way to do this portably. You're hoping that coalesced BBs will make up the performance difference? What's the difficulty? It isn't something which could be implemented per-target? > The proposal leaves me with a nasty feeling that it will introduce all > sorts of complex inter-component dependencies and generally be a > maintenance and portability problem later. I actually think its pretty clean that way. By keeping it all on the real CPU rather than in virtual space, we avoid falling into a bunch of ratholes we just escaped from. > I would prefer a solution which didn't involve so much magic in the JIT. Well, there's a little bit of magic in calling a helper for the before wrapper, which doesn't really count. The patching-in of the exit wrapper is a bit tricky, but in the worst case we can always generate a space to patch into. Or regenerate the BBs. > Why do we need general function wrapping? Currently all we care about > is intercepting libpthread calls. Well, that's the immediate concern. But I think there's a lot of other things we could do with wrappers. For example, I think we should consider wrapping client mallocs rather than replacing them outright. We already have the problem that ld.so and glibc each have their own copies of malloc() and friends, and assume that they can operate of each other's pointers. I think we're OK in that case, but its just one instance where being functionally correct requires 100% coverage; with wrapping, we could miss a few cases, and it wouldn't be the end of the world. And Tools like massif don't need a special malloc at all; it only cares about observing the mallocs a program does, with no further checks. > I would prefer to write, in C, a > libpthread stub library, and use the existing intercept mechanism to > route all calls there. The stub library emits events -- using the > client request mechanism -- to those who want to know, and calls onwards > to the real pthread functions (my hands wave here). Right. I thought about that a lot, and it basically comes down to being able to distinguish between an "outside" call to a wrapped function, which needs to be directed to the wrapper, and an "inside" call, which is from the wrapper to the real function, and making that work if the wrapped function is recursive. I can think of a bunch of hacks (look at the callsite, and see if its within the wrapper), but it just seems cleaner to me to keep all this out of the virtual space. And I'm feeling a bit allergic to stub libraries and so on. We're still depending on LD_PRELOAD/LD_LIBRARY path tricks to get that code into the client space, and I'd like to minimize, or even eliminate, that. J |