【问题标题】:accessing command-line arguments with gdb使用 gdb 访问命令行参数
【发布时间】:2011-05-15 18:09:48
【问题描述】:

我在 linux 上使用 gdb 版本 6.8-debian。我一直很好奇 c 程序中的 main 函数是如何执行的,如何在不同的地方玩耍和寻找,我了解到函数 __libc_start_main 对此负责。 __libc_start_main 的参数包括:main 的地址(就像我们从 c 中知道的那样,路径总是以 argv[0] 形式给出),应该驻留在寄存器 ESI 中的下一个 argc,以及应该是 argv 的下一个地址在 ECX 中。

为了玩耍,我制作了以下简单的程序 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 并在 main 和 __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

这里我在 __libc_start_main 中的断点 2 可以查看 argc 和 argv[0]

(gdb) p $esi

(gdb) x/s *($ecx)

这按预期工作,但我如何访问第一个非隐式命令行参数“qwerty”?我尝试在 main 处继续断点并介入,但无法识别 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) 

【问题讨论】:

    标签: c assembly gdb


    【解决方案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]-ed 之一)。请注意,以下示例中的第一个参数是带引号的字符串:

    (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 *argv@argc                                    
    $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"
    

    【讨论】:

      【解决方案2】:

      输出看起来好像您没有足够的调试信息。 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)
      

      【讨论】:

        【解决方案3】:

        你应该将 -g 选项添加到 gcc,它告诉它也构建调试信息..

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-19
          • 2012-09-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多