2009-08-06 25 views
50

Tôi đang cố gắng tháo rời chương trình để xem hướng dẫn lắp ráp syscall (lệnh INT, tôi tin) và trình xử lý với GDB và đã viết một chương trình nhỏ (xem bên dưới) để mở và đóng tệp. Tôi đã có thể làm theo các cuộc gọi để fopen với GDB cho đến khi nó thực hiện một cuộc gọi. Khi tôi cố gắng nói với GDB "tháo rời 0x ...." (địa chỉ cuộc gọi), nó trả lời bằng 'Không có hàm nào chứa địa chỉ được chỉ định.' Có thể buộc GDB phải tháo rời (hoặc hiển thị nó trong trình biên dịch càng tốt càng tốt) địa chỉ bộ nhớ đó không? Nếu vậy, làm thế nào?Tôi làm cách nào để buộc GDB phải tháo rời?

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    FILE* f; 
    f = fopen("main.c", "r"); 
    if (!f) { 
     perror("open"); 
     return -1; 
    } 
fclose(f); 
return 0; 
} 
+2

fopen() không phải là cuộc gọi hệ thống, đó là cuộc gọi đến thư viện chuẩn C. Và tại sao bạn nghĩ rằng một cuộc gọi hệ thống phải được thực hiện thông qua một hướng dẫn INT? –

+0

Tôi có thể sai, nhưng chúng tôi đã được dạy rằng các cuộc gọi fopen cuối cùng dẫn đến một cuộc gọi hệ thống đến hạt nhân để mở tệp và trả về một bộ mô tả tệp? – Patrick

+1

Patrick: Vâng, nhưng không cần phải làm điều đó một cách trực tiếp. Thông thường nó gọi hàm libc mà sau đó nhập hạt nhân. Nhưng gọi nhân có thể được thực hiện không chỉ với int (điều này là chậm) nhưng với syscall/sysenter tùy thuộc vào kiến ​​trúc bộ xử lý ... – k3a

Trả lời

40

Bạn chỉ muốn tháo rời phần chính của mình? Nếu vậy hãy thử này:

(gdb) info line main 
(gdb) disas STARTADDRESS ENDADDRESS 

Giống như vậy:

[email protected] /cygdrive/c/prog/dsa 
$ gcc-3.exe -g main.c 

[email protected] /cygdrive/c/prog/dsa 
$ gdb a.exe 
GNU gdb 6.8.0.20080328-cvs (cygwin-special) 
... 
(gdb) info line main 
Line 3 of "main.c" starts at address 0x401050 <main> and ends at 0x401075 <main+ 
(gdb) disas 0x401050 0x401075 
Dump of assembler code from 0x401050 to 0x401075: 
0x00401050 <main+0>: push %ebp 
0x00401051 <main+1>: mov %esp,%ebp 
0x00401053 <main+3>: sub $0x18,%esp 
0x00401056 <main+6>: and $0xfffffff0,%esp 
0x00401059 <main+9>: mov $0x0,%eax 
0x0040105e <main+14>: add $0xf,%eax 
0x00401061 <main+17>: add $0xf,%eax 
0x00401064 <main+20>: shr $0x4,%eax 
0x00401067 <main+23>: shl $0x4,%eax 
0x0040106a <main+26>: mov %eax,-0xc(%ebp) 
0x0040106d <main+29>: mov -0xc(%ebp),%eax 
0x00401070 <main+32>: call 0x4010c4 <_alloca> 
End of assembler dump. 

Tôi không thấy hệ thống ngắt cuộc gọi của bạn tuy nhiên. INT 21h mặc dù, cuối cùng tôi nhớ lại

+0

ok, sau đó tôi sẽ cố gắng tìm kiếm INT 21h trong tương lai. Cảm ơn gợi ý đó. Nhưng những gì tôi muốn thử là làm theo chuỗi cuộc gọi có nguồn gốc trong fopen() (không nhìn thấy nó trong mã của bạn ...) 'xuống' cho đến khi tôi có thể thấy lệnh INT. – Patrick

+1

