How to find ioctl callback function inside the driver source

How can you see which code a module executes when your app calls an ioctl system call?

Consider this situation:

You app gets to the point where it executes an ioctl syscall and returns an error, e.g.

if (ioctl(fd, STVMIX_IOC_DISCONNECTLAYERS, &STVMIX_Ioctl_DisconnectLayers) != 0)
{
    /* IOCTL failed */
    ErrorCode = ST_ERROR_BAD_PARAMETER;
    printf (" STVMIX_DisconnectLayers():Ioctl error 0x%x\n", ErrorCode);
 }

Assuming that the module/driver source is available to y ou, how can you find out which function does the kernel call internally for this ioctl syscall?

Here’s the steps which should help you identify which function the ioctl calls internaly to handle your ioctl system call:

  • find out the node for the file descriptor (fd). This shouldn’t be too hard, just find out how fd was opened.
  • look up the major and minor numbers of the node in the /dev filesystem
  • cat /proc/devices and find the driver name from the major number
  • Next look for “struct file_operations” in the driver’s source. This struct holds the callback pointers for system calls, including the ioctl call and the kernel will later use this to resolve which is your ioctl callback function. Example:
    • static struct file_operations stvmix_ioctl_fops = {
      					open  : stvmix_ioctl_open,
      					read  : stvmix_ioctl_read,
      					write : stvmix_ioctl_write,
      					ioctl : stvmix_ioctl_ioctl ,
      					release : stvmix_ioctl_release,
      				};

    In this example the ioctl callback is called stvmix_ioctl_ioctl

  • Find the function in the source, usually it will consist of one big case-statement, find your particular ioctl value (in this case it will be STVMIX_IOC_DISCONNECTLAYERS) and see what’s happening in there.
  • In the not very common, yet possible (as it was in my case!) event of more than one such functions living in the code – add printk statements to your driver to id the code execution path. Note that to be able to see them you will need to either make them at least of level KERN_WARNING (level 4) which is the default log-level of the kernel, or tell the kernel to output higher level messages, e.g. KERN_NOTICE which is 5. You can do this by adding “loglevel=5” to kernel’s command line params.

Leave a Reply

Your email address will not be published. Required fields are marked *