Search code examples
recursiongdbusabilitystack-overflowinfinite-loop

Better GDB Usability for Call Stack Overflows


Can GDB detect call stack overflows typically in infinite recursion bugs and print some nice error and context message instead of the code given below which is very hard to understand for novices and very inconvenient for all of us. In this case it would be super-cool if GDB could detect which objects (pointers) that were involved in the infinite recursion loop by checking repetitive patterns in the (member-) function- or variable-pointers involved. I'm using gdb-7.3-dev on Ubuntu. Output follows:

Program received signal SIGSEGV, Segmentation fault.
0x008577e9 in _int_malloc (av=0x9483c0, bytes=4) at malloc.c:4249
4249    malloc.c: Filen eller katalogen finns inte.
    in malloc.c
(gdb) up
#1  0x00859f53 in __libc_malloc (bytes=4) at malloc.c:3660
3660    in malloc.c
(gdb) 
#2  0x00788b87 in operator new(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
(gdb) 
#3  0x0809cb7e in __gnu_cxx::new_allocator<Ob*>::allocate (this=0xbf80025c, __n=1)
    at /usr/include/c++/4.6/ext/new_allocator.h:92
92      return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
(gdb) 
#4  0x0809c7c8 in std::_Vector_base<Ob*, std::allocator<Ob*> >::_M_allocate (
    this=0xbf80025c, __n=1) at /usr/include/c++/4.6/bits/stl_vector.h:150
150       { return __n != 0 ? _M_impl.allocate(__n) : 0; }
(gdb) 
#5  0x0809c931 in std::vector<Ob*, std::allocator<Ob*> >::_M_insert_aux<Ob*> (
    this=0xbf80025c, __position=Cannot access memory at address 0x0
) at /usr/include/c++/4.6/bits/vector.tcc:324
324       pointer __new_start(this->_M_allocate(__len));
(gdb) up
#6  0x0809c65a in std::vector<Ob*, std::allocator<Ob*> >::emplace_back<Ob*> (
    this=0xbf80025c, __args#0=@0xbf800190) at /usr/include/c++/4.6/bits/vector.tcc:102
102       _M_insert_aux(end(), std::forward<_Args>(__args)...);
(gdb) 
#7  0x0809c5c4 in std::vector<Ob*, std::allocator<Ob*> >::push_back (this=0xbf80025c, 
    __x=@0xbf800190) at /usr/include/c++/4.6/bits/stl_vector.h:840
840       { emplace_back(std::move(__x)); }
(gdb) 

/Per


Solution

  • Gdb cannot really do this as the stack overflow detection is generally implemented by the compiler. The general way compilers implement this is with canaries. The canary is a value on the stack (the location is between the local variables and the stack frame) that is checked if it got overwritten. The problem with stack overflows is that you end with a damaged stack and the call stack is often not useful. A way around this is to set a watchpoint on the canary location with the br command. So it will break right at the point when the canary is getting overwritten