[RISC-V] RISC-V 툴체인으로 리눅스 커널 빌드하기
이번 포스트에서는 RISC-V 툴체인을 설치해 리눅스 커널을 빌드하는 방법을 소개합니다.
먼저 RISC-V 툴체인을 설치하는 명령어를 입력합시다.
<< RISC-V 툴체인 소스를 내려받기 >>
다음 명령어를 입력해 RISC-V 툴체인 소스를 내려받습니다.
$ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain
아래는 리눅스 터미널에서 위 명령어를 입력한 후의 출력 결과입니다. 소스를 내려받는데 1시간 정도 걸리네요.
austindh.kim:~/src/risc-v_toolchain$ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain
Cloning into 'riscv-gnu-toolchain'... remote: Enumerating objects: 21, done. remote: Counting objects: 100% (21/21), done. remote: Compressing objects: 100% (14/14), done. remote: Total 7795 (delta 7), reused 16 (delta 4), pack-reused 7774 Receiving objects: 100% (7795/7795), 4.75 MiB | 970.00 KiB/s, done. Resolving deltas: 100% (3940/3940), done. Submodule 'qemu' (<a href="https://git.qemu.org/git/qemu.git" rel="nofollow">https://git.qemu.org/git/qemu.git</a>) registered for path 'qemu' Submodule 'riscv-binutils' (<a href="https://github.com/riscv/riscv-binutils-gdb.git" rel="nofollow">https://github.com/riscv/riscv-binutils-gdb.git</a>) registered for path 'riscv-binutils' Submodule 'riscv-dejagnu' (<a href="https://github.com/riscv/riscv-dejagnu.git" rel="nofollow">https://github.com/riscv/riscv-dejagnu.git</a>) registered for path 'riscv-dejagnu' Submodule 'riscv-gcc' (<a href="https://github.com/riscv/riscv-gcc.git" rel="nofollow">https://github.com/riscv/riscv-gcc.git</a>) registered for path 'riscv-gcc' Submodule 'riscv-gdb' (<a href="https://github.com/riscv/riscv-binutils-gdb.git" rel="nofollow">https://github.com/riscv/riscv-binutils-gdb.git</a>) registered for path 'riscv-gdb' ...
시간이 오래 걸리니 밥 먹기 전에 명령어를 입력해 놔야 겠습니다.
<< RISC-V 툴체인 소스 빌드하고 설치하기 >>
소스를 전부 내려받은 다음에 아래와 같이 디렉터리를 생성합니다.
$ mkdir -p opt/riscv $ mkdir build $ cd build $ ../configure --prefix=/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv --enable-multilib
아래는 리눅스 터미널에서 위 명령어를 실행한 후 출력 결과입니다. 빌드되는데 2시간 정도가 소요됩니다.
austindh.kim:~/src/risc-v_toolchain$ mkdir -p opt/riscv austindh.kim:~/src/risc-v_toolchain$ mkdir build austindh.kim:~/src/risc-v_toolchain$ cd build austindh.kim:~/src/risc-v_toolchain/build$ ../configure --prefix=/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv --enable-multilib ... make[4]: Entering directory '/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/build/build-gdb-linux/libctf' make[4]: Leaving directory '/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/build/build-gdb-linux/libctf' make[3]: Leaving directory '/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/build/build-gdb-linux/libctf' make[2]: Nothing to be done for 'install-target'. make[2]: Leaving directory '/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/build/build-gdb-linux' make[1]: Leaving directory '/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/build/build-gdb-linux' mkdir -p stamps/ && touch stamps/build-gdb-linux austindh.kim:~/src/risc-v_toolchain/riscv-gnu-toolchain/build$
빌드가 끝나고 "~src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv/bin" 디렉터리로 이동하니, 다음과 같은 파일이 생성됐음을 확인할 수 있습니다.
austindh.kim:~/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv/bin$ ls riscv64-unknown-linux-gnu-addr2line riscv64-unknown-linux-gnu-gcc riscv64-unknown-linux-gnu-gdb riscv64-unknown-linux-gnu-objcopy ... riscv64-unknown-linux-gnu-elfedit riscv64-unknown-linux-gnu-gcov-dump riscv64-unknown-linux-gnu-lto-dump riscv64-unknown-linux-gnu-strings riscv64-unknown-linux-gnu-g++ riscv64-unknown-linux-gnu-gcov-tool riscv64-unknown-linux-gnu-nm riscv64-unknown-linux-gnu-strip
이제 RISC-V 툴체인 소스 빌드를 마무리했습니다.
<< RISC-V 툴체인으로 리눅스 커널 빌드하기>>
다음 명령어를 입력해 리눅스 커널 소스 코드를 내려 받습니다.
$ git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/next/linux-next
소스를 내려 받은 다음에 확인한 디렉터리 정보는 다음과 같습니다.
austindh.kim:~/src/dev_kernel/59_linux_kernel$ ls linux-next
'riscv_kernel_build.sh' 이름으로 셸 스크립트 파일을 생성한 다음에, 아래 빌드 스크립트를 입력합니다.
#!/bin/bash export PATH=$PATH:/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv/bin echo "configure build output path" TOP_PATH=$( cd "$(dirname "$0")" ; pwd ) OUTPUT="$TOP_PATH/out" BUILD_LOG="$TOP_PATH/rpi_build_log.txt" OUTPUT_PATH=$( cd "$(dirname "$0")" ; pwd ) OUTPUT="$OUTPUT_PATH/out" pushd linux-next > /dev/null # configure defconfig make ARCH=riscv O=$OUTPUT CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig -j16 2>&1 # build kernel with riscv tool-chain make ARCH=riscv O=$OUTPUT CROSS_COMPILE=riscv64-unknown-linux-gnu- modules dtbs -j16 2>&1 | tee $BUILD_LOG popd > /dev/null <code> 위 빌드 스크립트에서 가장 중요한 명령어는 아래와 같습니다. <code> # configure defconfig make ARCH=riscv O=$OUTPUT CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig -j16 2>&1 # build kernel with riscv tool-chain make ARCH=riscv O=$OUTPUT CROSS_COMPILE=riscv64-unknown-linux-gnu- modules dtbs -j16 2>&1 | tee $BUILD_LOG
'arch/riscv/configs/defconfig' 파일을 다음과 같이 수정해 vmlinux에 디버깅 심벌이 추가되도록 합시다.
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index d58c93e..6ea8e83 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig @@ -20,6 +20,7 @@ CONFIG_SMP=y CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y +CONFIG_DEBUG_INFO=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y
'riscv_kernel_build.sh' 빌드 셸 스크립트를 실행해, RISCV 툴 체인으로 커널을 빌드합니다.
아래는 'riscv_kernel_build.sh' 빌드 셸 스크립트를 터미널에서 실행한 출력 화면입니다.
austindh.kim:~/src/dev_kernel/59_linux_kernel$ ./riscv_kernel_build.sh configure build output path make[1]: Entering directory '/home001/austindh.kim/src/dev_kernel/59_linux_kernel/out' GEN Makefile HOSTCC scripts/basic/fixdep HOSTCC scripts/kconfig/conf.o ... KSYMS .tmp_vmlinux.kallsyms2.S AS .tmp_vmlinux.kallsyms2.S LD vmlinux SYSMAP System.map MODPOST Module.symvers CC [M] fs/nfs/flexfilelayout/nfs_layout_flexfiles.mod.o LD [M] fs/nfs/flexfilelayout/nfs_layout_flexfiles.ko
'out' 폴더를 가니 제대로 커널이 빌드됐음을 확인할 수 있습니다.
austindh.kim:~/src/dev_kernel/59_linux_kernel/out$ ls arch crypto include kernel mm modules.order scripts source virt vmlinux.symvers block drivers init lib modules.builtin Module.symvers security System.map vmlinux certs fs ipc Makefile modules.builtin.modinfo net sound usr vmlinux.o
<< RISC-V 바이너리 유틸리티 사용해보기 >>
이번엔 다음 명령어를 입력해 vmlinux의 셉션 정보를 확인해보겠습니다.
$ ./riscv64-unknown-linux-gnu-objdump -x vmlinux | more
아래는 './riscv64-unknown-linux-gnu-objdump -x vmlinux | more' 빌드 셸 스크립트를 터미널에서 실행한 출력 화면입니다.
austindh.kim:~/src/dev_kernel/59_linux_kernel/out$ ./riscv64-unknown-linux-gnu-objdump -x vmlinux | more vmlinux: file format elf64-littleriscv vmlinux architecture: riscv:rv64, flags 0x00000112: EXEC_P, HAS_SYMS, D_PAGED start address 0xffffffe000000000 Program Header: LOAD off 0x0000000000001000 vaddr 0xffffffe000000000 paddr 0x0000000000000000 align 2**12 filesz 0x0000000000025af4 memsz 0x0000000000025af4 flags r-x LOAD off 0x0000000000027000 vaddr 0xffffffe000026000 paddr 0x0000000000026000 align 2**12 filesz 0x0000000000019de8 memsz 0x0000000000019de8 flags rwx LOAD off 0x0000000000041000 vaddr 0xffffffe000200000 paddr 0x0000000000200000 align 2**12 filesz 0x00000000006ce0a2 memsz 0x00000000006ce0a2 flags r-x LOAD off 0x0000000000710000 vaddr 0xffffffe000a00000 paddr 0x0000000000a00000 align 2**12 filesz 0x000000000022a9fc memsz 0x000000000022a9fc flags rw- LOAD off 0x000000000093b000 vaddr 0xffffffe000e00000 paddr 0x0000000000e00000 align 2**12 filesz 0x0000000000002400 memsz 0x0000000000002400 flags r-- LOAD off 0x000000000093e000 vaddr 0xffffffe001000000 paddr 0x0000000001000000 align 2**12 filesz 0x00000000000e19b4 memsz 0x0000000000131920 flags rw- NOTE off 0x000000000093a9c0 vaddr 0xffffffe000c2a9c0 paddr 0x0000000000c2a9c0 align 2**2 filesz 0x000000000000003c memsz 0x000000000000003c flags r-- STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4 filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
출력 결과를 보니 아키텍처의 정보는 'riscv:rv64'이고 스타트업 코드의 위치는 0xffffffe000000000 주소임을 알 수 있습니다.
(개인블로그)
http://rousalome.egloos.com/
댓글 달기