public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* GDB Frame Filter - handling corrupt stack
@ 2014-09-09 12:26 Simeon S
  2014-09-09 15:48 ` Phil Muldoon
  0 siblings, 1 reply; 3+ messages in thread
From: Simeon S @ 2014-09-09 12:26 UTC (permalink / raw)
  To: gdb

Hi all,

I am trying to decorate the output of "backtrace" command. I have
written a simple gdb Frame Filter coupled with a Frame Decorator. I
have followed the official documentation tutorial
(https://sourceware.org/gdb/current/onlinedocs/gdb/Writing-a-Frame-Filter.html#Writing-a-Frame-Filter).
My gdb is compiled against Python 3.3.2 and my code looks like this:



    import gdb
    import itertools
    from gdb.FrameDecorator import FrameDecorator
    import copy

    class UpperCase_Decorator (FrameDecorator):
        def __init__(self, fobj):
            super(UpperCase_Decorator, self).__init__(fobj)
            self.fobj = fobj

        def function(self):
            frame = self.fobj.inferior_frame()

            if not frame.is_valid():
                return ""

            name = str(frame.name()).upper()
            return name


    class InlineFilter():
        def __init__(self):
            self.name = "InlinedFrameFilter"
            self.priority = 100
            self.enabled = True
            gdb.frame_filters[self.name] = self

        def filter(self, frame_iter):
            frame_iter = map(UpperCase_Decorator,
                             frame_iter)
            print(type(frame_iter))
            return frame_iter

    ff = InlineFilter()



When the gdb "backtrace" command is issued, frames are decorated
followed by a gdb crash. This is what the last output from gdb is:

    UNIX ERR:tcsetattr:Input/output error
    Segmentation fault (core dumped)

The stack seems to be corrupt which is what I suspect is causing the
crash. If the frame filter is disabled, the last line of the
"backtrace" command is:

    Backtrace stopped: previous frame inner to this frame (corrupt stack?)

I haven't looked into why the stack is corrupt - all the frames of
interest to me are there.  Is there a way to catch this condition to
avoid crashing? I am not interested in any of the corrupt frames -
what is in the stack is enough.

I guess I am looking for a mechanism to stop gdb iterating over
further frames if it detects a corrupt/invalid frame.  The
documentation does say that gdb has to iterate over all stack frames
though.

Regards,
Simeon

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: GDB Frame Filter - handling corrupt stack
  2014-09-09 12:26 GDB Frame Filter - handling corrupt stack Simeon S
@ 2014-09-09 15:48 ` Phil Muldoon
  2014-09-09 21:37   ` Simeon S
  0 siblings, 1 reply; 3+ messages in thread
From: Phil Muldoon @ 2014-09-09 15:48 UTC (permalink / raw)
  To: Simeon S, gdb

On 09/09/14 13:26, Simeon S wrote:


It's a fairly simple filter, so I don't see much wrong with that.
 
>
> When the gdb "backtrace" command is issued, frames are decorated
> followed by a gdb crash. This is what the last output from gdb is:
>
>     UNIX ERR:tcsetattr:Input/output error
>     Segmentation fault (core dumped)

I'd love to see a backtrace of this.  It is not related to your issue,
but it is a bug in the frame filters.  It should print the error
message below:

> The stack seems to be corrupt which is what I suspect is causing the
> crash. If the frame filter is disabled, the last line of the
> "backtrace" command is:
>
>     Backtrace stopped: previous frame inner to this frame (corrupt stack?)

Yeah at this point the stack looks clobbered, or some kind of bug
internal to GDB has occurred.

> I haven't looked into why the stack is corrupt - all the frames of
> interest to me are there.  Is there a way to catch this condition to
> avoid crashing? I am not interested in any of the corrupt frames -
> what is in the stack is enough.

No not really.  Someone else may have an idea.

> I guess I am looking for a mechanism to stop gdb iterating over
> further frames if it detects a corrupt/invalid frame.  The
> documentation does say that gdb has to iterate over all stack frames
> though.

Even though the documentation does indeed say that, you can always
slice/trim the iterator that is handed to the frame filter and return
the sliced iterator.  The trick is finding which frame would be the
corrupted one and slicing appropriately.  See the itertools Python
module for iterator tools (including slicing).

Cheers

Phil


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: GDB Frame Filter - handling corrupt stack
  2014-09-09 15:48 ` Phil Muldoon
