无法使用 GDB 进入 string.h 函数

标签 c gdb

在 GDB 7.5 中单步执行 string.h 时遇到问题。这是一个简单的示例程序:

源代码:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[20];
    strcpy(str1, "STEP INTO ME\n");
    printf(str1);
}

编译: ~$ gcc -g foo.c

调用: ~$ gdb -q ./a.out

GDB:

(gdb) break 5
Breakpoint 1 at 0x8048471: file foo.c, line 6.
(gdb) break strcpy
Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 2 (strcpy) pending.
(gdb) run 
Starting program: /home/user/a.out 

Breakpoint 1, main () at foo.c:6
6               strcpy(str_a, "Hello, world!\n");
(gdb) step
7               printf(str_a);

此时我不应该在字符串库中吗?相反,它会继续执行 printf()。


编辑:

Scott 的建议“奏效了”,但没有以预期的方式出现。

Breakpoint 1, main () at foo.c:6
6               strcpy(str_a, "Hello, world!\n");
(gdb) i r $eip
eip            0x80484a1        0x80484a1 <main+21>
(gdb) step

Breakpoint 2, __strcpy_ssse3 () at ../sysdeps/i386/i686/multiarch/strcpy-ssse3.S:78
78      ../sysdeps/i386/i686/multiarch/strcpy-ssse3.S: No such file or directory.
(gdb) i r $eip
eip            0xb7e9c820       0xb7e9c820 <__strcpy_ssse3> 

我对 78 中的目录感到惊讶...预期是这样的:/lib/.../cmov/libc.so.6。并声称不存在这样的文件或目录。

最佳答案

使用 gcc -fno-builtin -g foo.c 重新编译您的代码和 gdb step命令将起作用。 (参见 -fno-builtin documentation)。否则小strcpy() , memcpy()调用通常会被翻译成开放编码的数据移动指令,例如在 x86-64 上:

4   int main() {
   0x000000000040052c <+0>: push   %rbp
   0x000000000040052d <+1>: mov    %rsp,%rbp
   0x0000000000400530 <+4>: sub    $0x20,%rsp

5       char str1[20];
6       strcpy(str1, "STEP INTO ME\n");
   0x0000000000400534 <+8>: lea    -0x20(%rbp),%rax
   0x0000000000400538 <+12>:    movl   $0x50455453,(%rax)
   0x000000000040053e <+18>:    movl   $0x544e4920,0x4(%rax)
   0x0000000000400545 <+25>:    movl   $0x454d204f,0x8(%rax)
   0x000000000040054c <+32>:    movw   $0xa,0xc(%rax)

7       printf(str1);
   0x0000000000400552 <+38>:    lea    -0x20(%rbp),%rax
   0x0000000000400556 <+42>:    mov    %rax,%rdi
   0x0000000000400559 <+45>:    mov    $0x0,%eax
   0x000000000040055e <+50>:    callq  0x400410 <printf@plt>

8   }
   0x0000000000400563 <+55>:    leaveq 
   0x0000000000400564 <+56>:    retq

你可以看到 strpcy()调用被编译成多个 MOV 指令。

gcc -fno-builtin将相同的程序编译成:

4   int main() {
   0x000000000040057c <+0>: push   %rbp
   0x000000000040057d <+1>: mov    %rsp,%rbp
   0x0000000000400580 <+4>: sub    $0x20,%rsp

5       char str1[20];
6       strcpy(str1, "STEP INTO ME\n");
   0x0000000000400584 <+8>: lea    -0x20(%rbp),%rax
   0x0000000000400588 <+12>:    mov    $0x400660,%esi
   0x000000000040058d <+17>:    mov    %rax,%rdi
   0x0000000000400590 <+20>:    callq  0x400450 <strcpy@plt>

7       printf(str1);
   0x0000000000400595 <+25>:    lea    -0x20(%rbp),%rax
   0x0000000000400599 <+29>:    mov    %rax,%rdi
   0x000000000040059c <+32>:    mov    $0x0,%eax
   0x00000000004005a1 <+37>:    callq  0x400460 <printf@plt>

8   }
   0x00000000004005a6 <+42>:    leaveq 
   0x00000000004005a7 <+43>:    retq 

您可以看到对 <strcpy@plt> 的调用.

假设您想进入 strcpy()要研究它的实现,您需要安装 libc.so 的调试信息。不幸的是,获取调试信息的方式因 Linux 发行版而异。在 Fedora 上它就像 debuginfo-install glibc 一样简单.它在 Ubuntu 和 Debian 上需要更多步骤。这RPM DPKG Rosetta Stone页面有指向 Fedora、Ubuntu 和 Debian 说明的链接(搜索 debuginfo)。

由于您使用的是 Ubuntu 12.10 并且实际上想要查看 strcpy()汇编源代码:

$ sudo apt-get install libc6-dbg
$ sudo apt-get source libc6-dev
$ gdb ./a.out
(gdb) directory eglibc-2.15/sysdeps
Source directories searched: /home/scottt/eglibc-2.15/sysdeps:$cdir:$cwd
(gdb) break strcpy
Breakpoint 1 at 0x400450
(gdb) run
Starting program: /home/scottt/a.out 

Breakpoint 1, __strcpy_sse2 () at ../sysdeps/x86_64/multiarch/../strcpy.S:32
32      movq %rsi, %rcx     /* Source register. */

关于无法使用 GDB 进入 string.h 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15306090/

相关文章:

c - 我的代码中全局变量的值如何变化?

c - 如何正确地字节移位一大块数据?

c - 在不按回车键的情况下读入命令提示符输入

c - __strcpy_sse2_unaligned 与 -fno-builtin

c++ - 我使用 gdb 跟踪 'catch' 和 'syscall' 失败,它报告找不到 'brk'?

c++ - 如何使用 gdb 达到与使用可视化调试器相同的效率水平?

c: 不允许使用类型名称

c - 如何解决 MISRA C :2012 error regarding to memcpy function?

linux - GDB远程调试: can't stop the thread

c++ - 如何取消引用和打印指针数组的每个元素?