2013-03-09 24 views
10

Có rắc rối bước vào string.h trong GDB 7.5. Dưới đây là một ví dụ đơn giản chương trình: MãKhông thể bước vào chức năng string.h với GDB

Nguồn:

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

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

Biên soạn:~$ gcc -g foo.c

Được triệu gọi:~$ 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); 

nên tôi không có trong thư viện string vào thời điểm này? Thay vào đó nó tiếp tục với printf().


EDIT:

gợi ý của Scott "làm việc", nhưng không phải theo cách thức dự kiến.

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> 

Tôi ngạc nhiên tại thư mục ở 78 ... mong đợi điều gì đó như: /lib/.../cmov/libc.so.6. Và tuyên bố rằng không có tệp hoặc thư mục như vậy.

+0

@skirkpatrick: Đây là sai, ít nhất là trên hầu hết các hệ thống (OS X, Debian, Ubuntu, Fedora. ..). Thư viện được chia sẻ * được biên dịch với các biểu tượng gỡ lỗi. Câu hỏi thực sự là liệu các biểu tượng đó có được cài đặt hay không. –

+0

@DietrichEpp: Sau khi tìm kiếm nhanh, có vẻ như bạn đã đúng. Xin lỗi vì thông tin sai lạc; Tôi sẽ xóa nhận xét của tôi. – skirkpatrick

+0

Các biểu tượng gỡ lỗi không phải là một phần của .so nằm trong LD_LIBRARY_PATH của bạn. Thay vào đó chúng nằm trong một thư mục mà gdb tìm kiếm như '/ usr/lib/debug'. Thông tin này có thể thu được bằng cách chạy 'show debug-file-directory' trong' gdb'. Các tệp này chỉ chứa thông tin gỡ lỗi mà không có bất kỳ phần '.text' hoặc' .data' nào của '.so'. Và có bạn cần phải cài đặt chúng một cách riêng biệt. – Tuxdude

Trả lời

16

Biên dịch lại mã của bạn bằng gcc -fno-builtin -g foo.c và lệnh gdb step sẽ hoạt động. (Xem -fno-builtin documentation). Nếu không, các cuộc gọi strcpy(), memcpy() thường sẽ được dịch sang hướng dẫn di chuyển dữ liệu được mã hóa mở, ví dụ: trên 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 

Bạn có thể xem strpcy() gọi được biên soạn thành nhiều MOV hướng dẫn.

gcc -fno-builtin biên dịch cùng một chương trình thành:

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 

và bạn sẽ nhìn thấy cuộc gọi đến <[email protected]>.

Giả sử bạn muốn bước vào strcpy() để nghiên cứu triển khai, bạn muốn có thông tin gỡ lỗi cho libc.so được cài đặt. Thật không may là cách để có được thông tin gỡ lỗi khác nhau giữa các bản phân phối Linux. Trên Fedora nó đơn giản như debuginfo-install glibc. Phải mất nhiều bước trên Ubuntu và Debian. Trang RPM DPKG Rosetta Stone này có các liên kết đến hướng dẫn cho Fedora, Ubuntu và Debian (tìm kiếm debuginfo).

Kể từ khi bạn đang ở trên Ubuntu 12.10 và thực sự muốn xem mã nguồn strcpy() lắp ráp:

$ 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

Có phải 't.c' phải đại diện cho' foo.c' (trong trường hợp này) hay là một tệp mà tôi phải liên kết với? – d0rmLife

+0

Tôi đã thử điều này. Các bước, nhưng nó đi vào một thư mục bất ngờ và nói * Không có tập tin hoặc thư mục *. Tôi sẽ đăng các kết quả trong câu hỏi của tôi ... định dạng sẽ tàn bạo trong một nhận xét. – d0rmLife

+0

@ d0rmLife: có vẻ như strcpy được thực hiện trong assembly trong glibc – teppic

0

Bạn có lẽ không có bất kỳ biểu tượng cho thư viện C của bạn. Hãy thử stepi, nhưng hãy chuẩn bị để chỉ xem hướng dẫn lắp ráp.

+0

'stepi' cũng không vào thư viện. Nhìn vào lý do khác ... – d0rmLife

+0

@ d0rmLife, bạn có chắc không? Bạn đã kiểm tra như thế nào? –

+0

Bằng cách chạy 'GDB' và sử dụng' stepi'. Không, tôi đoán tôi không tích cực nhưng dường như không. Ít nhất, không theo cách thông thường ... – d0rmLife

3

Bạn đã cố gắng để thiết lập một breakpoint cho một chức năng được xác định trong thư viện string thường một phần của standard C library - libc.so

Và như gdb thông báo cho bạn:

(gdb) break strcpy 
Function "strcpy" not defined. 
Make breakpoint pending on future shared library load? (y or [n]) y 

Breakpoint 2 (strcpy) pending. 

thư viện được không nạp được nêu ra. Tuy nhiên, vấn đề thực sự là ngay cả khi thư viện được tải, nếu thư viện tức là libc.so không có biểu tượng gỡ lỗi trong đó, bạn sẽ không thể bước qua mã trong thư viện bằng cách sử dụng gdb.

Bạn có thể kích hoạt chế độ tiết để xem những biểu tượng, gdb có thể tải:

(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; 

Dòng này ví dụ cho bạn biết liệu nó đã có thể để có được những biểu tượng cho libc.so:

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

sau đó, bạn có thể tìm ra nơi biểu tượng debug được nhặt từ việc sử dụng show debug-file-directory:

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

Như bạn thấy /usr/lib/debug đây không chứa .so đầy đủ với các biểu tượng gỡ lỗi. Thay vào đó, chỉ có các thông tin gỡ lỗi mà không cần bất kỳ .text hoặc .data phần của libc.so thực tế mà chương trình sử dụng để thực hiện.

Giải pháp cài đặt thông tin gỡ lỗi cho các thư viện sẽ bị phân biệt cụ thể.

Tôi nghĩ gói được gọi là libc6-dbg trên các bản phân phối dựa trên debian. Trên máy tính của openSUSE của tôi, nó dường như được gọi là glibc-debuginfo

BTW, 1 trên gợi ý của việc sử dụng -fno-builtin để gcc mà không sử dụng các phương pháp tích hợp của nó đối với các chức năng như strcpy và những tiêu chuẩn khác theo quy định như một phần của scottt 's C tiêu chuẩn.

+0

Cho dù libc.so có thông tin gỡ lỗi không phải là vấn đề ở đây. Kể từ khi chương trình được liên kết động, nếu có một cuộc gọi đến strcpy() đi qua PLT, gdb sẽ bắt nó. Vấn đề ở đây là tùy chọn gcc '-fno-buitin' không được thông qua, và lệnh gọi strcpy() trong nguồn đã được dịch sang hướng dẫn lưu trữ. – scottt

+0

Bất kỳ ý tưởng nào gói có thể được gọi cho Ubuntu 12? – d0rmLife

+0

Thử 'sudo apt-get install libc6-dbg' – Tuxdude

Các vấn đề liên quan