Quản lý nó - Con đường để đi là sử dụng cả câu trả lời của bạn và Falaina. Tôi đã phải biên dịch nó tĩnh với gcc --static main.c và sau đó sử dụng gdb/objdump để đi sâu vào thư viện C. Tối đa, kết quả là một cuộc gọi đến __open_nocancel, đã thực hiện * INT 0x80 *. Nhờ cả hai bạn – Patrick

+4

Lưu ý: cú pháp 'disas 0x401050 0x401075' ít nhất trong phiên bản gdb 7.7 sẽ không hoạt động. Bạn đã viết nó giống như 'disas 0x401050,0x401075'. Cũng có lẽ bạn có thể muốn thêm tiền tố «/ m» để hiển thị mã nguồn xung quanh: 'disas \ m 0x401050,0x401075' –

28

Đây không phải là câu trả lời trực tiếp cho câu hỏi của bạn, nhưng vì bạn dường như chỉ muốn tháo rời tệp nhị phân , có lẽ bạn chỉ có thể sử dụng objdump:

objdump -d program 

này sẽ cho bạn của mình dissassembly bạn có thể thêm -S nếu bạn muốn nó nguồn chú thích

+0

⁺¹ đối với '-S', tôi không biết nó có thể bao gồm mã nguồn. –

6

bạn có thể buộc gcc để đầu ra trực tiếp vào mã lắp ráp bằng cách thêm.. the -S switch

gcc -S hello.c 
83

Vâng, tháo rời không phải là lệnh tốt nhất để sử dụng ở đây. Lệnh bạn muốn là "x/i" (kiểm tra như hướng dẫn):

(gdb) x/i 0xdeadbeef 
+3

CẢM ƠN! Thêm văn bản này để giúp người khác tìm thấy gợi ý này: đây là hướng dẫn được sử dụng để tháo rời blob nhị phân, ROM tháo rời, kiểm tra hướng dẫn trong tệp hình ảnh nhị phân v.v. Viết chương trình C nhỏ để fread() blob nhị phân vào bộ đệm. Sau đó, làm 'x/i' trên bộ đệm. – user188012

+0

@ user188012 nếu bạn muốn tháo rời một đốm màu nhị phân, cách dễ dàng hơn để sử dụng nó là sử dụng bộ tách rời độc lập như ndisasm hoặc tương tự. –

+0

Bạn có thể sử dụng: x/i $ pc để nhận hướng dẫn cho máy tính là địa chỉ của hướng dẫn hiện tại – k3a

3

Nếu tất cả những gì bạn muốn là để xem tháo gỡ với các cuộc gọi INTC, sử dụng objdump -d như một ai đó đề cập nhưng sử dụng - tùy chọn tĩnh khi biên dịch. Nếu không hàm fopen không được biên dịch vào elf và được liên kết khi chạy.

7

fopen() là một hàm thư viện C và vì vậy bạn sẽ không thấy bất kỳ chỉ dẫn syscall nào trong mã của bạn, chỉ cần gọi hàm bình thường. Tại một số điểm, nó gọi mở (2), nhưng nó làm điều đó thông qua một tấm bạt lò xo. Chỉ đơn giản là nhảy đến trang VDSO, được cung cấp bởi hạt nhân cho mọi quá trình. VDSO sau đó cung cấp mã để thực hiện cuộc gọi hệ thống. Trên các bộ vi xử lý hiện đại, các lệnh SYSCALL hoặc SYSENTER sẽ được sử dụng, nhưng bạn cũng có thể sử dụng INT 80h trên các bộ xử lý x86.

1

Bạn không phải sử dụng gdb. GCC sẽ làm điều đó.

gcc -S foo.c 

Điều này sẽ tạo foo.s là lắp ráp.

gcc -m32 -c -g -Wa,-a,-ad foo.c > foo.lst 

Phiên bản trên sẽ tạo tệp danh sách có cả C và cụm được tạo bởi nó. GCC FAQ

1

gdb tháo rời có/m để bao gồm mã nguồn cùng với hướng dẫn. Điều này tương đương với objdump -S, với lợi ích bổ sung của việc hạn chế chỉ một hàm (hoặc dải địa chỉ) quan tâm.

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