gdb macros from Embedded Linux Primer

Here are the macros from the book. Remember that when using these, they are by necessity tied to kernel internal data structures. As such, they are fragile and subject to breakage when kernel data structures are modified. You may have to tweak them for your particular kernel. Thanks to Scott Anderson for the original ideas.

Have fun!

Listing 14-10

$ cat ~/.gdbinit
set history save on
set history filename ~/.gdb_history
set output-radix 16

define connect
#   target remote bdi:2001
    target remote /dev/ttyS0
    b panic
    b sys_sync
end

Listing 14-11
gdb find_task Macro

 1 # Helper function to find a task given a PID or the
 2 # address of a task_struct.
 3 # The result is set into $t
 4 define find_task
 5   # Addresses greater than _end: kernel data...
 6   # ...user passed in an address
 7   if ((unsigned)$arg0 > (unsigned)&_end)
 8     set $t=(struct task_struct *)$arg0
 9   else
10     # User entered a numeric PID
11     # Walk the task list to find it
12     set $t=&init_task
13     if (init_task.pid != (unsigned)$arg0)
14       find_next_task $t
15       while (&init_task!=$t && $t->pid != (unsigned)$arg0)
16         find_next_task $t
17       end
18       if ($t == &init_task)
19         printf "Couldn't find task; using init_task\n"
20       end
21     end
22   end
23   printf "Task \"%s\":\n", $t->comm
24 end

Listing 14-12
gdb Print Process Information Macro

 1 define ps
 2   # Print column headers
 3   task_struct_header
 4   set $t=&init_task
 5   task_struct_show $t
 6   find_next_task $t
 7   # Walk the list
 8   while &init_task!=$t
 9     # Display useful info about each task
10     task_struct_show $t
11     find_next_task $t
12   end
13 end
14
15 document ps
16 Print points of interest for all tasks
17 end

Listing 14-14
gdb task_struct_show Macro

 1 define task_struct_show
 2   # task_struct addr and PID
 3   printf "0x%08X %5d", $arg0, $arg0->pid
 4
 5   # Place a 'state == 0)
16     printf "Running   "
17   else
18     if ($arg0->state == 1)
19       printf "Sleeping  "
20     else
21       if ($arg0->state == 2)
22         printf "Disksleep "
23       else
24         if ($arg0->state == 4)
25           printf "Zombie    "
26         else
27           if ($arg0->state == 8)
28             printf "sTopped   "
29           else
30             if ($arg0->state == 16)
31               printf "Wpaging   "
32             else
33               printf "%2d        ", $arg0->state
34             end
35           end
36         end
37       end
38     end
39   end
40
41   # User NIP
42   if ($arg0->thread.regs)
43     printf "0x%08X ", $arg0->thread.regs->nip
44   else
45     printf "           "
46   end
47
48   # Display the kernel stack pointer
49   printf "0x%08X ", $arg0->thread.ksp
50
51   # device
52   if ($arg0->signal->tty)
53     printf "%s   ", $arg0->signal->tty->name
54   else
55     printf "(none) "
56   end
57
58   # comm
59   printf "%s\n", $arg0->comm
60 end

Listing 14-15
gdb find_next_task Macro

define find_next_task
  # Given a task address, find the next task in the linked list
  set $t = (struct task_struct *)$arg0
  set $offset=( (char *)&$t->tasks - (char *)$t)
  set $t=(struct task_struct *)( (char *)$t->tasks.next-(char *)$offset)
end

Listing 14-16
gdb List Modules Macro

 1 define lsmod
 2   printf "Address\t\tModule\n"
 3   set $m=(struct list_head *)&modules
 4   set $done=0
 5   while ( !$done )
 6     # list_head is 4-bytes into struct module
 7     set $mp=(struct module *)((char *)$m->next - (char *)4)
 8     printf "0x%08X\t%s\n", $mp, $mp->name
 9     if ( $mp->list->next == &modules)
10       set $done=1
11     end
12     set $m=$m->next
13   end
14 end
15
16 document lsmod
17 List the loaded kernel modules and their start addresses
18 end

Thanks for posting the macros from the book - cut & paste is a time saver for implementation.

Following the thread of this topic, from LWN.net Debugging kernel modules