Ubuntu版本:ubuntu-gnome-16.04-desktop-amd64,gnome版
-----------------------------------------------------------------------------------
1. 准备代码hello.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("baoli");
MODULE_DESCRIPTION("hello world module");
static int __init hello_init(void)
{
int * p = 0;
printk(KERN_WARNING "hello world.\n");
*p = 1;
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_WARNING "hello exit!\n");
}
module_init(hello_init);
module_exit(hello_exit);
2. 编译&安装模块
编译成ko模块后,执行isnmod hello.ko,显示killed安装失败。
用dmesg内核日志,可以看到内核跑出了Oops异常:
给出了原因:不能访问NULL指针
错误发生位置:hello_init+0x10,即hello_init偏移0x10处,可以反汇编查看此处对应的具体指令。
3. 反汇编分析
执行:objdump -d hello.o > assemble.txt
汇编代码如下:
hello.o: file format elf64-x86-64
Disassembly of section .init.text:
0000000000000000 <init_module>:
MODULE_LICENSE("GPL");
MODULE_AUTHOR("baoli");
MODULE_DESCRIPTION("hello world module");
static int __init hello_init(void)
{
0: 55 push %rbp
1: 48 c7 c7 00 00 00 00 mov $0x0,%rdi
8: 48 89 e5 mov %rsp,%rbp
b: e8 00 00 00 00 callq 10 <init_module+0x10>
10: c7 04 25 00 00 00 00 movl $0x1,0x0
17: 01 00 00 00
1b: 31 c0 xor %eax,%eax
1d: 5d pop %rbp
1e: c3 retq
Disassembly of section .exit.text:
0000000000000000 <cleanup_module>:
0: 55 push %rbp
1: 48 c7 c7 00 00 00 00 mov $0x0,%rdi
8: 48 89 e5 mov %rsp,%rbp
b: e8 00 00 00 00 callq 10 <cleanup_module+0x10>
10: 5d pop %rbp
11: c3 retq
可以看到hello_init+0x10处对应汇编指令为
movl $0x1,0x0,即*p = 1;
通过objdump反汇编Oops可以轻松的知道错误原因及位置。
4.
objdump
总结
1)objdump -d:
反汇编目标文件中包含的可执行指令。
2)如果需要
混合显示源码和汇编代码,需要加上-S选项,并且在编译目标文件时加上-g。
3)如果在编译目标文件时没有加-g选项,则-S相当于-d。
4)-S选项生成的混合代码,有时文件结构混乱,可读性较差。推荐使用-d选项,直接阅读汇编代码。