@ 2014-09-09 21:37   ` Simeon S
  0 siblings, 0 replies; 3+ messages in thread
From: Simeon S @ 2014-09-09 21:37 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: gdb

Hi Phil,

Thanks for the response. I've been able to reproduce this issue with
just the following python code which just returns the iterator
untouched:


    import gdb

    class InlineFilter():
        def __init__(self):
            self.name = "InlinedFrameFilter"
            self.priority = 100
            self.enabled = True
            gdb.frame_filters[self.name] = self

        def filter(self, frame_iter):
            return frame_iter

    ff = InlineFilter()


When my program is loaded, it creates a new thread and does a longjmp
so I suspect gdb will not be able to see the stack before the jump
(but this part of the stack is of no interest). The corrupt stack when
debugging my program is probably not something gdb can handle and in
general doesn't cause much problems...until today that is. Anyway, my
first thought was that this is a bug in gdb - a corner case. It would
be a good idea if gdb handles this rare case gracefully - print a
message and continue with the debug session.


I've done a bit of debugging and below is my short debug session. I
have gdb 7.8 as the inferior of gdb 7.8 which has my program as its
inferior (gdb-----|gdb------|prog). When the inferior gdb crashes, the
following backtrace is shown:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x00000000005b0b86 in do_my_cleanups (pmy_chain=0xd0ede0
<cleanup_chain>, old_chain=0x74261b0) at cleanups.c:155
#2  0x0000000000530a64 in py_print_args (filter=0x7ffff0ed6978,
out=0x14aa3d0, args_type=CLI_SCALAR_VALUES, frame=0x902b800) at
./python/py-framefilter.c:987
#3  0x0000000000531226 in py_print_frame (filter=0x7ffff0ed6978,
flags=7, args_type=CLI_SCALAR_VALUES, out=0x14aa3d0, indent=0,
levels_printed=0x41a7440) at ./python/py-framefilter.c:1236
#4  0x0000000000531a54 in gdbpy_apply_frame_filter (extlang=0x8ba080
<extension_language_python>, frame=0xe01a40, flags=7,
args_type=CLI_SCALAR_VALUES, out=0x14aa3d0, frame_low=0,
frame_high=-1) at ./python/py-framefilter.c:1534
#5  0x0000000000624428 in apply_ext_lang_frame_filter (frame=0xe01a40,
flags=7, args_type=CLI_SCALAR_VALUES, out=0x14aa3d0, frame_low=0,
frame_high=-1) at extension.c:553
#6  0x000000000061e3de in backtrace_command_1 (count_exp=0x0,
show_locals=0, no_filters=0, from_tty=1) at stack.c:1801
#7  0x000000000061e82b in backtrace_command (arg=0x0, from_tty=1) at
stack.c:1916
#8  0x00000000004fbf43 in do_cfunc (c=0xdedbf0, args=0x0, from_tty=1)
at ./cli/cli-decode.c:107
#9  0x00000000004feec5 in cmd_func (cmd=0xdedbf0, args=0x0,
from_tty=1) at ./cli/cli-decode.c:1886
#10 0x000000000072fba0 in execute_command (p=0xd451c2 "", from_tty=1)
at top.c:462
#11 0x0000000000630ab0 in command_handler (command=0xd451c0 "bt") at
event-top.c:433
#12 0x0000000000631063 in command_line_handler (rl=0x7e3a690 "") at
event-top.c:630
#13 0x0000000000791c12 in rl_callback_read_char () at callback.c:220
#14 0x00000000006305ec in rl_callback_read_char_wrapper
(client_data=0x0) at event-top.c:167
#15 0x00000000006309c2 in stdin_event_handler (error=0,
client_data=0x0) at event-top.c:373
#16 0x000000000062f5b7 in handle_file_event (data=...) at event-loop.c:766
#17 0x000000000062ea8c in process_event () at event-loop.c:343
#18 0x000000000062eb53 in gdb_do_one_event () at event-loop.c:407
#19 0x000000000062eba3 in start_event_loop () at event-loop.c:432
#20 0x000000000063061e in cli_command_loop (data=0x0) at event-top.c:182
#21 0x0000000000626961 in current_interp_command_loop () at interps.c:328
#22 0x0000000000627b0e in captured_command_loop (data=0x0) at main.c:302
#23 0x0000000000623811 in catch_errors (func=0x627af3
<captured_command_loop>, func_args=0x0, errstring=0x91759b "",
mask=RETURN_MASK_ALL) at exceptions.c:506
#24 0x0000000000629054 in captured_main (data=0x7fffffffe7d0) at main.c:1155
#25 0x0000000000623811 in catch_errors (func=0x627ee8 <captured_main>,
func_args=0x7fffffffe7d0, errstring=0x91759b "", mask=RETURN_MASK_ALL)
at exceptions.c:506
#26 0x000000000062907d in gdb_main (args=0x7fffffffe7d0) at main.c:1163
#27 0x0000000000462d3d in main (argc=1, argv=0x7fffffffe8d8) at gdb.c:33
(gdb) frame 1
#1  0x00000000005b0b86 in do_my_cleanups (pmy_chain=0xd0ede0
<cleanup_chain>, old_chain=0x74261b0) at cleanups.c:155
155          (*ptr->function) (ptr->arg);
(gdb) list
150      struct cleanup *ptr;
151
152      while ((ptr = *pmy_chain) != old_chain)
153        {
154          *pmy_chain = ptr->next;    /* Do this first in case of
recursion.  */
155          (*ptr->function) (ptr->arg);
156          if (ptr->free_arg)
157        (*ptr->free_arg) (ptr->arg);
158          xfree (ptr);
159        }
(gdb) info locals
ptr = 0x8f8960 <sentinel_cleanup>
(gdb) p *pmy_chain
$1 = (struct cleanup *) 0x0
(gdb) p *ptr
$2 = {next = 0x0, function = 0x0, free_arg = 0x0, arg = 0x0}
(gdb) p old_chain
$3 = (struct cleanup *) 0x74261b0
(gdb) p *old_chain
$4 = {next = 0x6adca20, function = 0x76dbce <xfree>, free_arg = 0x0,
arg = 0x9c47f00}
(gdb)


Let me know what you need here - I can provide support.

Simeon

On 9 September 2014 16:48, Phil Muldoon <pmuldoon@redhat.com> wrote:
> On 09/09/14 13:26, Simeon S wrote:
>
>
> It's a fairly simple filter, so I don't see much wrong with that.
>
>>
>> When the gdb "backtrace" command is issued, frames are decorated
>> followed by a gdb crash. This is what the last output from gdb is:
>>
>>     UNIX ERR:tcsetattr:Input/output error
>>     Segmentation fault (core dumped)
>
> I'd love to see a backtrace of this.  It is not related to your issue,
> but it is a bug in the frame filters.  It should print the error
> message below:
>
>> The stack seems to be corrupt which is what I suspect is causing the
>> crash. If the frame filter is disabled, the last line of the
>> "backtrace" command is:
>>
>>     Backtrace stopped: previous frame inner to this frame (corrupt stack?)
>
> Yeah at this point the stack looks clobbered, or some kind of bug
> internal to GDB has occurred.
>
>> I haven't looked into why the stack is corrupt - all the frames of
>> interest to me are there.  Is there a way to catch this condition to
>> avoid crashing? I am not interested in any of the corrupt frames -
>> what is in the stack is enough.
>
> No not really.  Someone else may have an idea.
>
>> I guess I am looking for a mechanism to stop gdb iterating over
>> further frames if it detects a corrupt/invalid frame.  The
>> documentation does say that gdb has to iterate over all stack frames
>> though.
>
> Even though the documentation does indeed say that, you can always
> slice/trim the iterator that is handed to the frame filter and return
> the sliced iterator.  The trick is finding which frame would be the
> corrupted one and slicing appropriately.  See the itertools Python
> module for iterator tools (including slicing).
>
> Cheers
>
> Phil
>
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-09-09 21:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-09 12:26 GDB Frame Filter - handling corrupt stack Simeon S
2014-09-09 15:48 ` Phil Muldoon
2014-09-09 21:37   ` Simeon S

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).