2013-03-09 55 views
10

難以進入GDB 7.5中的string.h。這裏有一個簡單的例子程序:無法使用GDB進入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。並聲稱沒有這樣的文件或目錄。

+0

@skirkpatrick:這是不對的,至少在大多數系統(OS X,Debian的,Ubuntu的,Fedora的。 ..)。共享庫*使用調試符號編譯。真正的問題是這些符號是否已安裝。 – 2013-03-09 01:33:46

+0

@DietrichEpp:快速搜索後,看起來你是對的。對錯誤信息抱歉;我會刪除我的評論。 – skirkpatrick 2013-03-09 01:38:53

+0

調試符號不是駐留在LD_LIBRARY_PATH中的.so的一部分。相反,它們駐留在gdb所搜索的目錄中,如'/ usr/lib/debug'。這個信息可以通過在'gdb'中運行'show debug-file-directory'獲得。這些文件僅包含調試信息,不包含'.so'的'.text'或'.data'部分。是的,你需要分別安裝它們。 – Tuxdude 2013-03-09 01:49:49

回答

16

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 <[email protected]> 

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 <[email protected]> 

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

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

,你可以看到調用<[email protected]>

假設你想進入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. */ 
+0

't.c'應該表示'foo.c'(在這種情況下),還是我應該鏈接的文件? – d0rmLife 2013-03-09 01:41:18

+0

我試過了。步驟中,但它去到一個意想不到的目錄,並說*沒有這樣的文件或目錄*。我會在我的問題中發佈結果......格式在評論中會很殘酷。 – d0rmLife 2013-03-09 01:50:50

+0

@ d0rmLife:看起來好像strcpy是在glibc的程序集中實現的 – teppic 2013-03-09 01:52:13

0

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

+0

'stepi'也不會進入庫。尋找其他原因... – d0rmLife 2013-03-09 01:32:16

+0

@ d0rmLife,你確定嗎?你是怎麼檢查的? – 2013-03-09 01:33:02

+0

通過運行'GDB'並使用'stepi'。不,我想我並不積極,但似乎沒有。至少,不是以通常的方式...... – d0rmLife 2013-03-09 01:36:30

3

您嘗試設置斷點在字符串庫通常的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部分。

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

我認爲該軟件包在基於debian的發行版中被稱爲libc6-dbg。在我的openSUSE的機器,它好像是叫glibc-debuginfo

BTW,+1使用​​這樣GCC不使用定義的一部分,像strcpy等標準的人功能內置的方法scottt的建議C標準。

+0

libc.so是否有調試信息在這裏不是問題。由於程序是動態鏈接的,如果存在對通過PLT的strcpy()的調用,gdb會捕獲它。這裏的問題是gcc選項'-fno-buitin'沒有被傳遞,並且源中對strcpy()的調用被轉換爲存儲指令。 – scottt 2013-03-09 01:38:54

+0

不知道Ubuntu 12可能需要什麼軟件包? – d0rmLife 2013-03-09 01:40:01

+0

試試'sudo apt-get install libc6-dbg' – Tuxdude 2013-03-09 01:40:44