admin 管理员组文章数量: 887007
内核oops错误调试学习笔记
驱动开发中遇到的 oops 问题,导致内核崩溃,log 一般如下形式
Unable to handle kernel paging request at virtual address bfb10be0pgd = c0003000[bfb10be0] *pgd=80000040006003, *pmd=47ab3003, *pte=00000000Internal error: Oops: 80000207 [#1] PREEMPT SMP ARM
Modules linked in: wctdm(+) i2s timer pppoe ppp_async brcmfmac pppox ppp_generic nf_conntrack_ipv6 iptable_nat ipt_REJECT ipt_MASQUERADE cfg80211 xt_time xt_tcpudp xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_conntrack xt_comment xt_TCPMSS xt_REDIRECT xt_LOG xt_FLOWOFFLOAD spidev slhc nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_conntrack_ipv4 nf_nat_ipv4 nf_nat nf_log_ipv4 nf_flow_table_hw nf_flow_table nf_defrag_ipv6 nf_defrag_ipv4 nf_conntrack_rtcache nf_conntrack iptable_mangle iptable_filter ip_tables dahdi crc_ccitt compat brcmutil rtc_sunxi ledtrig_heartbeat echo ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables x_tables snd_pcm_oss snd_mixer_oss snd_rawmidi snd_seq_device snd_hwdep [last unloaded: h3i2s]CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 4.14.63 #0Hardware name: Allwinner sun8i Family
task: c0c07080 task.stack: c0c00000
PC is at 0xbfb10be0LR is at vchan_complete+0x188/0x1ac
关注点:
PC is at 0xbfb10be0
说明了出错时的指令位置 0xbfb10be0
1.如何确定 0xbfb10be0 是编进内核里的函数地址还是insmod 模块加载的函数地址?
进入内核源码目录(编译过的)
cat System.map
c0008000 T stext
c00080a0 t __create_page_tables
c000817c t __turn_mmu_on_loc
c0008188 t __fixup_smp
c00081f0 t __fixup_smp_on_up
c0008214 t __fixup_pv_table
c0008268 t __vet_atags
c0200000 T __idmap_text_start
c0200000 T __turn_mmu_on
c0200000 T _stext
.....
.....
c0c9d318 b radix_tree_node_cachep
c0c9d31c B __bss_stop
c0c9d31c B _end
看在不在其中,不在则说明是在 insmod 加载的模块里。
2.如果在 insmod 加载的模块里 ,如何确定是在哪一个ko 里?
答:通过查看/proc/kallsyms 来确定。
cat /proc/kallsyms | grep 0xbfb10b
/proc/kallsyms 的内容节选如下,其中右边 [ ] 里的就是所在驱动名
bf000084 t snd_hwdep_poll [snd_hwdep]
bf000a04 t snd_hwdep_ioctl [snd_hwdep]
bf0000ac t snd_hwdep_mmap [snd_hwdep]
bf000544 t snd_hwdep_open [snd_hwdep]
bf0004b8 t snd_hwdep_release [snd_hwdep]
bf0000d4 t snd_hwdep_dev_free [snd_hwdep]
bf000334 t snd_hwdep_dev_register [snd_hwdep]
bf000238 t snd_hwdep_dev_disconnect [snd_hwdep]
bf000cdc t cleanup_module [snd_hwdep]
bf000110 T snd_hwdep_new [snd_hwdep]
由此可以根据 PC is at 0xbfb10be0 确定是哪个模块的,同时还可以确定是哪个函数里。
3.反汇编 找到指令位置
如果是确定是在.ko 里,直接反汇编 .ko ,.ko反汇编出来的地址是从0开始。
xxx-objdump -D xxx.ko > xxx.dis
如果是编译进内核里,要反汇编整个内核的话,时间要很久!
这里从网上找到一个快速高效的脚本 objdump_func.sh :
#!/bin/bashvmlinux=$1
symbol=$2 if [ -z "$vmlinux" ]; then echo "usage : $0 vmlinux symbol"exit
fi
#这里指定你 objdump 的路径
objdump=~/work/openwrt/arm-openwrt-linux-objdumpstartaddress=$(nm -n $vmlinux | grep "\w\s$symbol" | awk '{print "0x"$1;exit}')
endaddress=$(nm -n $vmlinux | grep -A1 "\w\s$symbol" | awk '{getline; print "0x"$1;exit}') if [ -z "$symbol" ]; then echo "dump all symbol"$objdump -d $vmlinux
else echo "start-address: $startaddress, end-address: $endaddress" $objdump -d $vmlinux --start-address=$startaddress --stop-address=$endaddress
fi
使用方法 ./objdump_func.sh vmlinux xx_func > xxx.dis
cat xxx.dis 找到指令位置,分析汇编代码,找到出错原因。这十分考验读汇编能力。
鸣谢:要感谢韦东山老师,以上知识学习自韦老师的二期视频。
本文标签: 内核oops错误调试学习笔记
版权声明:本文标题:内核oops错误调试学习笔记 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1732356680h1534631.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论