This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Add a menu for select directory and a check.

Thanks,
Hui

On Wed, Aug 17, 2011 at 13:45, Hui Zhu <teawater@gmail.com> wrote:
> 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@gmail.com), 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;

#Check if the target is available
if str(gdb.selected_thread()) == "None":
	raise gdb.error("Please connect to Linux Kernel before use the script.");

#Output the help
print "Use GDB command \"set $mod_search_dir=dir\" to set an directory for search the modules."

#Get the mod_search_dir
mod_search_dir_list = [];
#Get dir from $mod_search_dir
tmp_dir = gdb.parse_and_eval("$mod_search_dir");
if tmp_dir.type.code == gdb.TYPE_CODE_ARRAY:
	tmp_dir = str(tmp_dir);
	tmp_dir = tmp_dir[1:len(tmp_dir)];
	tmp_dir = tmp_dir[0:tmp_dir.index("\"")];
	mod_search_dir_list.append(tmp_dir);
#Get dir that same with current vmlinux
tmp_dir = str(gdb.execute("info files", False, True));
tmp_dir = tmp_dir[tmp_dir.index("Symbols from \"")+len("Symbols from \""):len(tmp_dir)];
tmp_dir = tmp_dir[0:tmp_dir.index("\"")];
tmp_dir = tmp_dir[0:tmp_dir.rindex("/")];
mod_search_dir_list.append(tmp_dir);
#Get the dir of current Kernel
tmp_dir = "/lib/modules/" + str(os.uname()[2]);
if os.path.isdir(tmp_dir):
	mod_search_dir_list.append(tmp_dir);
#Let user choice dir
mod_search_dir = "";
while mod_search_dir == "":
	for i in range(0, len(mod_search_dir_list)):
		print str(i)+". "+mod_search_dir_list[i];
	try:
		s = input('Select a directory for search the modules [0]:');
	except SyntaxError:
		s = 0;
	except:
		continue;
	if s < 0 or s >= len(mod_search_dir_list):
		continue;
	mod_search_dir = mod_search_dir_list[i];

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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]