A script that used by GDB to load the symbols from Linux kernel modules

From: Hui Zhu
Date: Wed Aug 17 2011 - 01:46:16 EST


Hi,

When use GDB to debug or trace your kernel with KGDB, QEMU debug
interface or KGTP. You must get some trouble with LKM symbols. For
example:
(gdb) target remote localhost:12345
Remote debugging using localhost:12345
native_safe_halt () at
/home/teawater/big/kernel/linux-2.6/arch/x86/include/asm/irqflags.h:50
50 }
(gdb) b e100_poll
Function "e100_poll" not defined.
Make breakpoint pending on future shared library load? (y or [n])
This is because GDB didn't get the LKM symbols. You can do it with
your hand. But if you have a lot of LKMs, it will need some time.

Now, GDB support python script. The attachment is a script to load
all symbols from Linux kernel modules to GDB.
For example:
(gdb) target remote localhost:12345
Remote debugging using localhost:12345
native_safe_halt () at
/home/teawater/big/kernel/linux-2.6/arch/x86/include/asm/irqflags.h:50
50 }
(gdb) so ~/kernel/svn/branches/teawater/getmod.py
(gdb) b e100_poll
Breakpoint 1 at 0xc889db40: file
/home/teawater/big/kernel/linux-2.6/drivers/net/e100.c, line 2165.

This script will include in KGTP(https://code.google.com/p/kgtp/) source.

Thanks,
Hui
#!/usr/bin/python

# This script is used by GDB to load the symbols from Linux kernel modules
# GPL
# Copyright(C) Hui Zhu (teawater@xxxxxxxxx), 2011

#Set special mod_search_dir
#set $mod_search_dir="dir"
#Clear special mod_search_dir
#set $mod_search_dir=(void)1

import gdb;
import os;

def format_file(name):
tmp = "";
for c in name:
if c == "_":
c = "-";
tmp += c;
return tmp;

#Get the mod_search_dir
mod_search_dir = gdb.parse_and_eval("$mod_search_dir");
if mod_search_dir.type.code == gdb.TYPE_CODE_ARRAY:
mod_search_dir = str(mod_search_dir);
mod_search_dir = mod_search_dir[1:len(mod_search_dir)];
mod_search_dir = mod_search_dir[0:mod_name.index("\"")];
else:
mod_search_dir = str(gdb.execute("info files", False, True));
mod_search_dir = mod_search_dir[mod_search_dir.index("Symbols from \"")+len("Symbols from \""):len(mod_search_dir)];
mod_search_dir = mod_search_dir[0:mod_search_dir.index("\"")];
mod_search_dir = mod_search_dir[0:mod_search_dir.rindex("/")];
print "Search modules from "+mod_search_dir+"\n";

mod_list_offset = long(gdb.parse_and_eval("((size_t) &(((struct module *)0)->list))"));
mod_list = long(gdb.parse_and_eval("(&modules)"));
mod_list_current = mod_list;

while 1:
mod_list_current = long(gdb.parse_and_eval("((struct list_head *) "+str(mod_list_current)+")->next"));

#check if need break the loop
if mod_list == mod_list_current:
break;

mod = mod_list_current - mod_list_offset;

#get mod_name
mod_name = str(gdb.parse_and_eval("((struct module *)"+str(mod)+")->name"));
mod_name = mod_name[mod_name.index("\"")+1:len(mod_name)];
mod_name = mod_name[0:mod_name.index("\"")];
mod_name += ".ko"
mod_name = format_file(mod_name);

#get mod_dir_name
mod_dir_name = "";
for root, dirs, files in os.walk(mod_search_dir):
for afile in files:
tmp_file = format_file(afile);
if tmp_file == mod_name:
mod_dir_name = os.path.join(root,afile);
break;
if mod_dir_name != "":
break;

command = " ";

#Add module_core to command
command += str(gdb.parse_and_eval("((struct module *)"+str(mod)+")->module_core"));

#Add each sect_attrs->attrs to command
#get nsections
nsections = int(gdb.parse_and_eval("((struct module *)"+str(mod)+")->sect_attrs->nsections"));
sect_attrs = long(gdb.parse_and_eval("(u64)((struct module *)"+str(mod)+")->sect_attrs"));
for i in range(0, nsections):
command += " -s";
tmp = str(gdb.parse_and_eval("((struct module_sect_attrs *)"+str(sect_attrs)+")->attrs["+str(i)+"].name"));
tmp = tmp[tmp.index("\"")+1:len(tmp)];
tmp = tmp[0:tmp.index("\"")];
command += " "+tmp;
tmp = str(gdb.parse_and_eval("((struct module_sect_attrs *)"+str(sect_attrs)+")->attrs["+str(i)+"].address"));
command += " "+tmp;

if mod_dir_name == "":
print "Can find out",mod_name,"from directory.";
print "Please use following command load the symbols from it:"
print "add-symbol-file some_dir/"+mod_name+command;
else:
#print "add-symbol-file "+mod_dir_name+command;
gdb.execute("add-symbol-file "+mod_dir_name+command, False, False);