Terry Greentail
Terry Greentail

Reputation: 143

Is there a way to see the value behind a raw pointer in strace output?

With strace it is possible to see the ioctl call for the certain file descriptor and with certain command. The third argument is a structure, but strace shows it as a raw pointer to the memory. strace output example:

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

Is there a way (strace options or other tools) to see what is the structure, or at least a value behind a raw pointer?

Upvotes: 13

Views: 6394

Answers (2)

Tarc
Tarc

Reputation: 3312

I've run into a similar problem: wanted to inspect a syscall to ioctl made by vde_switch (which creates a TUN/TAP virtual network interface), in order to know what I was doing wrong in my code (which had to do the same thing as vde_switch, but programmatically.)

By running:

sudo strace vde_switch -tap tap0

I was able to know, as Terry Greentail, that the syscall being made was ioctl(5, TUNSETIFF, 0x7fffa99404e0) and the pointer would be a reference to a structure of type struct ifreq. In my code I had something like ioctl(tapfd, TUNSETIFF, &ifr_dev).

Initially I tried to make gdb stop on a syscall, setting: catch syscall ioctl (I had run gdb as gdb --args vde_switch -tap tap0), but whenever the catch was hit, gdb showed no information about the parameters of ioctl. After struggling with this for a while, I decided to run strace inside gdb, as:

gdb --args strace vde_witch -tap -tap0

Although no breakpoint had worked in this way, the output showed which file descriptor was being used:

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

So I tried another time with: gdb --args strace vde_witch -tap -tap0 and set a conditional breakpoint:

b ioctl if $rdi==9

The calling convention (I'm on an AMD64) uses RDI for the first parameter, RSI for the second and RDX for the third (see System V AMD64 ABI.) Finally, when the breakpoint was hit, I was able to inspect the ifreq structure:

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

Upvotes: 2

koral
koral

Reputation: 6650

In gdb, if you stop it right before the call to ioctl, you can then enter:

(gdb) p *(ioctl_struct *) 0x8f0eb18

That will show you how the contents of that memory location maps to the ioctl_struct.

Upvotes: 2

Related Questions