使用 gdb 在 LibC 中设置断点
Set a breakpoint into LibC with gdb
为什么我不能在 LibC 的导出函数中设置断点(使用 gdb)?由于是 Libc 动态链接,它必须包含它导出的函数的符号。我不能为这些函数中的任何一个设置断点吗?
我只是想做:
(gdb) b _IO_vfprintf@@GLIBC_2.2.5
Function "_IO_vfprintf@@GLIBC_2.2.5" not defined.
但是查看 ELF 文件中的动态符号 table 该符号确实存在:
127: 0000000000049cf0 20904 FUNC GLOBAL DEFAULT 12 _IO_vfprintf@@GLIBC_2.2.5
我不知道你是怎么想出你正在使用的符号名称的,但这是我在我的系统 (Ubuntu 14.04.1) 上看到的:
$ objdump --dynamic-syms /lib/x86_64-linux-gnu/libc.so.6 |grep vfprintf
0000000000049cf0 g DF .text 00000000000051a8 GLIBC_2.2.5 _IO_vfprintf
00000000001097e0 g DF .text 0000000000000111 GLIBC_2.3.4 __vfprintf_chk
0000000000049cf0 g DF .text 00000000000051a8 GLIBC_2.2.5 vfprintf
这是一个演示程序:
#include <stdio.h>
#include <stdarg.h>
int myprintf( const char *format, ... )
{
va_list ap;
va_start( ap, format );
int result = _IO_vfprintf( stderr, format, ap );
va_end(ap);
return result;
}
int main()
{
myprintf( "hello world! %s %s %s\n", "abc", "def", "ghi" );
myprintf( "goodbye world! %d %d\n", 123, 456 );
return 0;
}
我发现如果我先 运行 main()
, 然后 只用 b _IO_vfprintf
.[=17 设置断点,它的抱怨就会少一些=]
$ make CFLAGS="-Wall -Werror -g" test && ./test
$ objdump --disassemble test |grep vfprintf ## verify call isn't inlined
0000000000400480 <_IO_vfprintf@plt>:
40061e: e8 5d fe ff ff callq 400480 <_IO_vfprintf@plt>
$ gdb --quiet ./test
Reading symbols from ./test...done.
(gdb) b main
Breakpoint 1 at 0x400635: file test.c, line 16.
(gdb) run
Starting program: .../test
Breakpoint 1, main () at test.c:16
16 myprintf( "hello world! %s %s %s\n", "abc", "def", "ghi" );
(gdb) b _IO_vfprintf
Breakpoint 2 at 0x7ffff7a5ecf4
(gdb) cont
Continuing.
Breakpoint 2, 0x00007ffff7a5ecf4 in vfprintf () from /lib/x86_64-linux-gnu/libc.so.6
所以是的,它有效...
更上一层楼 -- 您可以通过应用以下命令单步执行 libc 源...
$ sudo apt-get install libc6-dbg ## get the debug symbols
$ apt-get source libc-dev-bin ## download the source (on Ubuntu or similar)
$ gdb --quiet --directory ./eglibc-2.19/stdio-common ./test
相关注释here.
为什么我不能在 LibC 的导出函数中设置断点(使用 gdb)?由于是 Libc 动态链接,它必须包含它导出的函数的符号。我不能为这些函数中的任何一个设置断点吗?
我只是想做:
(gdb) b _IO_vfprintf@@GLIBC_2.2.5
Function "_IO_vfprintf@@GLIBC_2.2.5" not defined.
但是查看 ELF 文件中的动态符号 table 该符号确实存在:
127: 0000000000049cf0 20904 FUNC GLOBAL DEFAULT 12 _IO_vfprintf@@GLIBC_2.2.5
我不知道你是怎么想出你正在使用的符号名称的,但这是我在我的系统 (Ubuntu 14.04.1) 上看到的:
$ objdump --dynamic-syms /lib/x86_64-linux-gnu/libc.so.6 |grep vfprintf
0000000000049cf0 g DF .text 00000000000051a8 GLIBC_2.2.5 _IO_vfprintf
00000000001097e0 g DF .text 0000000000000111 GLIBC_2.3.4 __vfprintf_chk
0000000000049cf0 g DF .text 00000000000051a8 GLIBC_2.2.5 vfprintf
这是一个演示程序:
#include <stdio.h>
#include <stdarg.h>
int myprintf( const char *format, ... )
{
va_list ap;
va_start( ap, format );
int result = _IO_vfprintf( stderr, format, ap );
va_end(ap);
return result;
}
int main()
{
myprintf( "hello world! %s %s %s\n", "abc", "def", "ghi" );
myprintf( "goodbye world! %d %d\n", 123, 456 );
return 0;
}
我发现如果我先 运行 main()
, 然后 只用 b _IO_vfprintf
.[=17 设置断点,它的抱怨就会少一些=]
$ make CFLAGS="-Wall -Werror -g" test && ./test
$ objdump --disassemble test |grep vfprintf ## verify call isn't inlined
0000000000400480 <_IO_vfprintf@plt>:
40061e: e8 5d fe ff ff callq 400480 <_IO_vfprintf@plt>
$ gdb --quiet ./test
Reading symbols from ./test...done.
(gdb) b main
Breakpoint 1 at 0x400635: file test.c, line 16.
(gdb) run
Starting program: .../test
Breakpoint 1, main () at test.c:16
16 myprintf( "hello world! %s %s %s\n", "abc", "def", "ghi" );
(gdb) b _IO_vfprintf
Breakpoint 2 at 0x7ffff7a5ecf4
(gdb) cont
Continuing.
Breakpoint 2, 0x00007ffff7a5ecf4 in vfprintf () from /lib/x86_64-linux-gnu/libc.so.6
所以是的,它有效...
更上一层楼 -- 您可以通过应用以下命令单步执行 libc 源...
$ sudo apt-get install libc6-dbg ## get the debug symbols
$ apt-get source libc-dev-bin ## download the source (on Ubuntu or similar)
$ gdb --quiet --directory ./eglibc-2.19/stdio-common ./test
相关注释here.