linux-5.17
echo "CONFIG_DEBUG_INFO=y" >> ./arch/arm/configs/multi_v7_defconfig
make ARCH=arm CROSS_COMPILE=${CROSS_COMPILE} defconfig
qemu-system-arm -M virt -m 512M -kernel arch/arm/boot/zImage -nographic -S -s 等待连接. 目前 gdb server 已经架好.
1. qemu virt 板子 内存 已经有镜像了.
2. 被halt 住了
gdb-multiarch -x gdb_init -tui
gdb_init的内容
set logging file log_gdb.txt
set logging on
set architecture armv7
target remote localhost:1234
我们的动作
1. print $pc
2. si
3. 一直 si到 0x40010000
此时
r0 0x0 0
r1 0xffffffff -1
r2 0x48000000 1207959552
4. x/8xw 0x40010000
5. add-symbol-file arch/arm/boot/compressed/vmlinux -o 0x40010000
6. si
7. 在单步到 arch/arm/boot/compressed/head.S 543 行的时候,再单步就发现失去符号信息了
8. 在单步543行之前,做两个动作
symbol
add-symbol-file arch/arm/boot/compressed/vmlinux -o 0x41B3C460
9.再次单步到 1442行(ARM( mov pc, r4 ) @ call kernel) 之前 的 状态为如下
r0 0x0 0
r1 0xffffffff -1
r2 0x48000000 1207959552
r3 0xc 12
r4 0x40208000 1075871744
可见 :
r0 : 0
r1 : 0xffffffff
r2 : 0x48000000
从下面的命令 可见 : 0x40208000 是 Image
可以对得上 xxd arch/arm/boot/Image | head -5
(gdb) x/8xw 0x40208000
0x40208000: 0xeb0431d6 0xe10f9000 0xe229901a 0xe319001f
0x40208010: 0xe3c9901f 0xe38990d3 0x1a000004 0xe3899c01
arch/arm/kernel/head.o 的反汇编
Disassembly of section .head.text:
00000000 <stext>:
0: ebfffffe bl 0 <__hyp_stub_install>
4: e10f9000 mrs r9, CPSR
8: e229901a eor r9, r9, #26
c: e319001f tst r9, #31
10: e3c9901f bic r9, r9, #31
14: e38990d3 orr r9, r9, #211 ; 0xd3
18: 1a000004 bne 30 <stext+0x30>
1c: e3899c01 orr r9, r9, #256 ; 0x100
$ arm-linux-gnueabihf-readelf -S vmlinux
There are 42 section headers, starting at offset 0x1702bd54:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .head.text PROGBITS c0208000 008000 000280 00 AX 0 0 4
[ 2] .text PROGBITS c0300000 010000 d4c714 00 AX 0 0 4096
[ 3] .rodata PROGBITS c1100000 d60000 52dc2a 00 WA 0 0 4096
symbol
add-symbol-file vmlinux -s .text 0x40300000 -s .head.text 0x40208000 -s .rodata 0x41100000
__turn_mmu_on
ret r3
下面就需要 再次更换符号信息
symbol
add-symbol-file vmlinux
info symbol 0x40208000
info symbol stext
arm32-linux boot 过程,如果要用gdb调试,需要换多少次符号信息?
- 以下的过程适合于任何 平台及linux版本的 arm32-linux boot过程(命令里的地址需要根据情况替换)
1. zImage 过程中
1. gdb attach 上去 , 需要加载一次 symbol
2. 由于zImage 搬移,需要 更新一次 symbol
2. Image 过程中
1. 由于程序流转移到 Image , 需要更新一次
2. 由于开mmu后,从恒等映射页表切换到同一pgd的kernel页表 , 需要更新一次
直接从Image启动
为什么 arm32 Image 不能随意放个位置,就可以跑起来
rv64/arm64 Image都可以,是不是刚好地址满足???TODO
为什么arm32 Image 不可以,地址不对,会进入 __fixup_pv_table 循环
arch/arm/kernel/head.S 中对地址做了校验,该地址应该满足 : "该地址减去 TEXT_OFFSET 之后,满足2M对齐" , TEXT_OFFSET 平台相关
原因:
https:
https:
https:
用Image 直接启动 :
qemu-system-arm -M virt -m 512M -kernel arch/arm/boot/Image -nographic -S -s
此时Image作为第一阶段,还是被加载到 0x40010000.
symbol 和 add-symbol-file vmlinux -s .text 0x40108000 -s .head.text 0x40010000 -s .rodata 0x40f08000
死在了 arch/arm/kernel/phys2virt.S : line 50
49 0: mov r0, r0 @ deadloop on error
50 b 0b
zImage 启动 和 Image 启动 唯一的区别 就是
1. 过程中 Image 被加载地址不同
2. Image启动前的寄存器信息(r0/r1/r2)都是一样的
TEXT_OFFSET 是什么,为什么每个平台都不一样
mem 物理首地址 - (mem物理首地址+TEXT_OFFSET) 存了什么
arch/arm/kernel/head.S
122 adr_l r8, _text @ __pa(_text)
123 sub r8, r8, #TEXT_OFFSET @ PHYS_OFFSET(0x208000)
...
137 bl __fixup_pv_table
1. 计算 r0 : r0 = r8 >> 12
2. 计算 r3 : r3 = LOW_OFFSET(r0)
3. 计算 r3[21:0] 是否为0 , 不为0 ,一直循环
arm/Makefile
140 # Text offset. This list is sorted numerically by address in order to
141 # provide a means to avoid/resolve conflicts in multi-arch kernels.
142 # Note: the 32kB below this value is reserved for use by the kernel
143 # during boot, and this offset is critical to the functioning of
144 # kexec-tools.
编译 arch/arm/boot/compressed/head.S 时 编译选项为 : -DTEXT_OFFSET=0x00208000
arch/arm/boot/compressed/head.S
283 mov r0, pc
284 and r0, r0, #0xf8000000
...
315
316 add r4, r0, #TEXT_OFFSET
那么 qemu virt 平台 怎么才能 用 -kernel 将 Image 加载到 0x40208000 ,而不是 0x40010000 ?
用 gdb 的命令
用 qemu 的命令行
改 qemu 源码
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index dc62918..566b5c2 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -23,7 +23,7 @@
* They have different preferred image load offsets from system RAM base.
*/
#define KERNEL_ARGS_ADDR 0x100
-#define KERNEL_LOAD_ADDR 0x00010000
+#define KERNEL_LOAD_ADDR 0x000208000
#define KERNEL64_LOAD_ADDR 0x00080000
typedef enum {
我在这里完成了 Image 的启动
但也不是直接将 Image 启动
而是 用 ./scripts/mkuboot.sh 给 Image 包了个头 , 让 u-boot 将 Image 加载到 Image 想位于的地方