2012-06-21 23 views
11

Với strace nó có thể nhìn thấy các cuộc gọi ioctl cho bộ mô tả tập tin nhất định và với lệnh nhất định. Đối số thứ ba là một cấu trúc, nhưng strace cho thấy nó như một con trỏ thô tới bộ nhớ. strace dụ đầu ra:Giải thích đầu ra strace

open("/dev/node", O_RDWR) = 3 
ioctl(3, 0x108, 0x8f0eb18) = 0 
close(3) 

Có cách nào (tùy chọn strace hoặc các công cụ khác) để xem cấu trúc, hoặc ít nhất một giá trị đằng sau một con trỏ liệu là gì?

+0

Liệu nó cung cấp cho bạn địa chỉ của chỉ dẫn? Nếu vậy nó thực sự đơn giản trong GDB để thêm một điểm break và sau đó nhìn vào bộ nhớ ... Làm thế nào bạn muốn xác định cấu trúc thực tế tôi không chắc chắn như vậy. – Matt

+0

Tôi có nghĩa là nếu tôi sẽ viết nó trong chương trình của tôi, nó sẽ trông như thế này: 'ioctl (dev_node, IOCTL_CODE, & ioctl_struct)', trong đó đối số thứ ba là một cấu trúc kiểu Ioctl_Buf_Struct. Khi strace được sử dụng cho chương trình nhị phân như chúng ta thấy trong ví dụ trên, tôi sẽ tò mò muốn biết những gì đằng sau địa chỉ 0x8f0eb18: cấu trúc được gửi ở đó là gì, hoặc ít nhất giá trị của nó là gì. Gdb có thể trợ giúp ở đây không? –

+0

cũng ... Nếu bạn chạy chương trình, hãy dừng lại ngay trước lệnh đó, sau đó bạn có thể tìm các giá trị bằng cách dereferencing con trỏ. Sử dụng strace để tìm tất cả các cuộc gọi malloc, cho đến khi bạn tìm thấy một trong đó trả về con trỏ đó. Điều đó sẽ cho bạn biết kích thước của cấu trúc.Sau đó bạn có thể nhìn vào bộ nhớ, với kích thước đã biết và tái tạo cấu trúc ở dạng nhị phân của nó. Bạn có thể không bao giờ biết * cấu trúc là gì, nhưng bạn có thể tìm thấy giá trị. – Matt

Trả lời

2

Trong gdb, nếu bạn ngăn chặn nó ngay trước khi cuộc gọi đến ioctl, bạn có thể sau đó nhập:

(gdb) p *(ioctl_struct *) 0x8f0eb18 

Điều đó sẽ chỉ cho bạn cách nội dung mà bản đồ vị trí bộ nhớ để các ioctl_struct.

1

Tôi đã gặp sự cố tương tự: muốn kiểm tra một tòa nhà syscall đến ioctl được tạo bởi vde_switch (tạo giao diện mạng ảo TUN/TAP) để biết tôi đang làm gì sai trong mã của mình để làm điều tương tự như vde_switch, nhưng lập trình)

Bằng cách chạy:.

sudo strace vde_switch -tap tap0 

tôi đã có thể biết, như Terry Greentail, rằng syscall đang được thực hiện là ioctl(5, TUNSETIFF, 0x7fffa99404e0) và con trỏ sẽ là một tài liệu tham khảo đến một cấu trúc loại struct ifreq. Trong mã của tôi, tôi đã có một cái gì đó như ioctl(tapfd, TUNSETIFF, &ifr_dev). Ban đầu tôi cố gắng làm cho gdb dừng trên syscall, thiết lập: catch syscall ioctl (Tôi đã chạy gdb là gdb --args vde_switch -tap tap0), nhưng bất cứ khi nào bắt được hit, gdb không cho thấy thông tin về các tham số của ioctl. Sau khi vật lộn với điều này trong một thời gian, tôi quyết định chạy strace bên trong gdb, như:

gdb --args strace vde_witch -tap -tap0 

Mặc dù không có điểm dừng đã làm việc theo cách này, đầu ra cho thấy trong đó mô tả tập tin đã được sử dụng:

open("/dev/net/tun", O_RDWR)   = 9 
ioctl(9, TUNSETIFF, 0x7fffffffe350)  = 0 

Vì vậy, tôi đã cố gắng một thời điểm khác với: gdb --args strace vde_witch -tap -tap0 và thiết lập một breakpoint có điều kiện:

b ioctl if $rdi==9 

Các quy ước gọi (tôi đang trên một AMD64) sử dụng RDI f hoặc các tham số đầu tiên, RSI cho phần thứ hai và RDX cho thứ ba (xem System V AMD64 ABI.) Cuối cùng, khi breakpoint được hit, tôi đã có thể kiểm tra việc ifreq cấu trúc:

Breakpoint 6, ioctl() at ../sysdeps/unix/syscall-template.S:81 
81  ../sysdeps/unix/syscall-template.S: File or directory not found. 

(gdb) p (struct ifreq) *$rdx 
$5 = {ifr_ifrn = {ifrn_name = "tap0", '\000' <repete 11 vezes>}, ifr_ifru = {ifru_addr = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_dstaddr = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_broadaddr = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_netmask = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_hwaddr = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_flags = 4098, ifru_ivalue = 4098, ifru_mtu = 4098, ifru_map = {mem_start = 4098, mem_end = 0, base_addr = 0, irq = 0 '\000', dma = 0 '\000', port = 0 '\000'}, ifru_slave = "\002\020", '\000' <repete 13 vezes>, ifru_newname = "\002\020", '\000' <repete 13 vezes>, ifru_data = 0x1002 <Address 0x1002 out of bounds>}}