首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不能使用GDB进入string.h .h函数

不能使用GDB进入string.h .h函数
EN

Stack Overflow用户
提问于 2013-03-09 01:23:43
回答 3查看 7.7K关注 0票数 13

在gdb7.5中难以进入string.h。下面是一个简单的示例程序:

源代码:

代码语言:javascript
复制
#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:

代码语言:javascript
复制
(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()。

编辑:

斯科特的建议“奏效了”,但并没有达到预期的效果。

代码语言:javascript
复制
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。并声称没有这样的文件或目录。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-03-09 01:31:22

gcc -fno-builtin -g foo.c重新编译代码,gdb step命令就可以工作了。(见-fno-builtin documentation)。否则,小型strcpy()memcpy()调用通常会被转换成开放编码的数据移动指令,例如在x86-64上:

代码语言:javascript
复制
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将相同的程序编译成:

代码语言:javascript
复制
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的说明(搜索调试器)。

由于您在Ubuntu12.10上,并且实际上希望看到strcpy()程序集源代码:

代码语言:javascript
复制
$ 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. */
票数 18
EN

Stack Overflow用户

发布于 2013-03-09 01:28:10

您尝试为字符串库(通常是standard C library - libc.so的一部分)中定义的函数设置断点。

正如gdb告诉您的那样:

代码语言:javascript
复制
(gdb) break strcpy
Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 2 (strcpy) pending.

图书馆还没有加载。

但真正的问题是,即使在加载库时,如果库(即libc.so )中没有调试符号,则无法使用gdb在库中遍历代码。

您可以启用详细模式来查看哪些符号,gdb能够加载:

代码语言:javascript
复制
(gdb) b main
Breakpoint 1 at 0x400914: file test.cpp, line 7.
(gdb) set verbose on
(gdb) run
Starting program: /home/agururaghave/.scratch/gdb-test/test 
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from system-supplied DSO at 0x7ffff7ffb000...(no debugging symbols found)...done.
Reading symbols from /usr/lib64/libstdc++.so.6...(no debugging symbols found)...done.
Registering libstdc++-v6 pretty-printer for /usr/lib64/libstdc++.so.6 ...
Loaded symbols for /usr/lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6

Breakpoint 1, main () at test.cpp:7
7       bool result = myObj1 < myObj2;

例如,这一行告诉您它是否能够获得libc.so的符号:

代码语言:javascript
复制
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.

然后,您可以找出从使用show debug-file-directory中提取调试符号的位置。

代码语言:javascript
复制
(gdb) show debug-file-directory 
The directory where separate debug symbols are searched for is "/usr/lib/debug".

如您所见,/usr/lib/debug这里不包含带有调试符号的完整.so。相反,它只有调试信息,而没有程序用于执行的实际.text.data部分的任何libc.so部分。

安装库调试信息的解决方案将是发行版特定的。

我认为这个包在基于debian的发行版上被称为libc6-dbg。在我的openSUSE机器上,它似乎被称为glibc-debuginfo

顺便说一下,+1是scottt关于使用-fno-builtin的建议,这样gcc就不会将其内置方法用于strcpy和其他定义为C标准一部分的标准函数。

票数 3
EN

Stack Overflow用户

发布于 2013-03-09 01:26:21

你的C库可能没有任何符号。尝试stepi,但要准备只查看程序集说明。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15306090

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档