[Linux] QEMU + busybox 로 커널 디버깅

문연수·2025년 7월 5일
0

Linux (Fedora)

목록 보기
28/28
post-thumbnail

 이전에는 buildroot 으로 rootfs 를 만들어 QEMU 로 커널을 디버깅했다. 하지만 커널 디버깅만 하기에 buildroot 는 너무 무겁다. (빌드도 오래 걸리고 부팅 시간도 길다.) 따라서 이번에는 busybox 를 통해 minimal 한 rootfs 를 구성한 뒤, 이를 QEMU 로 디버깅 해볼 것이다.

1. busybox 다운로드 받기

https://busybox.net/downloads/?C=M;O=D

 위 링크로 들어가면 busybox 를 다운로드 받을 수 있다. 필자는 Last modified 로 정렬해서 (글을 작성하는 시점인 25년 07월 05일 기준) 가장 최신 버전인 busybox-1.37.0.tar.bz2 를 다운로드 받았다.

wget https://busybox.net/downloads/busybox-1.37.0.tar.bz2
tar -xf busybox-1.37.0.tar.bz2
rm busybox-1.37.0.tar.bz2
mv busybox-1.37.0 busybox

압축을 풀고 압축파일을 삭제하였다.

2. 빌드 환경 구성하기 (sysroot)

 필자는 arm64 커널을 디버깅 할 예정이기 때문에 rootfs 의 바이너리도 aarch64 로 빌드해야 한다. 필자의 호스트 머신은 x86_64 이므로 크로스 컴파일이 필요하다. 여기서부터는 배포판마다 진행 과정이 약간씩은 다를 수 있으나 큰 줄기는 같다. 필자는 Fedora Linux 42 (Workstation Edition) x86_64 를 기준으로 서술한다.

sudo dnf install gcc-aarch64-linux-gnu gcc-c++-aarch64-linux-gnu
sudo dnf install binutils-aarch64-linux-gnu
sudo dnf install sysroot-aarch64-fc42-glibc

busybox 를 빌드하기 위해선 sysroot 패키지가 필요한데 여기에서 sysroot 이란, 크로스 컴파일 툴체인이 default 로 인식하는 headerlibrary 의 논리적인 root directory 를 의미한다. (출처: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html)

Fedora 의 경우, aarch64-linux-gnuaarch64-redhat-linux 의 경로와 통합되어 있지 않기 때문에 직접 sys-root 을 이어줘야 한다. 어찌보면 이러한 패키지 디렉토리 구조가 sysroot 의 취지에 잘 들어맞는다고 볼 수도 있다.

ln -s /usr/aarch64-redhat-linux/sys-root/fc42/usr /usr/aarch64-redhat-linux/sys-root/usr
ln -s /usr/aarch64-redhat-linux/sys-root /usr/aarch64-linux-gnu/sys-root

3. 빌드하기, 전에 버그 수정

mkdir build
make O=build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig

 우선 defconfig 명령어를 입력하고 몇 가지 에러를 수정해야 한다. 가장 먼저 해야 하는 일은 menuconfig 에서 발생하는 버그를 수정하는 것이다.

 이것은 ncurses-devel 패키지를 설치해도 발생하는 문제로 scripts/kconfig/lxdialog/check-lxdialog.sh 라는 쉘 스크립트의 내용을 수정해야 해결할 수 있다. 50번째 라인을 아래와 같이 수정한다:

make O=build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig

수정한 뒤에 menuconfig 을 입력하면 정상적으로 다이얼로그가 나오는 것을 확인할 수 있다.

 그 다음으로 할 일은 몇 가지 설정을 변경하는 것이다:

  • Networking Utilities -> tc [ ]
  • Settings -> Build static binary (no shared libs) [*]
  • Settings -> SHA1 [ ] : Use hardware accelerated instructions if possible
  • Settings -> SHA256 [ ] : Use hardware accelerated instructions if possible

다음과 같이 언/체크한다.

networking/tls_aesgcm.c 파일에 9~11 번 라인을 추가로 작성해준다. LONG_BIT 가 정의되지 않아서 발생하는 문제인데 그냥 직접 정의해도 별 문제 없다.

4. 빌드 및 rootfs 생성

make O=build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-

 경고가 조금 발생하긴 하지만 빌드는 문제없이 잘 된다. 이제 make install 을 통해 rootfs 를 생성하면 된다.

make O=build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CONFIG_PREFIX=install/ install

이제 build/install 디렉토리로 들어가면 bin, linuxrc, sbin, usr 디렉토리를 확인할 수 있다.

5. initramfs 만들기

이제 이 rootfs 에 몇 가지 파일과 디렉토리를 추가해볼 것이다.

mkdir proc sys dev etc etc/init.d

ln -s bin/busybox init

touch etc/init.d/rcS
chmod +x etc/init.d/rcS

etc/init.d/rcS 파일의 내용을 이하와 같이 구성한다:

#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys

exec /bin/sh

최종적으로 다음과 같이 구성하면 끝난다. 이제 이 파일들을 그러모아서 하나의 initramfs 파일을 만들면 된다.

find . | cpio -o -H newc | gzip > ../../initramfs.cpio.gz

6. QEMU 로 실행하기

qemu-system-aarch64 -M virt -cpu cortex-a57 -kernel <Image> -nographic -initrd <initramfs.cpio.gz>

끝!

profile
2000.11.30

0개의 댓글