无法使用GDB找到堆栈粉碎功能

时间:2010-10-26 14:49:07

标签: c gcc gdb

我有以下C应用程序:

#include <stdio.h>

void smash()
{
    int i;
    char buffer[16];
    for(i = 0; i < 17; i++)  // <-- exceeds the limit of the buffer
    {
        buffer[i] = i;
    }
}

int main()
{
    printf("Starting\n");
    smash();
    return 0;
}

我使用以下版本的gcc交叉编译:

armv5l-linux-gnueabi-gcc -v
Using built-in specs.
Target: armv5l-linux-gnueabi
Configured with: /home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/gcc-4.4.1/gcc-4.4.1/configure --target=armv5l-linux-gnueabi --host=i486-linux-gnu --build=i486-linux-gnu --prefix=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain --with-sysroot=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain --with-headers=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain/include --enable-languages=c,c++ --with-gmp=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/gmp-5.0.0/gmp-host-install --with-mpfr=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/mpfr-2.4.2/mpfr-host-install --disable-nls --disable-libgcj --disable-libmudflap --disable-libssp --disable-libgomp --enable-checking=release --with-system-zlib --with-arch=armv5t --with-gnu-as --with-gnu-ld --enable-shared --enable-symvers=gnu --enable-__cxa_atexit --disable-nls --without-fp --enable-threads
Thread model: posix
gcc version 4.4.1 (GCC) 

像这样调用:

armv5l-linux-gnueabi-gcc -ggdb3 -fstack-protector-all -O0 test.c

在目标上运行时,输出:

Starting
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)

我在gdb中加载生成的核心转储,产生以下回溯:

GNU gdb (GDB) 7.0.1
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i486-linux-gnu --target=armv5l-linux-gnueabi".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/andersn/workspace/stacktest/a.out...done.
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6...done.
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain/lib/ld-linux.so.3...done.
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/ld-linux.so.3
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain    /lib/libgcc_s.so.1...done.
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/libgcc_s.so.1
Core was generated by `./a.out'.
Program terminated with signal 6, Aborted.
#0  0x40052d4c in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67
67  ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
    in ../nptl/sysdeps/unix/sysv/linux/raise.c
(gdb) bt
#0  0x40052d4c in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67
#1  0x40054244 in *__GI_abort () at abort.c:92
#2  0x40054244 in *__GI_abort () at abort.c:92
#3  0x40054244 in *__GI_abort () at abort.c:92
#4  0x40054244 in *__GI_abort () at abort.c:92
#5  0x40054244 in *__GI_abort () at abort.c:92
#6  0x40054244 in *__GI_abort () at abort.c:92
... and so on ...

现在,问题是: 即使smash()函数没有覆盖堆栈的任何结构数据,也只是堆栈保护器本身,我完全无法找到导致堆栈从GDB粉碎的函数。我该怎么办?

3 个答案:

答案 0 :(得分:8)

问题是编译目标libc.so.6的GCC版本是错误的,并且没有为__GI_raise发出正确的展开描述符。使用不正确的展开描述符,GDB在展开堆栈时进入循环。

您可以使用

检查展开描述符
readelf -wf /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6

我希望您从任何调用abort的程序中获得与GDB完全相同的结果,例如

#include <stdlib.h>
void foo() { abort(); }
int main() { foo(); return 0; }

不幸的是,除了尝试构建更新版本的GCC,然后用它重建整个“世界”之外,你无能为力。

答案 1 :(得分:2)

即使使用-fstack-protector-all(甚至使用-Wstack-protector来警告带有未受保护的帧的函数),GDB也不能总是弄清楚被破坏的堆栈发生了什么。 Example

在这些情况下,堆栈保护器已经完成了它的工作(杀死了一个行为不端的应用程序),但没有对调试器做任何好处。 (典型的例子是堆栈粉碎,其中写入已经发生了足够大的步幅,它会跳过金丝雀。)在这些情况下,可能需要通过断点二进制搜索代码以缩小代码的哪个区域导致粉碎,然后单步穿过粉碎,看看它是如何发生的。

答案 2 :(得分:0)

您是否尝试过解决此投诉:“../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.”以查看实际上是否能够解析符号会有所帮助?