This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Re: uprobes and empty functions
On Wed, 2010-11-03 at 18:09 -0700, Josh Stone wrote:
> On 11/03/2010 04:59 PM, Jim Keniston wrote:
> > I wonder if this is the same problem reported in bugzilla #11249 (which
> > never got resolved, as far as I can tell). In comment #5 there, I
> > speculated as follows:
> >
> > The general protection fault on the call suggests that the destination
> > address
> > of the call is bad. (I think the IP is left at the faulting instruction.) The
> > destination is computed by adding the displacement in the call instruction to
> > the address of the next instruction. If you're in a big vma (e.g.,
> > libc-x.x.so), that displacement can be big. If you move the call instruction to
> > the (1-page) SSOL area, that big displacement can take you out of the SSOL vma,
> > to a potentially unmapped address. Does that warrant a GP fault? Uprobes
> > adjusts the IP after the call, so it's back in the probed vma, but by then it
> > may be too late.
>
> Interesting... the Intel manual has this pseudo-code for near relative:
>
> IF OperandSize = 32
> THEN
> tempEIP <- EIP + DEST; (* DEST is rel32 *)
> IF tempEIP is not within code segment limit THEN #GP(0); FI;
> IF stack not large enough for a 4-byte return address
> THEN #SS(0); FI;
> Push(EIP);
> EIP <- tempEIP;
> FI;
>
> So there's a specified GP if tempEIP is out of range. There's not the
> same check under OperandSize=64, so maybe that's why x86_64 is working
> ok for me. There are other reasons given for GP too, but I'm not sure
> whether any of those could be a side-effect of SSOL.
>
> > Sorry, that's my only idea. It looks interesting, but uprobes and stap
> > are no longer in my bailiwick.
>
> In #11249, you also mention that you have an idea of how to support
> relative calls and jumps -- care to elaborate? Can we just convert them
> to absolute? Or if the SSOL area is close enough, could we just give
> them a new displacement from SSOL to the right target?
I don't actually recall what I had in mind. It was probably, as you
say, something along the lines of altering the instruction that we
single-step.
As I remember, x86_32 doesn't actually have absolute versions of the
near-jump and near-call instructions; what we sometimes call absolute
(or absolute indirect) are really indirect, where the target address is
found in a register or memory location specified by the instruction.
But I think calls and jumps (conditional and unconditional) all have
versions that take 32-bit displacements, so I think that in all cases
you could achieve the desired effect by altering the displacement.
I.e., the SSOL area is always close enough. (In some cases -- e.g.,
opcodes eb and 70-7f -- the instruction takes a 1-byte displacement, so
your substitute instruction would have to be longer than the original;
but that's no big deal because there'd be no post-single-step fixup of
the ip anyway.)
Other possibilities:
For ip-relative calls and unconditional jumps, you could do what we do
with x86_64 rip-relative instructions: convert them to indirect
calls/jumps through a scratch register (which we save before
single-stepping and restore afterward). Conditional jumps are another
matter: they have no indirect versions, just ip-relative. But now that
uprobes has a uprobe_emulate_insn() hook, you could emulate jumps.
>
> I understand you're no longer working in this area, so thanks for your
> input so far! Glad we could keep you interested... ;)
>
> Josh
Jim