[webkit-dev] JSCore GDB Integration

Filip Pizlo fpizlo at apple.com
Sat Dec 24 13:43:40 PST 2011


> Hi all!
> 
> I've been trying to add GDB support to JavaScriptCore; basically
> giving GDB the ability to understand code emitted by the JIT.  This is
> easier now, due to a GDB extension I worked on some time back [1].  I
> have some of it working, and using a jit-reader plugin (again, see
> [1]), it is possible to have GDB display stack traces like the
> following (checkTermination and recurse are JS functions):

This is cool!

> However, I'm having some trouble getting GDB to unwind from the JITted
> code into code belonging to the JSCore image.  I suspect this is
> because ctiTrampoline does not have debug information.  I tried adding
> .cfi directives to the assembly for ctiTrampoline, but that does not
> seem to work (I'm yet to figure out why).

That's strange; I'd have expected something like this to work. :-(  Could it have something to do with it being a hidden symbol, or does that not matter for you?

> In fact, a much easier
> solution would be to re-use the jit-reader plugin itself to unwind
> through ctiTrampoline.  That can be done easily if I can somehow get
> hold of the size (equivalently the PC bounds) for ctiTrampoline.

Why not add a ctiTrampolineEnd label at the end of the ctiTrampoline?  Like:

asm (
".text\n"
".globl " SYMBOL_STRING(ctiTrampoline) "\n"
HIDE_SYMBOL(ctiTrampoline) "\n"
SYMBOL_STRING(ctiTrampoline) ":" "\n"
    "pushl %ebp" "\n"
    ... // same stuff as is there now
    "ret" "\n"
".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
HIDE_SYMBOL(ctiTrampolineEnd) "\n"
SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
);

Then you know where it starts and where it ends.

> One
> way could be to pad the end of ctiTrampoline with two nops and search
> for that pattern in the byte-stream.  But that sounds quite brittle to
> me, to be frank.

If you really needed to do that, I'd suggest the following sequence:

xorl $<some random 32-bit number>, %eax
xorl $<another random 32-bit number>, %eax
xorl $<and another one>, %eax
xorl $<and one more>, %eax

Where the random numbers are statically chosen and baked into the code in JITStubs.cpp.  That'll give you 128 bits of randomness of your choosing, which should be plenty unique.  You could go nuts with more such instructions, with more random 32-bit immediates.  But probably already 128 bits is plenty.

I only suggest using xorl because it's not the world's most common instruction, which is effectively giving you another couple of bits of uniqueness.

> Is there some other. more robust way to do the same
> thing?  Or, perhaps some standard way to completely skip the
> ctiTrampoline frame altogether?

Depends on what you mean by "completely skip".  As you seem to suggest below, if you know that you're at the trampoline frame then you can skip it by virtue of knowing what it does.

> This will also be perfectly doable if
> I can somehow, by looking at registers and examining some memory,
> figure out that a particular frame is the earliest JS frame in the call
> stack.

If you're traversing the JSC CallFrames, the earliest one will have ReturnPC = 0 and CallerFrame = HostCallFrameFlag (i.e. 1).

Hope this helps!

-Filip




More information about the webkit-dev mailing list