Linux Kernel의 elf 바이너리인 vmlinux가 arch/arm/boot/zImage로 변환되는 과정을 분석해보았습니다.
우선 조성진님이 올려주신 그림부터 보겠습니다. (http://www.iamroot.org/xe/Kernel_10_ARM/173496)
간략하게(?) 요약하면 다음과 같습니다.
1. vmlinux --> arch/arm/boot/Image
2. arch/arm/boot/Image --> arch/arm/boot/compressed/piggy.gzip
: Image를 gzip 압축하여 piggy.gzip을 생성합니다.
3. arch/arm/boot/compressed/piggy.gzip --> arch/arm/boot/compressed/piggy.gzip.o
: 압축한 piggy.gzip을 데이터로 포함하고 있는 piggy.gzip.S를 컴파일하여 piggy.gzip.o를 생성합니다.
4. arch/arm/boot/compressed/piggy.gzip.o --> arch/arm/boot/compressed/vmlinux
: piggy.gzip.o와 다른 여러 오브젝트들을 arch/arm/boot/compressed/vmlinux.lds 링커스크립트에 정의된 대로 링크하여 vmlinux elf 바이너리를 생성합니다.5. arch/arm/boot/compressed/vmlinux --> arch/arm/boot/zImage
arch/arm/boot/compressed/vmlinux는 elf 바이너리이므로 아래의 형태로 구성됩니다.
[ELF Header]
[Program Header Table]
[Section]
…
[Section]
[Section Header Table]
Section Header를 확인해보면 아래와 같구요.
arch/arm/boot/compressed (master) $ arm-none-eabi-readelf -S ./vmlinux There are 22 section headers, starting at offset 0x2beb1c: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00000000 001000 005a94 00 AX 0 0 32 [ 2] .rodata PROGBITS 00005a94 006a94 000d10 00 A 0 0 4 [ 3] .piggydata PROGBITS 000067a4 0077a4 29be70 00 A 0 0 1 [ 4] .got PROGBITS 002a2614 2a3614 00003c 00 WA 0 0 4 [ 5] .pad PROGBITS 002a2650 2a3650 000008 00 A 0 0 0 [ 6] .bss NOBITS 002a2658 2a3658 000024 00 WA 0 0 4 [ 7] .stack NOBITS 002a2680 2a3680 001000 00 WA 0 0 1 [ 8] .debug_line PROGBITS 00000000 2a4680 00263f 00 0 0 1 [ 9] .debug_info PROGBITS 00000000 2a6cbf 008b02 00 0 0 1 [10] .debug_abbrev PROGBITS 00000000 2af7c1 001697 00 0 0 1 [11] .debug_aranges PROGBITS 00000000 2b0e58 000188 00 0 0 8 [12] .debug_ranges PROGBITS 00000000 2b0fe0 0010e8 00 0 0 8 [13] .debug_frame PROGBITS 00000000 2b20c8 0009b8 00 0 0 4 [14] .debug_loc PROGBITS 00000000 2b2a80 008d36 00 0 0 1 [15] .debug_str PROGBITS 00000000 2bb7b6 0013f7 01 MS 0 0 1 [16] .comment PROGBITS 00000000 2bcbad 000010 01 MS 0 0 1 [17] .note.gnu.gold-ve NOTE 00000000 2bcbc0 00001c 00 0 0 4 [18] .ARM.attributes ARM_ATTRIBUTES 00000000 2bcbdc 00002d 00 0 0 1 [19] .symtab SYMTAB 00000000 2bcc0c 0012d0 10 20 194 4 [20] .strtab STRTAB 00000000 2bdedc 000b5f 00 0 0 1 [21] .shstrtab STRTAB 00000000 2bea3b 0000e0 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific)
위에서 설명한 5번 과정(.comment 섹션과 모든 symbol 및 relocation 정보를 제거)을 거치면 .text, .rodata, .piggydata, .got, .pad의 다섯개 섹션만 남게 됩니다. (남게 된다는 표현보다는, 결과적으로 zImage에 다섯개 섹션만 남아있었습니다.^^)
정말 그런지 한번 확인해보겠습니다.
먼저 arch/arm/boot/zImage의 시작부분과 끝부분을 확인합니다.
$ hexdump arch/arm/boot/zImage | head -n4 0000000 00 00 a0 e1 00 00 a0 e1 00 00 a0 e1 00 00 a0 e1 * 0000020 02 00 00 ea 18 28 6f 01 00 00 00 00 58 26 2a 00 0000030 00 90 0f e1 19 0e 00 eb 01 70 a0 e1 02 80 a0 e1 $ hexdump arch/arm/boot/zImage | tail -n4 02a2630 a4 67 00 00 14 26 2a 00 60 09 00 00 78 26 2a 00 02a2640 74 26 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 02a2650 00 00 00 00 00 00 00 00 02a2658
그리고 arch/arm/boot/compressed/vmlinux의 0x001000 위치(.text섹션의 시작오프셋)와 0x2a3630 위치(.pad섹션의 거의 끝오프셋)를 확인합니다.
$ hexdump -s 0x1000 arch/arm/boot/compressed/vmlinux | head -n4 0001000 00 00 a0 e1 00 00 a0 e1 00 00 a0 e1 00 00 a0 e1 * 0001020 02 00 00 ea 18 28 6f 01 00 00 00 00 58 26 2a 00 0001030 00 90 0f e1 19 0e 00 eb 01 70 a0 e1 02 80 a0 e1 $ hexdump -s 0x2a3630 arch/arm/boot/compressed/vmlinux| head -n4 02a3630 a4 67 00 00 14 26 2a 00 60 09 00 00 78 26 2a 00 02a3640 74 26 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 02a3650 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 *
일치하는군요..
.
이기환님 좋은자료 올료주셔서 감사합니다.
언능 오세요 지금 기다리고 있습니다. :)