1. 리눅스 커널 전처리 파일 생성 목적
1.1 전처리 코드 생성 목적
리눅스 커널 소스 코드를 분석하다 보면 수 많은 매크로를 만납니다. 그런데 이 매크로가 소스 분석의 큰 걸림돌입니다. 리눅스 커널에서 캡슐화와 다형성과 객체지향 방식을 구현하다 보니 매크로로 구현된 코드가 많습니다.
전처리 코드는 이 매크로를 모두 풀어서 표현해서 훨씬 편하게 소스 코드를 분석할 수 있습니다. 리눅스 커널 코드를 분석할 때 전처리 코드를 함께 보시기 바랍니다.
전처리 코드는 GCC 컴파일 오브젝트를 생성하는 과정에서 추출됩니다.
2. 전처리 파일 전체 생성방법
2.1 MakeFile 수정
CFLAGS는 gcc의 옵션임.
-Wall : 모든 경고메시지 활성화
-std=gnu11은 C11 표준
-f는 flag나 feature로 예상.
Makefile 파일 421 라인 다음에 아래 코드를 입력하면 됩니다.
-save-temps=obj \
"-save-temps=obj \" 코드를 입력한 후 Makefile은 다음과 같습니다.
417 KBUILD_AFLAGS := -D__ASSEMBLY__
418 KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
419 -fno-strict-aliasing -fno-common -fshort-wchar \
420 -Werror-implicit-function-declaration \
421 -Wno-format-security \
422 -save-temps=obj \
423 -std=gnu89
424 KBUILD_CPPFLAGS := -D__KERNEL__
425 KBUILD_AFLAGS_KERNEL :=
426 KBUILD_CFLAGS_KERNEL :=
427 KBUILD_AFLAGS_MODULE := -DMODULE
Makefile 을 위 방식으로 수정한 다음 이전 절에 소개한 build_RPi_kernel.sh 커널 빌드 스크립트를 실행합시다. 전처리 코드는 out 폴더에 생성됩니다. 전처리 코드가 어떻게 생성됐는지 확인합시다.
커널 스케줄링 공통 코드가 있는 kernel/sched/core.c 파일에 대한 전처리 코드를 찾아 보겠습니다.
root@raspberrypi:/home/pi/RPi_kernel_src/out/kernel/sched# ls -al
total 33692
...
-rw-r--r-- 1 root home 613852 Mar 19 09:35 .tmp_completion.i
-rw-r--r-- 1 root home 20953 Mar 19 09:35 .tmp_completion.s
-rw-r--r-- 1 root home 2800883 Mar 19 09:57 .tmp_core.i
-rw-r--r-- 1 root home 368699 Mar 19 09:57 .tmp_core.s
-rw-r--r-- 1 root home 1262723 Mar 19 09:35 .tmp_cpuacct.i
-rw-r--r-- 1 root home 17772 Mar 19 09:35 .tmp_cpuacct.s
C 포멧 리눅스 커널 소스 파일은 다음 위치에서 전처리 파일로 생성됩니다.
linux/kernel/sched/core.c
out/kernel/sched/.tmp_core.i
소스 파일 이름 앞에 ".tmp_"란 접두사와 가장 마지막에 i가 붙습니다.
그러면 다른 리눅스 커널 소스 코드는 어떻게 전처리 파일로 생성될까요?
linux/init 폴더에 있는 아래 파일을 예로 들겠습니다.
calibrate.c do_mounts.c do_mounts_initrd.c
위 파일들은 전처리 과정으로 out/init 폴더에 다음 이름으로 생성됩니다.
.tmp_calibrate.i .tmp_do_mounts.c .tmp_do_mounts.i .tmp_do_mounts_initrd.i
root@raspberrypi:/home/pi/RPi_kernel_src/out/init# ls -al
total 12912
-rw-r--r-- 1 312538 Mar 19 09:34 .tmp_calibrate.i
-rw-r--r-- 1 10928 Mar 19 09:34 .tmp_calibrate.s
-rw-r--r-- 1 2830878 Mar 19 09:34 .tmp_do_mounts.i
-rw-r--r-- 1 1616189 Mar 19 09:34 .tmp_do_mounts_initrd.i
-rw-r--r-- 1 7311 Mar 19 09:34 .tmp_do_mounts_initrd.s
-rw-r--r-- 1 1621237 Mar 19 09:34 .tmp_do_mounts_rd.i
-rw-r--r-- 1 14425 Mar 19 09:34 .tmp_do_mounts_rd.s
위와 같이 커널 Makefile을 수정해 모든 리눅스 커널 소스 파일을 전처리 코드가 담긴 *.i 파일로 변환할 수 있습니다. 문제는 "*.i" 뿐만 아니라 "*.s" 파일로 생성되 용량이 5GB 까지 커진다는 점입니다.
대부분 우리는 보고 싶은 커널 소스 파일에 대한 전처리 파일을 열어 보는 경우가 많습니다.
이번에 특정 소스 파일만 전처리 파일로 생성하는 방법을 소개합니다.
셸 스크립트는 다음과 같습니다.
[build_preprocess_rpi_kernel.sh]
#!/bin/sh
echo "configure build output path"
KERNEL_TOP_PATH="$( cd "$(dirname "$0")" ; pwd -P )"
OUTPUT="$KERNEL_TOP_PATH/out"
echo "$OUTPUT"
KERNEL=kernel7
BUILD_LOG="$KERNEL_TOP_PATH/rpi_preproccess_build_log.txt"
PREPROCESS_FILE=$1
echo "build preprocessed file: $PREPROCESS_FILE"
echo "move kernel source"
cd linux
echo "make defconfig"
make O=$OUTPUT bcm2709_defconfig
echo "kernel build"
make $PREPROCESS_FILE O=$OUTPUT zImage modules dtbs -j4 2>&1 | tee $BUILD_LOG
위와 같은 코드를 입력한 후 build_preprocess_rpi_kernel.sh 이름으로 저장합시다.
파일을 저장한 후 다음 명령어로 실행 권한을 줍시다.
root@raspberrypi:/home/pi/rpi_kernel_src# chmod +x build_preprocess_rpi_kernel.sh
이전에 소개했던 build_rpi_kernel.sh 빌드 스크립트 코드에 3줄 정도 명령어를 추가했습니다.
12 PREPROCESS_FILE=$1
13 echo "build preprocessed file: $PREPROCESS_FILE"
12~13 번째 줄은 셸 스크립트를 실행할 때 전달하는 소스 코드 이름입니다.
22 번째 줄 코드를 보겠습니다.
22 make $PREPROCESS_FILE O=$OUTPUT zImage modules dtbs -j4 2>&1 | tee $BUILD_LOG
커널 코드를 빌드할 때 "$PREPROCESS_FILE" 구문이 추가됐습니다.
지정한 파일만 전처리 파일로 추출하라는 의도입니다.
이번에 build_preprocess_rpi_kernel.sh 셸 스크립트를 실행하는 방법을 알아봅시다. build_preprocess_rpi_kernel.sh 셸 스크립트를 실행할 때 디렉토리를 포함한 파일 이름을 지정해야 합니다.
build_preprocess_rpi_kernel.sh [파일이름.i]
예를 들어 linux/sched/core.c 파일을 전처리 코드로 추출하려면 다음 형식으로 셸 스크립트를 실행하면 됩니다.
build_preprocess_rpi_kernel.sh linux/sched/core.i
이번엔 라즈베리파이에서 다음 명령어로 실행해 봅시다.
root@raspberrypi:/home/pi/RPi_kernel_src# build_preprocess_RPi_kernel.sh kernel/sched/core.i
configure build output path
build preprocessed file: kernel/sched/core.i
make[1]: Entering directory ' root@raspberrypi:/home/pi/RPi_kernel_src/out '
GEN ./Makefile
#
# configuration written to .config
#
make[1]: Leaving directory '/home/pi/RPi_kernel_src/out'
make[1]: Entering directory '/home/pi/RPi_kernel_src/out'
GEN ./Makefile
scripts/kconfig/conf --silentoldconfig Kconfig
CHK include/config/kernel.release
GEN ./Makefile
CHK include/generated/uapi/linux/version.h
Using /home/pi/RPi_kernel_src/linux as source for kernel
CHK include/generated/utsrelease.h
CHK scripts/mod/devicetable-offsets.h
CHK include/generated/timeconst.h
CHK include/generated/bounds.h
CHK include/generated/asm-offsets.h
CALL /home/pi/RPi_kernel_src/linux/scripts/checksyscalls.sh
CHK include/generated/compile.h
CPP kernel/sched/core.i
GZIP kernel/config_data.gz
CHK kernel/config_data.h
Kernel: arch/arm/boot/Image is ready
Building modules, stage 2.
Kernel: arch/arm/boot/zImage is ready
MODPOST 1506 modules
make[1]: Leaving directory '/home/pi/RPi_kernel_src/out'
제대로 전처리 파일을 생성하면 위와 같은 빌드 메시지를 볼 수 있습니다.
out/kernel/sched 디렉토리로 가면 core.i 파일만 전처리 코드로 생성된 것을 확인할 수 있습니다.
root@raspberrypi:/home/pi/RPi_kernel_src/out/kernel/sched# ls
autogroup.o clock.o core.i cpuacct.o cpufreq.o cpupri.o
소스 코드 디렉토리를 잘못 지정하면 다음 에러 메시지와 함께 빌드가 중단됩니다.
austin.kim@LGEARND20B15:~/src/book_RPi_kernel$ ./build_preprocess_RPi_kernel.sh sched/core.i
configure build output path
build preprocessed file: sched/core.i
make[1]: Entering directory '/home001/austin.kim/src/book_RPi_kernel/out'
GEN ./Makefile
#
# configuration written to .config
#
make[1]: Leaving directory '/home/pi/RPi_kernel_src/out'
make[1]: Entering directory '/home/pi/RPi_kernel_src/out'
GEN ./Makefile
scripts/kconfig/conf --silentoldconfig Kconfig
make[1]: *** No rule to make target 'sched/core.i'. Stop.
make[1]: Leaving directory '/home/pi/RPi_kernel_src/out'
Makefile:146: recipe for target 'sub-make' failed
make: *** [sub-make] Error 2
이 셸 스크립트를 실행할 때는 디렉토리와 소스 파일을 이름을 정확히 지정해야 합니다.
출처: Austin Kim 블로그
'SoC : : Architecture > : : Raspberry' 카테고리의 다른 글
(2) 디버깅과 코드 학습 능력 (0) | 2024.10.10 |
---|---|
(1) 디버깅은 문제 해결 능력의 지름길 (0) | 2024.10.10 |
Kernel Source 구조 (1) | 2024.10.10 |
Raspbian - 리눅스 커널 소스코드 다운로드, 빌드, 설치 (0) | 2024.05.06 |
라즈베리파이(Raspberry pi) 기본 셋팅 (0) | 2024.04.27 |