zImage来历
顶层vmlinux ---->
arch/arm/boot/Image --->
arch/arm/boot/compressed/piggy.gz --->
arch/arm/boot/compressed/vmlinux --->
arch/arm/boot/zImage
如果要分析zImage的反汇编反汇编文件,可将arch/arm/boot/compressed/vmlinux进行反汇编,
arm-linux-xxx-objdump –d vmlinux > vmlinux.dis
对顶层的vmlinux反汇编得到的是未压缩的内核的反汇编文件,这个vmlinux才是真正的Linux内核。
piggy.gz压缩文件的特点
gzip -f -9 < Image > piggy.gz
在piggy.gz的结尾四个字节表示的是 Image 镜像的大小,并且是以小端格式存放的。下面我们验证一下:
可以看到,Image的大小是6806148B,十六进制值就是67DA84,接下来看看piggy.gz的结尾:
可以看到,确实是将0x67DA84以小端的格式存放在了piggy.gz的结尾四字节中了。
vmlinux.lds
1: /*
2: * linux/arch/arm/boot/compressed/vmlinux.lds.in
3: *
4: * Copyright (C) 2000 Russell King
5: *
6: * This program is free software; you can redistribute it and/or modify
7: * it under the terms of the GNU General Public License version 2 as
8: * published by the Free Software Foundation.
9: */
10: OUTPUT_ARCH(arm)
11: ENTRY(_start)
12: SECTIONS
13: {
14: /DISCARD/ : {
15: *(.ARM.exidx*)
16: *(.ARM.extab*)
17: /*
18: * Discard any r/w data - this produces a link error if we have any,
19: * which is required for PIC decompression. Local data generates
20: * GOTOFF relocations, which prevents it being relocated independently
21: * of the text/got segments.
22: */
23: *(.data)
24: }
25:
26: . = 0;
27: _text = .;
28:
29: .text : {
30: _start = .;
31: *(.start)
32: *(.text)
33: *(.text.*)
34: *(.fixup)
35: *(.gnu.warning)
36: *(.rodata)
37: *(.rodata.*)
38: *(.glue_7)
39: *(.glue_7t)
40: *(.piggydata)
41: . = ALIGN(4);
42: }
43:
44: _etext = .;
45:
46: _got_start = .;
47: .got : { *(.got) }
48: _got_end = .;
49: .got.plt : { *(.got.plt) }
50: _edata = .;
51:
52: . = ALIGN(8);
53: __bss_start = .;
54: .bss : { *(.bss) }
55: _end = .;
56:
57: . = ALIGN(8); /* the stack must be 64-bit aligned */
58: .stack : { *(.stack) }
59:
60: .stab 0 : { *(.stab) }
61: .stabstr 0 : { *(.stabstr) }
62: .stab.excl 0 : { *(.stab.excl) }
63: .stab.exclstr 0 : { *(.stab.exclstr) }
64: .stab.index 0 : { *(.stab.index) }
65: .stab.indexstr 0 : { *(.stab.indexstr) }
66: .comment 0 : { *(.comment) }
67: }
68:
arch/arm/boot/compressed/head.S
1: .section ".start", #alloc, #execinstr
2: /*
3: * 清理不同的调用约定
4: */
5: .align
6: .arm @ 启动总是进入ARM状态
7: start:
8: .type start,#function
9: .rept 7
10: mov r0, r0
11: .endr
12: ARM( mov r0, r0 )
13: ARM( b 1f )
14: THUMB( adr r12, BSYM(1f) )
15: THUMB( bx r12 )
16: .word 0x016f2818 @ 用于boot loader的魔数
17: .word start @ 加载/运行zImage的绝对地址(编译时确定), 在vmlinux.lds中可以看到,zImage的链接起始地址是0
18: .word _edata @ zImage结束地址,分析vmlinux.lds可以看到,_edata是 .got 段的结束地址,后面紧接的就是.bss段和.stack段
19: THUMB( .thumb )
20: 1: mov r7, r1 @ 保存构架ID到r7(此前由bootloader放入r1)
21: mov r8, r2 @ 保存内核启动参数地址到r8(此前由bootloader放入r2)
22: #ifndef __ARM_ARCH_2__
23: /*
24: * 通过Angel调试器启动 - 必须进入 SVC模式且关闭FIQs/IRQs
25: * (numeric definitions from angel arm.h source).
26: * 如果进入时在user模式下,我们只需要做这些
27: */
28: mrs r2, cpsr @ 获取当前模式
29: tst r2, #3 @ 判断是否是user模式
30: bne not_angel
31: mov r0, #0x17 @ angel_SWIreason_EnterSVC
32: ARM( swi 0x123456 ) @ angel_SWI_ARM swi会产生软中断,会跳入中断向量表,这个向量表用的是bootloader的,因为在head.S中并没有建立新的向量表
33: THUMB( svc 0xab ) @ angel_SWI_THUMB
34: not_angel:
35: mrs r2, cpsr @ 关闭中断
36: orr r2, r2, #0xc0 @ 以保护调试器的运作 关闭IRQ和FIQ
37: msr cpsr_c, r2
38: #else
39: teqp pc, #0x0c000003@ 关闭中断(此外bootloader已设置模式为SVC)
40: #endif
GOT表是什么?
GOT(Global Offset Table)表中每一项都是本运行模块要引用的一个全局变量或函数的地址。可以用GOT表来间接引用