LINUX KERNEL & DEVICE DRIVER PROGRAMMING

Ch 4 - Debugging Techniques

($Revision: 1.1 $)
 

Summary


Simple Techniques


Getting Debugging Output: printk


Places to Look for Log Messages


Controlling Logging


Debugging Options in Kernel Configuration


Remember to copy System.map from the kernel source directory to /boot, with appropriate renaming. Several kernel debugging tools depend on it.


Remote Serial Console Device


See serial console device Howto for more details.


Textbook Debugging Techniques


"Pulling" Information


Defining a /proc Read Function

int (*read_proc) (char *page, char **start, off_t offset,
   int count, int *eof, void *data);
int scull_read_procmem(char *buf, char **start, off_t offset,
                   int count, int *eof, void *data)
{
    int i, j, len = 0;
    int limit = count - 80; /* Don't print more than this */

    for (i = 0; i < scull_nr_devs && len <= limit; i++) {
        Scull_Dev *d = &scull_devices[i];
        if (down_interruptible(&d->sem))
                return -ERESTARTSYS;
        len += sprintf(buf+len,"\nDevice %i: qset %i, q %i, sz %li\n",
                       i, d->qset, d->quantum, d->size);
        for (; d && len <= limit; d = d->next) { /* scan the list */
            len += sprintf(buf+len, "  item at %p, qset at %p\n", d, d->data);
            if (d->data && !d->next) /* dump only the last item - save space */
                for (j = 0; j < d->qset; j++) {
                    if (d->data[j])
                        len += sprintf(buf+len,"    % 4i: %8p\n",j,d->data[j]);
                }
        }
        up(&scull_devices[i].sem);
    }
    *eof = 1;
    return len;
}

Connecting to a Directory in /proc

#ifdef SCULL_DEBUG /* use proc only if debugging */
int scull_read_procmem(...) { ...see above...}

#ifdef USE_PROC_REGISTER
static int scull_get_info(char *buf, char **start, off_t offset,
                int len, int unused)
{
    int eof = 0;
    return scull_read_procmem (buf, start, offset, len, &eof, NULL);
}
struct proc_dir_entry scull_proc_entry = {
        namelen:    8,
        name:       "scullmem",
        mode:       S_IFREG | S_IRUGO,
        nlink:      1,
        get_info:   scull_get_info,
};
static void scull_create_proc()
{
    proc_register_dynamic(&proc_root, &scull_proc_entry);
}
static void scull_remove_proc()
{
    proc_unregister(&proc_root, scull_proc_entry.low_ino);
}
#else  /* no USE_PROC_REGISTER - modern world */
static void scull_create_proc()
{
    create_proc_read_entry("scullmem", 0 /* default mode */,
                           NULL /* parent dir */, scull_read_procmem,
                           NULL /* client data */);
}
static void scull_remove_proc()
{
    /* no problem if it was not registered */
    remove_proc_entry("scullmem", NULL /* parent dir */);
}
#endif /* USE_PROC_REGISTER */
#endif /* SCULL_DEBUG */

This code is included only if the debugging preprocessor flag is set. There are two versions, for backward compatibility with older kernels.


Debugging by Watching


Debugging System Faults


Built-in Kernel Debugging Features (as of 2.6.21.1)

Built-in self-checking and tracing features are more useful than interactive debugging tools for large and complex software systems like the Linux kernel.

The following list of built-in kernel debugging options has been growing over time.


If you insist on trying a debugger: kdb


How to install

Adapted from http://www-128.ibm.com/developerworks/linux/library/l-kdbug/

© 2003 T. P. Baker. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means without written permission. (Last updated by $Author: baker $ on $Date: 2010/06/07 14:29:15 $.)