kernel启动镜像不是vmlinux,而是它!

本文介绍ARM64架构下Linux内核启动镜像的构建流程,包括vmlinux生成、Image创建及压缩等步骤,并详细解析Makefile配置。

上一节我们介绍了vmlinux的编译过程。vmlinux是一个ELF文件,上百M,无法直接flash到板子上。不同架构最终生成的启动镜像略有区别,一般地:

  • 通过编译生成vmlinuxSystem.map
  • 通过objcopy移除vmlinux中不必要段,输出binary格式Image
  • 再对Image进行压缩,输出不同格式的压缩文件,比如gzip对应的Image.gz
  • 最后通过工具加上BootLoader可以识别的header用于启动引导。

我们重点关注arm64架构的编译情况。

根目录的Makefile include了不同架构的Makefile文件:

https://elixir.bootlin.com/linux/v5.4.200/source/Makefile#L583

include arch/$(SRCARCH)/Makefile

arm64下的Makefile中:

# Default target when executing plain make
boot		:= arch/arm64/boot
KBUILD_IMAGE	:= $(boot)/Image.gz

all:	Image.gz


Image: vmlinux
	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

Image.%: Image
	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

zinstall install:
	$(Q)$(MAKE) $(build)=$(boot) $@

由此可以发现,arm64的启动镜像为压缩后的Image.gz.</

### 关于Linux Kernel Panic的Vmlinux汇编代码及其分析 当Linux内核发生panic时,通常会触发一系列操作来保存崩溃状态以便后续调试[^1]。这些操作可能涉及调用`kexec`机制加载备用内核或其他工具进行内存转储。为了深入理解这一过程中的汇编代码行为,可以从以下几个方面入手: #### 1. **Kernel Panic的核心逻辑** 在Linux内核源码中,`kernel/panic.c`文件定义了核心函数`panic()`,该函数负责处理致命错误并执行必要的清理工作。以下是简化版的伪代码结构: ```c void panic(const char *fmt, ...) { static int panicking; unsigned long flags; if (panicking) while (1); /* 防止嵌套panic */ panicking = 1; console_unblank(); /* 解锁控制台 */ oops_enter(); printk(KERN_EMERG "Kernel panic - not syncing: %s\n", buf); crash_dump(); machine_halt(); /* 停止硬件运行 */ } ``` 此部分代码展示了如何通过打印日志、调用特定架构下的crash dump功能以及最终停止机器完成整个流程。 #### 2. **Crash Dump的具体实现** 对于某些体系结构而言,在进入真正的重启之前可能会先尝试捕获当前系统的状态信息作为诊断依据之一。这一步骤可以通过配置参数指定给定路径下存储镜像副本或者利用专门开发出来的第三方解决方案比如Kdump框架来进行更复杂的场景支持[^2]。 例如设置好环境变量之后可以使用下面这样的指令序列强制让系统陷入异常从而验证相应设施是否正常运作: ```bash echo 1 > /proc/sys/kernel/sysrq echo c > /proc/sysrq-trigger ``` 以上两条命令分别启用了魔术SysRq键位开关并将字符'C'发送过去模拟引发CPU软中断进而达到目的。 #### 3. **Vmlinux反汇编技术应用** 要查看实际生成的目标二进制文件(vmlinux),可以借助GNU Binutils套装里的objdump实用程序提取感兴趣区域内的低级表示形式供进一步研究学习之需。假设已经获取到了未经压缩版本,则可以直接执行类似以下的操作获得详尽列表展示出来每条语句对应的原始机器指令集表达方式: ```shell objdump -d vmlinux | less ``` 如果只想聚焦某几个特别关注的部分而非全部内容的话还可以加上额外选项过滤掉无关干扰项只保留目标范围的数据呈现效果更好一些: ```shell objdump -d --start-address=0x<address> --stop-address=0x<another_address> vmlinux ``` 这里需要注意的是地址数值应当替换为你所关心的实际位置处的确切值才行哦! 另外值得注意的一点就是不同处理器平台之间存在着显著差异因此具体细节也可能有所区别所以最好参照官方文档说明资料为准以免造成误解误判情况的发生几率增加不少呢😊 --- ### 提取关键片段实例演示 以X86_64为例选取一小段来自上述提到过的`panic()`内部实现部分做简单剖析看看大致长什么样儿吧👇 ```asm ... 40a7b0: e8 eb fe ff ff call 40a6a0 <console_unblank> 40a7b5: b8 00 00 00 00 mov $0x0,%eax 40a7ba: bb 01 00 00 00 mov $0x1,%ebx 40a7bf: bf f9 a7 40 00 lea 0x40a7f9(,%rip),%edi 40a7c5: ba 0e 00 00 00 mov $0xe,%edx 40a7ca: e8 d1 fd ff ff call 40a5a0 <printk> ... ``` 从上面可以看出每次遇到重要事件都会伴随着相应的寄存器赋值动作紧接着再跳转到其他地方继续往下走直至结束为止形成完整的链条关系链路图谱可供我们追踪探索其中奥秘所在之处啦😎 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

量子象限

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值