簡體   English   中英

無法通過GDB進入string.h函數

[英]Can't step into string.h function with 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()。


編輯:

斯科特的建議“奏效”,但未達到預期的效果。

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文檔 )。 否則,小的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. */

您試圖為字符串庫中定義的函數設置斷點,該函數通常是standard C library - libc.so一部分standard C library - libc.so

正如gdb通知您的那樣:

(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可以加載哪些符號:

(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的符號:

Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.

然后,您可以使用show debug-file-directory找出從哪里提取調試符號:

(gdb) show debug-file-directory 
The directory where separate debug symbols are searched for is "/usr/lib/debug".

如您所見/usr/lib/debug此處不包含帶有調試符號的完整.so。 相反,它僅具有調試信息,而沒有程序實際用於執行的libc.so的任何.text.data節。

為庫安裝調試信息的解決方案將特定於發行版。

我認為該libc6-dbg在基於debian的發行版上稱為libc6-dbg 在我的openSUSE機器上,它似乎叫做glibc-debuginfo

順便說一句,在scottt建議使用-fno-builtin的建議上,+ 1,這樣gcc不會將其內置方法用於諸如strcpy函數以及定義為C標准一部分的其他標准函數。

您的C庫可能沒有任何符號。 嘗試stepi ,但准備僅查看組裝說明。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM