This is the mail archive of the mailing list for the GDB project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Frame sniffers in Python/Guile/*

Hi Andy,

On 03/02/2015 01:28 PM, Andy Wingo wrote:

> (Why a new object type?  Because all <gdb:frame> objects have a
> frame_id, and this one does not, and it turns out it's a deep invariant
> that frames have identifiers.)


> The list of unwinders is run in order over the ephemeral frame, and the
> first one that calls (set-ephemeral-frame-id! frame sp [ip [special]])
> on the frame takes responsibility of unwinding the frame.  You can read
> registers with ephemeral-frame-read-register, and set their unwound
> values with ephemeral-frame-write-register!.  Simple stuff, and I'll
> post later once I get the V8 unwinder working.
> Unfortunately, the unwind callback is really squirrely -- you can't do
> much there.

You mean the "unwind->sniffer" callback, right?  If so, that's (so far) by
design.  The sniffer callback is only supposed to identify whether
the unwinder can unwind, not do any unwinding at all.  :-/

See here for example:

>   * You can't call the Guile lookup-symbol function within an unwind
>     handler, because the Guile wrapper wants to default the "block"
>     argument from the selected frame, and there is no selected frame.

There can certainly be a selected frame already when something tries
to unwind past the most-unwound-already frame.  That will
be the normal case of "up" past the innermost frame, even.  But
imagine the case of:

  #0 frame0  <<<< current
  #1 frame1  <<<< selected
  #2 frame2

And the user has frame 1 selected.  And now the user runs some guile or
python code that does frame-older a couple times, which results in GDB
trying to unwind past frame #2.

So what context does make sense for symbol look ups at that point?
With your current hack, because there's a selected frame (frame #1),
symbols will be looked up starting from there.  But it seems to me
that whatever was the selected frame shouldn't influence the sniffer's
decisions.  Isn't the correct answer that the sniffer should
pass in an explicit block to lookup-symbol?

>   * You can't value-call, which is not unexpected in general, but the
>     reason is unexpected: because call_function_by_hand calls
>     get_current_arch and that doesn't work

Where is that?  I think you meant that the guile wrapper calls
get_current_arch, not call_function_by_hand.

>   * You can't call get_current_arch, directly or indirectly, because it
>     causes unbounded recursion:
>       #3  0x00000000006a65f2 in frame_unwind_try_unwinder (this_frame=this_frame@entry=0x5f6af10, this_cache=this_cache@entry=0x5f6af28, unwinder=0x409fe30) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame-unwind.c:126
>       #4  0x00000000006a696f in frame_unwind_find_by_frame (this_frame=this_frame@entry=0x5f6af10, this_cache=this_cache@entry=0x5f6af28) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame-unwind.c:157
>       #5  0x00000000006a32cb in get_prev_frame_if_no_cycle (fi=0x5f6af10) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:454
>       #6  0x00000000006a32cb in get_prev_frame_if_no_cycle (this_frame=this_frame@entry=0x5f6ae40) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1780
>       #7  0x00000000006a53a9 in get_prev_frame_always (this_frame=0x5f6ae40) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1954
>       #8  0x00000000006a53a9 in get_prev_frame_always (this_frame=this_frame@entry=0x5f6ae40) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1971
>       #9  0x00000000006a5ab1 in get_prev_frame (this_frame=this_frame@entry=0x5f6ae40) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:2212
>       #10 0x00000000006a5d8c in unwind_to_current_frame (ui_out=<optimized out>, args=args@entry=0x5f6ae40) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1447
>       #11 0x00000000005cf63c in catch_exceptions_with_msg (func_uiout=<optimized out>, func=func@entry=0x6a5d80 <unwind_to_current_frame>, func_args=func_args@entry=0x5f6ae40, gdberrmsg=gdberrmsg@entry=0x0, mask=mask@entry=RETURN_MASK_ERROR)
>           at /home/wingo/src/binutils-gdb/+2.2/../gdb/exceptions.c:189
>       #12 0x00000000005cf75a in catch_exceptions (uiout=<optimized out>, func=func@entry=0x6a5d80 <unwind_to_current_frame>, func_args=func_args@entry=0x5f6ae40, mask=mask@entry=RETURN_MASK_ERROR) at /home/wingo/src/binutils-gdb/+2.2/../gdb/exceptions.c:169
>       #13 0x00000000006a33e0 in get_current_frame () at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1486
>       #14 0x00000000006a3fe7 in get_selected_frame (message=message@entry=0x0) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1541
>       #15 0x00000000005e7a27 in get_current_arch () at /home/wingo/src/binutils-gdb/+2.2/../gdb/arch-utils.c:784
>     Perhaps this is only the case for the most inner frame?  Anyway this
>     is the reason that many other things fail.
>   * You can't read user regs from an ephemeral frame for some reason:
>       /home/wingo/src/binutils-gdb/+2.2/../gdb/regcache.c:779: internal-error: regcache_cooked_read_value: Assertion `regnum < regcache->descr->nr_cooked_registers' failed.
>       #9  0x00000000005732b5 in regcache_cooked_read_value (regcache=0xd25cc0, regnum=221) at /home/wingo/src/binutils-gdb/+2.2/../gdb/regcache.c:779
>       #10 0x0000000000684c28 in sentinel_frame_prev_register (this_frame=0x6c7c350, this_prologue_cache=<optimized out>, regnum=<optimized out>) at /home/wingo/src/binutils-gdb/+2.2/../gdb/sentinel-frame.c:52
>       #11 0x00000000006a4408 in frame_unwind_register_value (frame=0x6c7c350, regnum=221) at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1111
>       #12 0x00000000006a468f in frame_register_unwind (frame=<optimized out>, regnum=<optimized out>, optimizedp=0x7fffffffcde8, unavailablep=0x7fffffffcdec, lvalp=0x7fffffffcdf0, addrp=0x7fffffffcdf8, realnump=0x7fffffffcdf4, bufferp=0x7fffffffce40 "l\305\001\367\377\177") at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1016
>       #13 0x00000000006a4892 in frame_register (frame=<optimized out>, regnum=<optimized out>, optimizedp=<optimized out>, unavailablep=<optimized out>, lvalp=<optimized out>, addrp=<optimized out>, realnump=<optimized out>, bufferp=<optimized out>)
>           at /home/wingo/src/binutils-gdb/+2.2/../gdb/frame.c:1057

Why would the unwinder want to access user / pseudo registers?
Shouldn't it be working only with raw registers?

> And so on.  From what I can tell, all of this is because there is no
> selected frame.  I recognize that this situation reflects reality in
> some way -- we're still building the selected frame -- but is there any
> way that we could have GDB be in a more "normal" state while the unwind
> callback is running?

Pedro Alves

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]