2012-06-21 20 views
11

Con strace es posible ver la llamada ioctl para el cierto descriptor de archivo y con cierto comando. El tercer argumento es una estructura, pero strace lo muestra como un puntero sin formato a la memoria. Ejemplo de salida strace:Interpretación de salida de salida

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

¿Hay alguna manera (strace opciones u otras herramientas) para ver cuál es la estructura, o por lo menos un valor detrás de un puntero en bruto?

+0

¿Te da la dirección de la ¿instrucción? Si es así, es realmente simple en GDB agregar un punto de quiebre y luego mirar la memoria ... Cómo no se puede determinar la estructura real. – Matt

+0

Quiero decir que si lo escribiera en mi programa, se vería así: 'ioctl (dev_node, IOCTL_CODE, & ioctl_struct)', donde el tercer argumento es una estructura de tipo Ioctl_Buf_Struct. Cuando strace se utiliza para el programa binario como vemos en el ejemplo anterior, me gustaría saber qué hay detrás de la dirección 0x8f0eb18: cuál es la estructura que se envía allí, o al menos cuál es su valor. ¿Puede gdb ayudar aquí? –

+0

bien ... Si ejecuta el programa, deténgalo si está justo antes de ese comando, luego puede encontrar los valores desreferenciando el puntero. Use strace para encontrar todas las llamadas malloc, hasta que encuentre la que devuelve ese puntero. Eso te dirá el tamaño de la estructura.Luego puede mirar la memoria, con el tamaño conocido, y así reproducir la estructura en su forma binaria. Puede que nunca sepas * qué * es la estructura, pero puedes encontrar el valor. – Matt

Respuesta

2

En GDB, si se detiene justo antes de la llamada a ioctl, a continuación, puede entrar en:

(gdb) p *(ioctl_struct *) 0x8f0eb18 

que le mostrará cómo los contenidos de que los mapas de las localizaciones de memoria a la ioctl_struct.

1

Me encontré con un problema similar: quería inspeccionar un syscall a ioctl hecho por vde_switch (que crea una interfaz de red virtual TUN/TAP), para saber qué estaba haciendo mal en mi código (que tenía hacer lo mismo que vde_switch, pero mediante programación)

ejecutando:.

sudo strace vde_switch -tap tap0 

pude conocer, como Terry Greentail, que la llamada al sistema que se hizo fue ioctl(5, TUNSETIFF, 0x7fffa99404e0) y el puntero sería una referencia a una estructura de tipo struct ifreq. En mi código tenía algo así como ioctl(tapfd, TUNSETIFF, &ifr_dev).

Inicialmente traté de hacer parada GDB en una llamada al sistema, estableciendo: catch syscall ioctl (me había acabado BGF como gdb --args vde_switch -tap tap0), pero cada vez que se vio afectada la captura, el BGF no mostraron ninguna información acerca de los parámetros de ioctl. Después de luchar con esto durante un tiempo, decidí correr strace dentro de gdb, como:

gdb --args strace vde_witch -tap -tap0 

Aunque ningún punto de interrupción había trabajado de esta manera, la salida mostraron lo que se estaba utilizando el descriptor de archivo:

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

así que he intentado otra vez con: gdb --args strace vde_witch -tap -tap0 y establecer un punto de interrupción condicional:

b ioctl if $rdi==9 

La convención de llamada (estoy en un AMD64) utiliza RDI f o el primer parámetro, RSI para el segundo y RDX para el tercer (ver System V AMD64 ABI.) Por último, cuando fue alcanzado el punto de interrupción, yo era capaz de inspeccionar la estructura ifreq:

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>}}