2010-11-25 129 views
3

我在Linux上使用gdb版本6.8-debian。我一直很好奇c程序中的主函数是如何被执行并且在不同的地方播放和查看的,我知道函数__libc_start_main对此负责。 __libc_start_main的参数是:主要的地址(就像我们从c知道的那样,路径总是以argv [0]给出的),下一个应该存在于寄存器ESI中的argc,以及应该是argv的下一个地址在ECX中。使用gdb访问命令行参数

要玩我做了如下简单的程序,cmdargs.c,它只是在输出开始给出的第一个命令行参数:

#include <stdio.h> 
#include <stdlib.h> 

int main (int argc, char *argv[]) 
{ 
    printf("%s: %s\n", "argv[1]", *++argv); 
    return EXIT_SUCCESS; 
} 

现在我开始调试cmdargs并设置主断点和__libc_start_main(从起始的gdb信息删除):

GDB cmdargs

(gdb) b main 
Breakpoint 1 at 0x80483d2 
(gdb) b __libc_start_main 
Breakpoint 2 at 0xb7f3f5a8 
(gdb) r qwerty 

在这里,我遇到断点2 __libc_start_main,可与

(gdb) p $esi 

(gdb) x/s *($ecx) 

可正常工作查看argc和argv [0],但我如何访问第一个非隐命令行参数“qwerty”?我已经尝试继续到主要的断点处,但是argc和argv不被识别(为什么?)。有人能告诉我发生了什么事吗?

Breakpoint 1, 0x080483d2 in main() 
(gdb) stepi 
0x080483d5 in main() 
(gdb) p argc 
No symbol "argc" in current context. 
(gdb) p argv 
No symbol "argv" in current context. 
(gdb) 

回答

1

输出看起来好像没有足够的调试信息。 GDB不应该只打印地址,而应该打印行号。

(gdb) b main 
Breakpoint 1 at 0x400543: file test.c, line 3. 
(gdb) r test1 test2 
Starting program: /home/simon/a.out test1 test2 

Breakpoint 1, main (argc=3, argv=0x7fffffffdca8) at test.c:3 
3    puts("blabla"); 
(gdb) print argc 
$1 = 3 
(gdb) print argv 
$2 = (char **) 0x7fffffffdca8 
(gdb) print argv[0] 
$3 = 0x7fffffffe120 "/home/simon/a.out" 
(gdb) print argv[1] 
$4 = 0x7fffffffe132 "test1" 
(gdb) print argv[2] 
$5 = 0x7fffffffe138 "test2" 
(gdb) 
1

你应该添加-g选项,GCC,它告诉它来构建调试信息太..

1

是的,你的问题是缺少的符号,不包括在编译的时候。

要使用调试信息编译:

$ gcc -g3 cmdargs.c -o cmdargs 

然后:

$ gdb ./cmdargs 
... 
Reading symbols from ./cmdargs...done. 
(gdb) b main 
Breakpoint 1 at 0x400545: file cmdargs.c, line 6. 
(gdb) r 
Starting program: cmdargs 

Breakpoint 1, main (argc=1, argv=0x7fffffffdc28) at cmdargs.c:6 
6  printf("%s: %s\n", "argv[1]", *++argv); 
(gdb) p argc 
$1 = 1 
(gdb) p argv 
$2 = (char **) 0x7fffffffdc28 
(gdb) p *argv 
$3 = 0x7fffffffe00c "/home/jcgonzalez/cmdargs" 

看,现在你可以访问符号(他们是公认),以及以行号。如Let_Me_Be所示,您可以使用array [n]符号访问单个数组元素,但您也可以使用* array @ times符号一次显示所有命令行参数(包括[0])。请注意,以下示例中的第一个参数是带引号的字符串:

(gdb) set args "this is an argument" these are four more 
(gdb) r 
Starting program: cmdargs "this is an argument" these are four more 

Breakpoint 1, main (argc=6, argv=0x7fffffffdbd8) at cmdargs.c:6 
6  printf("%s: %s\n", "argv[1]", *++argv); 
(gdb) p argc 
$4 = 6 
(gdb) p *[email protected]          
$5 = {0x7fffffffdfe6 "/home/jcgonzalez/cmdargs", 0x7fffffffdfff "this is an argument", 0x7fffffffe012 "these", 0x7fffffffe017 "are", 0x7fffffffe01b "four", 
    0x7fffffffe020 "more"} 
(gdb) p argv[1] 
$6 = 0x7fffffffdfff "this is an argument" 
(gdb) p argv[2] 
$7 = 0x7fffffffe012 "these"