如何装载内核模块的符号表

147 views
Skip to first unread message

Adam Jiang

unread,
Jun 8, 2010, 7:39:26 AM6/8/10
to 中文内核邮件列表, embedded-linux-zh-CN
Hello,

使用gdb做remote调试时,如何装载内核模块的符号表?
在我的环境中调试scsi_mod模块时,发生如下错误,

....
(gdb) disassemble scsi_get_command
No symbol table is loaded. Use the "file" command.

这个符号在scsi_mod.ko文件之中,我用file命令装载了这个文件,
但是错误依旧存在。

此外,我使用gdb vmlinux启动remote调试的,被包含在这个文件中的
符号可以正常的disas。

因为我使用的image文件并不由我自己控制,而是自动编译的结果,所以
我不能给编译过程增加-g选项,这时这个问题似乎变得有点难搞。
但是,我可以拿到System.map和Module.symvers文件,这两个文件似乎
包含了符号和符号的位置。
调试时,应该如何运用这两个文件?大家有没有遇到过此类情况?

谢谢。

--
Adam Jiang
-----------------------------------
e-mail:jiang...@gmail.com
http://www.adamjiang.com
-----------------------------------

Adam Jiang

unread,
Jun 9, 2010, 12:32:00 AM6/9/10
to Li Yu, 中文内核邮件列表, embedded-linux-zh-CN
2010/6/9 Li Yu <raise...@gmail.com>:

> 于 2010年06月08日 19:39, Adam Jiang 写道:
>> Hello,
>>
>> 使用gdb做remote调试时,如何装载内核模块的符号表?
>> 在我的环境中调试scsi_mod模块时,发生如下错误,
>>
>> ....
>> (gdb) disassemble scsi_get_command
>> No symbol table is loaded. Use the "file" command.
>>
>> 这个符号在scsi_mod.ko文件之中,我用file命令装载了这个文件,
>> 但是错误依旧存在。
>>
>> 此外,我使用gdb vmlinux启动remote调试的,被包含在这个文件中的
>> 符号可以正常的disas。
>>
>> 因为我使用的image文件并不由我自己控制,而是自动编译的结果,所以
>> 我不能给编译过程增加-g选项,这时这个问题似乎变得有点难搞。
>> 但是,我可以拿到System.map和Module.symvers文件,这两个文件似乎
>> 包含了符号和符号的位置。
>> 调试时,应该如何运用这两个文件?大家有没有遇到过此类情况?
>>
>
> 如果我记得没错,可以这样:
>
> gdb> add-symbol-file scsi_mod.ko VADDR
>
> VADDR可以通过grep scsi_mod.ko /proc/modules获得。
>

Hi, Li Yu.

非常感谢你的回复!

我刚才在实际调试环境中试验了一下,这个方法似乎时对的,唯一有一点点小小的问题就是
lsmod | grep scsi_mod 得到的是这样一个值:

/ # lsmod | grep scsi
scsi_mod 84000 4 sg,libata,usb_storage,sd_mod, Live 0xc017e000

最后一列给出的地址是相对于现在KERNEL的虚拟地址的OFFSET,所以,在gdb中指定这个
地址并不能正确的dump出来符号的内容。需要计算一下实际的虚拟地址才行。我遇到了这样
一个错误:

(gdb) disassemble scsi_get_command
Dump of assembler code for function scsi_get_command:
0xc017edb8 <scsi_get_command+0>: Cannot access memory at
address 0xc017edb8

这个虚拟地址应该怎样计算?

/大头阿当

Adam Jiang

unread,
Jun 9, 2010, 12:44:11 AM6/9/10
to Américo Wang, Li Yu, embedded-linux-zh-CN, 中文内核邮件列表
2010/6/9 Américo Wang <xiyou.w...@gmail.com>:
> 试试 /sys/module/scsi_mod/sections/.text
>

谢谢 Wang.

cat /sys/module/scsi_mod/sections/.text

得到的数值和lsmod最后一列一致,看上去时一个offset。
disas还是不成功。

Adam Jiang

