如何编译出带有调试信息的内核模块
Posted Li-Yongjun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何编译出带有调试信息的内核模块相关的知识,希望对你有一定的参考价值。
示例
led_drv.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/io.h>
#define GPIO_CLR_REG ((__u32)0x3f200028)
#define GPIO_SET_REG ((__u32)0x3f20001C)
static volatile __u32 *gpio_led_reg;
static int led_init(void)
printk("led on\\n");
gpio_led_reg = (__u32 *)ioremap(GPIO_CLR_REG, 4);
writel(0x7F, gpio_led_reg);
return 0;
static void led_exit(void)
printk("led off\\n");
gpio_led_reg = (__u32 *)ioremap(GPIO_SET_REG, 4);
writel(0x7F, gpio_led_reg);
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("Dual BSD/GPL");
Makefile
obj-m = led_drv.o
KDIR = /home/liyongjun/project/board/buildroot/RPi3/build/linux-custom
CROSS_COMPILE = /home/liyongjun/project/board/buildroot/RPi3/host/bin/arm-buildroot-linux-gnueabihf-
all:
make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules
clean:
make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) clean
编译
$ make
make -C /home/liyongjun/project/board/buildroot/RPi3/build/linux-custom M=/home/liyongjun/project/board/buildroot/override/led_drv ARCH=arm CROSS_COMPILE=/home/liyongjun/project/board/buildroot/RPi3/host/bin/arm-buildroot-linux-gnueabihf- modules
make[1]: 进入目录“/home/liyongjun/project/board/buildroot/RPi3/build/linux-custom”
CC [M] /home/liyongjun/project/board/buildroot/override/led_drv/led_drv.o
MODPOST /home/liyongjun/project/board/buildroot/override/led_drv/Module.symvers
CC [M] /home/liyongjun/project/board/buildroot/override/led_drv/led_drv.mod.o
LD [M] /home/liyongjun/project/board/buildroot/override/led_drv/led_drv.ko
make[1]: 离开目录“/home/liyongjun/project/board/buildroot/RPi3/build/linux-custom”
使用 file 命令查看 ko 是否带有 debug 信息,不带
$ file led_drv.ko
led_drv.ko: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), BuildID[sha1]=3aa652128eede4a93a7a8f31dbcc12a6ca49508c, not stripped
使用 gdb 查看 ko 是否带有 debug 符号信息,不带
(gdb) file led_drv.ko
Reading symbols from led_drv.ko...
(No debugging symbols found in led_drv.ko)
使用 objdump 查看 ko 是否带有 debug 符号信息,不带
$ /home/liyongjun/project/board/buildroot/RPi3/host/bin/arm-buildroot-linux-gnueabihf-objdump -d -l led_drv.ko
led_drv.ko: file format elf32-littlearm
Disassembly of section .text.unlikely:
00000000 <init_module>:
led_init():
0: e1a0c00d mov ip, sp
4: e92dd800 push fp, ip, lr, pc
8: e24cb004 sub fp, ip, #4
c: e52de004 push lr ; (str lr, [sp, #-4]!)
10: ebfffffe bl 0 <__gnu_mcount_nc>
14: e3000000 movw r0, #0
18: e3400000 movt r0, #0
1c: ebfffffe bl 0 <printk>
20: e3a01004 mov r1, #4
24: e3a00028 mov r0, #40 ; 0x28
28: e3430f20 movt r0, #16160 ; 0x3f20
2c: ebfffffe bl 0 <ioremap>
30: e3003000 movw r3, #0
34: e3403000 movt r3, #0
38: e5830000 str r0, [r3]
3c: f57ff04e dsb st
40: e3a0207f mov r2, #127 ; 0x7f
44: e5933000 ldr r3, [r3]
48: e5832000 str r2, [r3]
4c: e3a00000 mov r0, #0
50: e89da800 ldm sp, fp, sp, pc
00000054 <cleanup_module>:
led_exit():
54: e1a0c00d mov ip, sp
58: e92dd800 push fp, ip, lr, pc
5c: e24cb004 sub fp, ip, #4
60: e52de004 push lr ; (str lr, [sp, #-4]!)
64: ebfffffe bl 0 <__gnu_mcount_nc>
68: e3000000 movw r0, #0
6c: e3400000 movt r0, #0
70: ebfffffe bl 0 <printk>
74: e3a01004 mov r1, #4
78: e3a0001c mov r0, #28
7c: e3430f20 movt r0, #16160 ; 0x3f20
80: ebfffffe bl 0 <ioremap>
84: e3003000 movw r3, #0
88: e3403000 movt r3, #0
8c: e5830000 str r0, [r3]
90: f57ff04e dsb st
94: e3a0207f mov r2, #127 ; 0x7f
98: e5933000 ldr r3, [r3]
9c: e5832000 str r2, [r3]
a0: e89da800 ldm sp, fp, sp, pc
Disassembly of section .plt:
000000a4 <.plt>:
...
如何给 ko 添加调试信息呢?
使用 EXTRA_CFLAGS = -g
选项
因为编译内核模块不像编译一个 app,Makefile 中没有 gcc 命令,无法添加 -g 选项。
Makefile
obj-m = led_drv.o
KDIR = /home/liyongjun/project/board/buildroot/RPi3/build/linux-custom
CROSS_COMPILE = /home/liyongjun/project/board/buildroot/RPi3/host/bin/arm-buildroot-linux-gnueabihf-
EXTRA_CFLAGS = -g
all:
make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules
clean:
make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) clean
使用 EXTRA_CFLAGS 选项,就是向下级 Makefile 传递 CFLAGS 参数,通常,下级 Makefile 中都会隐式使用 CFLAGS 参数。
编译后再次查看 ko 信息
使用 file 命令查看 ko 是否带有 debug 信息,带
$ file led_drv.ko
led_drv.ko: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), BuildID[sha1]=00f91fef955b4980fbec6f39e8a0b994d6c56b6c, with debug_info, not stripped
使用 gdb 查看 ko 是否带有 debug 符号信息,带
(gdb) file led_drv.ko
Reading symbols from led_drv.ko...
使用 objdump 查看 ko 是否带有 debug 符号信息,带
$ /home/liyongjun/project/board/buildroot/RPi3/host/bin/arm-buildroot-linux-gnueabihf-objdump -d -l led_drv.ko
led_drv.ko: file format elf32-littlearm
Disassembly of section .text.unlikely:
00000000 <init_module>:
led_init():
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:12
0: e1a0c00d mov ip, sp
4: e92dd800 push fp, ip, lr, pc
8: e24cb004 sub fp, ip, #4
c: e52de004 push lr ; (str lr, [sp, #-4]!)
10: ebfffffe bl 0 <__gnu_mcount_nc>
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:13
14: e3000000 movw r0, #0
18: e3400000 movt r0, #0
1c: ebfffffe bl 0 <printk>
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:15
20: e3a01004 mov r1, #4
24: e3a00028 mov r0, #40 ; 0x28
28: e3430f20 movt r0, #16160 ; 0x3f20
2c: ebfffffe bl 0 <ioremap>
30: e3003000 movw r3, #0
34: e3403000 movt r3, #0
38: e5830000 str r0, [r3]
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:16
3c: f57ff04e dsb st
__raw_writel():
/home/liyongjun/project/board/buildroot/RPi3/build/linux-custom/./arch/arm/include/asm/io.h:95
40: e3a0207f mov r2, #127 ; 0x7f
led_init():
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:16
44: e5933000 ldr r3, [r3]
__raw_writel():
/home/liyongjun/project/board/buildroot/RPi3/build/linux-custom/./arch/arm/include/asm/io.h:95
48: e5832000 str r2, [r3]
led_init():
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:19
4c: e3a00000 mov r0, #0
50: e89da800 ldm sp, fp, sp, pc
00000054 <cleanup_module>:
led_exit():
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:22
54: e1a0c00d mov ip, sp
58: e92dd800 push fp, ip, lr, pc
5c: e24cb004 sub fp, ip, #4
60: e52de004 push lr ; (str lr, [sp, #-4]!)
64: ebfffffe bl 0 <__gnu_mcount_nc>
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:23
68: e3000000 movw r0, #0
6c: e3400000 movt r0, #0
70: ebfffffe bl 0 <printk>
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:24
74: e3a01004 mov r1, #4
78: e3a0001c mov r0, #28
7c: e3430f20 movt r0, #16160 ; 0x3f20
80: ebfffffe bl 0 <ioremap>
84: e3003000 movw r3, #0
88: e3403000 movt r3, #0
8c: e5830000 str r0, [r3]
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:25
90: f57ff04e dsb st
__raw_writel():
/home/liyongjun/project/board/buildroot/RPi3/build/linux-custom/./arch/arm/include/asm/io.h:95
94: e3a0207f mov r2, #127 ; 0x7f
led_exit():
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:25
98: e5933000 ldr r3, [r3]
__raw_writel():
/home/liyongjun/project/board/buildroot/RPi3/build/linux-custom/./arch/arm/include/asm/io.h:95
9c: e5832000 str r2, [r3]
led_exit():
/home/liyongjun/project/board/buildroot/override/led_drv/led_drv.c:26
a0: e89da800 ldm sp, fp, sp, pc
Disassembly of section .plt:
000000a4 <.plt>:
...
方法二
之所以编译的内核模块不带调试信息,是因为依赖的内核没有开启调试选项(-g),可以编译内核时打开调试选项,这样使用该内核编译出的内核模块也带有调试信息。
以上是关于如何编译出带有调试信息的内核模块的主要内容,如果未能解决你的问题,请参考以下文章