1) 查看当前安装的内核模块:lsmod
# lsmod
Module Size Used by Tainted: G
mailbox_test 16384 0
spinor_blk 49152 1
查看当前某个模块是否安装
# lsmod | grep "spinor_blk"
spinor_blk 49152 1
1) insmod使用方法
insmod加载模块,需要指定完整的路径和模块名字、依赖的模块,才可以成功的加载需要的模块,如下:
insmod /tmp/ mailbox_test.ko
2) modprobe使用方法
modprobe [-acdlrtvV][--help][模块文件][符号名称 = 符号值]
参数:
-a或--all 载入全部的模块。
-c或--show-conf 显示所有模块的设置信息。
-d或--debug 使用排错模式。
-l或--list 显示可用的模块。
-r或--remove 模块闲置不用时,即自动卸载模块。
-t或--type 指定模块类型。
-v或--verbose 执行时显示详细的信息。
-V或--version 显示版本信息。
-help 显示帮助。
安装内核模块:
modprobe –v mailbox_test
卸载内核模块:
modprobe –v –r mailbox_test
Note:mobprobe使用失败
# modprobe -v mailbox_test
modprobe: can't change directory to '/lib/modules': No such file or directory
导致该问题出现, 主要是由于我当前所使用的根文件系统为只读文件系统,未能创建'/lib/modules'目录所导致的。
rmmod [-wfas] [模块名]...
-v:显示指令执行的详细信息;
-f:强制移除模块,使用此选项比较危险;
-w:等待着,直到模块能够被除时在移除模块;
-s:向系统日志(syslog)发送错误信息。
如下:
rmmod mailbox_test
Note:不需要指定完成路径,只需模块名即可。
由于内核模块是单独编译的,其符号表未加入到vmlinux中,当使用GDB调试内核模块的时候,需单独的将对应的内核模块的调试信息加入到GDB中,才能精准的调试该模块。如何正确的导入内核模块的符号表信息,主要涉及到以下两个方面:
所使用的命令是:
arm-linux-objdump
参数选项:
-a
--archive-headers
显示档案库的成员信息,类似ls -l将lib*.a的信息列出。
-C
--demangle
将底层的符号名解码成用户级名字,除了去掉所开头的下划线之外,还使得C++函数名以可理解的方式显示出来。
-g
--debugging
显示调试信息。企图解析保存在文件中的调试信息并以C语言的语法显示出来。仅仅支持某些类型的调试信息。有些其他的格式被readelf -w支持。
-e
--debugging-tags
类似-g选项,但是生成的信息是和ctags工具相兼容的格式。
-d
--disassemble
从objfile中反汇编那些特定指令机器码的section。
-D
--disassemble-all
与 -d 类似,但反汇编所有section.
--prefix-addresses
反汇编的时候,显示每一行的完整地址。这是一种比较老的反汇编格式。
-EB
-EL
--endian={big|little}
指定目标文件的小端。这个项将影响反汇编出来的指令。在反汇编的文件没描述小端信息的时候用。例如S-records.
-f
--file-headers
显示objfile中每个文件的整体头部摘要信息。
-h
--section-headers
--headers
显示目标文件各个section的头部摘要信息。
-H
--help
简短的帮助信息。
-i
--info
显示对于 -b 或者 -m 选项可用的架构和目标格式列表。
-j name
--section=name
仅仅显示指定名称为name的section的信息
-l
--line-numbers
用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求编译时使用了-g之类的调试编译选项。
-m machine
--architecture=machine
指定反汇编目标文件时使用的架构,当待反汇编文件本身没描述架构信息的时候(比如S-records),这个选项很有用。可以用-i选项列出这里能够指定的架构.
-r
--reloc
显示文件的重定位入口。如果和-d或者-D一起使用,重定位部分以反汇编后的格式显示出来。
-R
--dynamic-reloc
显示文件的动态重定位入口,仅仅对于动态目标文件意义,比如某些共享库。
-s
--full-contents
显示指定section的完整内容。默认所有的非空section都会被显示。
-S
--source
尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,效果比较明显。隐含了-d参数。
--show-raw-insn
反汇编的时候,显示每条汇编指令对应的机器码,如不指定--prefix-addresses,这将是缺省选项。
--no-show-raw-insn
反汇编时,不显示汇编指令的机器码,如不指定--prefix-addresses,这将是缺省选项。
--start-address=address
从指定地址开始显示数据,该选项影响-d、-r和-s选项的输出。
--stop-address=address
显示数据直到指定地址为止,该项影响-d、-r和-s选项的输出。
-t
--syms
显示文件的符号表入口。类似于nm -s提供的信息
-T
--dynamic-syms
显示文件的动态符号表入口,仅仅对动态目标文件意义,比如某些共享库。它显示的信息类似于 nm -D|--dynamic 显示的信息。
-V
--version
版本信息
-x
--all-headers
显示所可用的头信息,包括符号表、重定位入口。-x 等价于-a -f -h -r -t 同时指定。
-z
--disassemble-zeroes
一般反汇编输出将省略大块的零,该选项使得这些零块也被反汇编。
@file
可以将选项集中到一个文件中,然后使用这个@file选项载入。
# arm-linux-objdump --section-headers module_test.ko
Module_test.ko: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000da4 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .init.text 00000024 00000000 00000000 00000dd8 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
2 .exit.text 0000001c 00000000 00000000 00000dfc 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
3 .ARM.extab 00000084 00000000 00000000 00000e18 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .ARM.exidx 00000058 00000000 00000000 00000e9c 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
5 .ARM.extab.init.text 0000000c 00000000 00000000 00000ef4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .ARM.exidx.init.text 00000008 00000000 00000000 00000f00 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
7 .ARM.extab.exit.text 0000000c 00000000 00000000 00000f08 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .ARM.exidx.exit.text 00000008 00000000 00000000 00000f14 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
9 .rodata 00000278 00000000 00000000 00000f1c 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
10 .modinfo 00000132 00000000 00000000 00001194 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .rodata.str1.1 000002d4 00000000 00000000 000012c6 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
12 __mcount_loc 0000002c 00000000 00000000 0000159c 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
13 __versions 00000bc0 00000000 00000000 000015c8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
14 .note.gnu.build-id 00000024 00000000 00000000 00002188 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 __jump_table 00000018 00000000 00000000 000021b0 2**3
CONTENTS, ALLOC, LOAD, RELOC, DATA
16 .data 0000005c 00000000 00000000 000021c8 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
17 __verbose 00000040 00000000 00000000 00002228 2**3
CONTENTS, ALLOC, LOAD, RELOC, DATA
18 .gnu.linkonce.this_module 00000200 00000000 00000000 00002280 2**6
CONTENTS, ALLOC, LOAD, RELOC, DATA, LINK_ONCE_DISCARD
19 .bss 00000008 00000000 00000000 00002480 2**2
ALLOC
20 .debug_frame 00000280 00000000 00000000 00002480 2**2
CONTENTS, RELOC, READONLY, DEBUGGING
21 .debug_info 0000defa 00000000 00000000 00002700 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
22 .debug_abbrev 00000949 00000000 00000000 000105fa 2**0
CONTENTS, READONLY, DEBUGGING
23 .debug_loc 0000067e 00000000 00000000 00010f43 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
24 .debug_aranges 00000048 00000000 00000000 000115c1 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
25 .debug_ranges 00000200 00000000 00000000 00011609 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
26 .debug_line 00001026 00000000 00000000 00011809 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
27 .debug_str 00007b34 00000000 00000000 0001282f 2**0
CONTENTS, READONLY, DEBUGGING
28 .comment 0000008e 00000000 00000000 0001a363 2**0
CONTENTS, READONLY
29 .note.GNU-stack 00000000 00000000 00000000 0001a3f1 2**0
CONTENTS, READONLY
30 .ARM.attributes 0000002f 00000000 00000000 0001a3f1 2**0
CONTENTS, READONLY
涉及内核模块调试需用到的段信息是以下几个:
Arm-linux-objdump --section-headers module_test.ko | grep .text
0 .text 00000da4 00000000 00000000 00000034 2**2
Arm-linux-objdump --section-headers module_test.ko | grep .text
9 .rodata 00000278 00000000 00000000 00000f1c 2**2
16 .data 0000005c 00000000 00000000 000021c8 2**2
Arm-linux-objdump --section-headers module_test.ko | grep .bss
19 .bss 00000008 00000000 00000000 00002480 2**2
内核模块的信息主要保存在/proc/modules中,如下:
cat /proc/modules
modules_test 16384 0 - Live 0xbf013000
spinor_blk 49152 1 - Live 0xbf000000 (O)
0xbf013000 为module_test的加载地址(install_addr)
0xbf000000 为spinor_blk的加载地址(install_addr)
GDB导入vmlinux符号表:
arm-none-linux-gnueabi-gdb vmlinux
add-symbol-file ./drivers/mailbox/module_test.ko 0xbf013034 -s .data 0xbf0151c8 -s .bss 0xbf045480
具体使用方法:
Add-symbol-file *.ko text_addr –s .section0 section_addr0 -s .section1 section_addr1
Text_addr = install_addr + file_off
.section_addr0 = install_addr + file_off
如:.data 段
Section_addr = install_addr + file_off = 0xbf013000 + 0x21c8 = 0xbf0151c8
一般来说,正常调试内核模块所需要的段信息有.text、.data、.bss等几个就可以正常调试内核模块了。