망고 100 보드로놀아보자 -10 Kernel build 분석 http:// http://www.mangoboard.com
커널 build 환경분석 >(Top Dir)/Makefile 첫번째라인에위치 > 커널 2.6.29 버전사용 >ARCH?=arm 의미는 ARCH 의값으로 arm 있느냐묻고, 없으면, arm 문자를대입 >.cross_compile 이있으면,.cross_compile 내용을 CROSS_COMPILE 로사용
커널 build 환경분석 (Conf) #make mango100_android_defconfig 실행시 Scripts/kconfig/Makefile 에서아래코드수행 %_defconfig: $(obj)/conf $(Q)$< -D arch/$(srcarch)/configs/$@ $(Kconfig) make D arch/arm/configs/mango100_android_defconfig.config 파일생성
커널 build 환경분석 (Conf) #make menu_config 명령실행시 #make scripts/kconfig menuconfig 이실행됨 menuconfig: $(obj)/mconf $< $(Kconfig).config 저장
커널 build 환경분석 (Conf) #make xconfig (QT3 Package 필요 ) #yum install qt* 명령으로설치 cannot find lxi 에러발생시 #yum install libxi 실행
커널 build 실행분석 $(TOP)/Makefile 최상위 Makefile vmlinux 와 modules 생성.config 커널설정파일 make [config menuconfig xconfig] 를통해생성. arch/$(arch)/makefile - 아키텍처별 makefile scripts/makefile.* - 모든 kbuild Makefile 에사용되는규칙이들어있는파일 kbuild Makefiles 약 500 개정도가있다.
커널 build 실행분석 1. 커널설정 (make config menuconfig xconfig).config 를만듬 2. 커널버전을 include/linux/version.h 에저장 3. include/asm-$(arch) 에대한심볼릭링크만듬 4. arch/$(arch)/makefile 에서정의된, 그외의타겟빌딩을위한모든종속리스트를준비 5. init-*, core-*, driver-*, net-* 등의타겟등을만듬 6. 모든오브젝트들이링크되고, 소스트리의루트디렉토리에 vmlinux 를만듬. 7. 최종부트이미지 (zimage) 를만들기위한아키텍처에따른부분이실행됨
Built-in object goals (obj-y) specifying object files for vmlinux $(LD) r : to merge $(obj-y) files into one built-in.o file ex. $(TOP)/kernel/Makefile./arch/arm/xxx/built-in.o /drivers/built-in.o /drivers/xxx/built-in.o vmlinux./firmware/built-in.o./fs/built-in.o./kernel/built-in.o./fs/xxx/built-in.o 컴파일후 #find. name built-in.o 명령으로확인./lib/built-in.o
Built-in object goals (obj-y) echo "(patsubst pattern,replacement,text)" vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ $(net-y) $(net-m) $(libs-y) $(libs-m))) vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \ $(init-n) $(init-) \ $(core-n) $(core-) $(drivers-n) $(drivers-) \ $(net-n) $(net-) $(libs-n) $(libs-)))) init-y core-y drivers-y net-y libs-y1 libs-y2 libs-y := $(patsubst %/, %/built-in.o, $(init-y)) := $(patsubst %/, %/built-in.o, $(core-y)) := $(patsubst %/, %/built-in.o, $(drivers-y)) := $(patsubst %/, %/built-in.o, $(net-y)) := $(patsubst %/, %/lib.a, $(libs-y)) := $(patsubst %/, %/built-in.o, $(libs-y)) := $(libs-y1) $(libs-y2)
Loadable module goals (obj-m) object files which are built as loadable kernel modules. ex. $(TOP)/driver/scsi/Makefile ex. $(TOP)/.config 참고!! 커널에포함되지않은 external module 을컴파일하기위해서는 Documentation/kbuild/modules.txt 를참조 디바이스드라이버 개발
Environment Variables variable value Description V 0 빌드시에, 현재컴파일되는파일명만을보여줌. (default) V 1 빌드시에실행되는모든명령및메시지를보여 줌. O dir 컴파일되는모든 output file들을 dir에저장되게 지정 C 1 빌드과정에서 sparse tool이컴파일된파일을체 크하게끔한다. sparse은커널소스파일의프로 그래밍에러를찾는툴이다. C 2 sparse tool은컴파일에관계없이모든파일을 체크하게끔한다. Example :# make V=1 ARCH=arm
커널빌드시, 명령및메시지출력옵션 $(top)/makefile 커널빌드시, 소스코드체크옵션 빌드된파일의출력디렉토리지정
How to build vmlinux?? -Makefile : 아키텍처독립적인부분 - arch/arm/makefile : 아키텍처종속적인부분
Building vmlinux vmlinux는 $(vmlinux-init) 와 $(vmlinux-main) 에서정의된오브젝트로만들어진다. 링커스크립트지정 각오브젝트의 linking 순서가중요. ld [ 옵션 ] 오브젝트파일.. -m : 어떤포맷으로출력물을만들것인가?? -T: 링커스크립트지정 --start-group ~ --end-group : ~ 에지정된오브젝트들서로간에변수나함수참조를가능하게함. -o : 출력파일명지정 $(vmlinux-init) $(head-y) $(init-y) vmlinux $(vmlinux-main) $(core-y) $(libs-y) $(drivers-y) $(net-y) kallsyms.o
Building zimage (1/3) 1. arch/arm/boot/compressed/image $(topdir)/vmlinux 에서.note 섹션,.comment 섹션및모든심볼들과재배치정보들을제거한후, 인스트럭션데이터만을뽑아, arch/arm/boot/compressed/image 라는바이너리파일을만든다. arm-linux-objcopy -O binary -R.note -R.note.gnu.build-id -R.comment -S vmlinux arch/arm/boot/image objcopy [ 옵션 ] 입력파일 [ 출력파일 ] -O오브젝트형식: 어떤오브젝트형식으로출력파일을만들것인지지정 ( 예 : elf32-i386, binary) -R 섹션 : 출력파일에서해당섹션을지운다. -S : 입력파일의재배치정보와심볼정보를출력파일에복사하지않는다. 2. arch/arm/boot/compressed/piggy.gz 1 단계에서만든, Image 을가장압축률이좋은방법으로압축해서 (-9), piggy.gz 을만듬 gzip -f -9 < arch/arm/boot/compressed/../image > arch/arm/boot/compressed/piggy.gz
Building zimage (2/3) 3. arch/arm/boot/compressed/piggy.o arm-linux-gcc -Wp,-MD,arch/arm/boot/compressed/.piggy.o.d -nostdinc -isystem /usr/local/arm/4.2.2-eabi/usr/bin-ccache/../lib/gcc/arm-unknown-linux-gnueabi/4.2.2/include -Iinclude -I/home/icanjji/work/mango100/mango100_kernel_2010_06_30/arch/arm/include -include include/linux/autoconf.h -D KERNEL -mlittle-endian -Iarch/arm/mach-s5pc100/include -Iarch/arm/plat-s5pc1xx/include -Iarch/arm/plat-s3c/include -D ASSEMBLY -mabi=aapcs-linux -mno-thumb-interwork -D LINUX_ARM_ARCH =7 -march=armv5t -Wa,-march=armv7-a -msoft-float -gdwarf-2 -Wa,-march=all -c -o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/piggy.s 4. arch/arm/boot/compressed/vmlinux head.o + misc.o + piggy.o 를링킹해서, vmlinux 를만듬, 이때.text 섹션은 0x20008000 위치부터, 엔트리포인트는 startup_32 로지정한다. ld [ 옵션 ] 오브젝트파일.. -m emulation : 링커에게해당타겟 emulation 에맞는정보를제공 ( 예. 링커스크립트등 ) -r : 재할당가능한출력파일을생성. 즉, ld 의입력오브젝트로쓰일수있는출력파일을생성. ( 실제로 piggy.o 는 ld 로다시링킹됨 ) --format input-format : 입력오브젝트파일의형식지정 --oformat output-format : 출력오브젝트파일의형식지정. -o : 출력파일명지정 -Ttext org : text 섹션의시작주소를 org로지정 -e entry : 엔트리포인트를지정한다.
Building zimage (3/3) 5. arch/arm/boot/zimage 4 단계에서만든 vmlinux 에서.note 섹션,.comment 섹션및모든심볼들과재배치정보들을제거한후, 인스트럭션데이터만을뽑아, arch/arm/boot/zimage 라는바이너리파일을만든다. arm-linux-objcopy -O binary -R.note -R.note.gnu.build-id -R.comment -S arch/arm/boot/compressed/vmlinux arch/arm/boot/zimage
결론 - Kernel Build Process arch/arm/boot/compressed arch/arm/boot 45M head.o misc.o 5M objcopy gzip 압축 3M piggy.o linking 3M objcopy 3M vmlinux 인스트럭션과데이터부분외의기타섹션은모두삭제 Image Piggy.gz ELF Object Binary Object vmlinux 인스트럭션과데이터부분외의기타섹션은모두삭제 zimage
참고 : kernel Makefile 계층도 all make silentoldconfig vmlinux zimage arch/arm/boot/makefile 에서 make zimage 를다시수행 $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsysms.o) $(obj) = arch/arm/boot zimage $(vmlinux-dirs) init usr kernel mm fs ipc security crypto block drivers sound net lib prepare prepare0 archpare arch/arm/kernel arch/arm/mm arch/arm/crypto include/config/auto.conf include/config/kernel.release prepare1 prepare2 prepare3 scripts_basic include/linux/version.h include/linux/utsrelease.h include/asm $(obj) = arch/arm/boot/compressed $(obj)/compressed/vmlinux $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o $(obj)/piggy.gz $(obj)/image vmlinux 여기에서 vmlinux 는커널소스최상위디렉토리에서만들어진 vmlinux 를말한다.
vmlinux.lds 첫부분. OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS {. = 0; _text =.;.text : { _start =.; *(.start) *(.text) *(.text.*) *(.fixup) *(.gnu.warning) *(.rodata) *(.rodata.*) *(.glue_7) *(.glue_7t) *(.piggydata). = ALIGN(4); } Start entry 포인트는 _start
( 예제 ) readelf -l arch/arm/boot/compressed/vmlinux
참고 : 커널빌드시, Log 남기기 make V=1 ARCH=arm 2>&1 tee log-kernel.txt