unread,
Jun 9, 2010, 1:02:21 AM6/9/10
to Li Yu, 中文内核邮件列表, embedded-linux-zh-CN
2010/6/9 Li Yu <raise...@gmail.com>:
> 于 2010年06月08日 19:39, Adam Jiang 写道:
>> Hello,
>>
>> 使用gdb做remote调试时,如何装载内核模块的符号表?
>> 在我的环境中调试scsi_mod模块时,发生如下错误,
>>
>> ....
>> (gdb) disassemble scsi_get_command
>> No symbol table is loaded. Use the "file" command.
>>
>> 这个符号在scsi_mod.ko文件之中,我用file命令装载了这个文件,
>> 但是错误依旧存在。
>>
>> 此外,我使用gdb vmlinux启动remote调试的,被包含在这个文件中的
>> 符号可以正常的disas。
>>
>> 因为我使用的image文件并不由我自己控制,而是自动编译的结果,所以
>> 我不能给编译过程增加-g选项,这时这个问题似乎变得有点难搞。
>> 但是,我可以拿到System.map和Module.symvers文件,这两个文件似乎
>> 包含了符号和符号的位置。
>> 调试时,应该如何运用这两个文件?大家有没有遇到过此类情况?
>>
>
> 如果我记得没错,可以这样:
>
> gdb> add-symbol-file scsi_mod.ko VADDR
>
> VADDR可以通过grep scsi_mod.ko /proc/modules获得。
>

OK,我找到方法了。

gdb vmlinux
......
add-symbol-file /lib/modules/.../scsi_mod.ko 0xc017e000 -s .data
0xc0191c60 -s .bss 0xc0192600
......

disas scsi_get_command

其中,必须把.text,.data,.bss等各段的具体位置告诉gdb才行,这些地址都可以采用Americo Wang教的方法
cat /proc/modules/scsi_mod/.text 等得到的。

问题解决,谢谢各位。

/大头阿当

Adam Jiang

unread,
Jun 9, 2010, 1:20:04 AM6/9/10
to yy Hong, Li Yu, embedded-linux-zh-CN, 中文内核邮件列表
2010/6/9 yy Hong <yaa...@gmail.com>:
> Adam:
> 你是在什么平台上调试?x86?mips?arm?power?

Hi, Hong

我在mips上做调试的。用serial接续。

/Adam

>> _______________________________________________
>> Linux 内核开发中文邮件列表
>> Linux-...@zh-kernel.org
>> http://zh-kernel.org/mailman/listinfo/linux-kernel
>> Linux 内核开发中文社区: http://zh-kernel.org

Adam Jiang

unread,
Jun 9, 2010, 2:01:36 AM6/9/10
to Li Yu, 中文内核邮件列表, embedded-linux-zh-CN
2010/6/9 Adam Jiang <jiang...@gmail.com>:

将elf的每个段的地址逐一加入gdb挺烦人,所以,我写了一个脚本做这个事。
它可以输出一个命令字串,拷贝粘贴到gdb命令行,或者重定向到文件,
然后source这个文件都可以。贴到这里跟大家分享一下。

_________________________________________
#!/bin/sh
# file: disas_helper.sh
# author: jiang...@gmail.com
# revision: 2010-06-09

if [ $# != 2 ]; then
echo "$0 objfile modname"
exit 1
fi
if [ ! -f $1 ]; then
echo "cannot find objfile '$1'"
exit 1
fi
if [ ! -d /sys/module/$2/sections ]; then
echo "cannot find module sections '$2'"
exit 1
fi
modname=$2

add_sect()
{
addr=`cat /sys/module/$modname/sections/$1`
if [ $1 == ".text" ]; then
echo "$addr"
else
echo "-s $1 $addr"
fi
}

add_all_sect()
{
for i in `ls -a
/sys/module/$modname/sections/.[abcdefghijklmnopqrstuvwxyz]*`; do
if [ `basename $i` != ".text" ]; then
add_sect `basename $i`;
fi
done;
}

echo "add-symbol-file $1" `add_sect .text` `add_all_the_other_sect`
_________________________________________

Reply all
Reply to author
Forward
0 new messages