시작

이번에 qemu를 이용해서 risc-v에서 돌아가는 xv6이라는 운영체제에 대해서 공부하고있는데요. 문제는 현재 맥에서 xv6를 돌리다보니 gdb를 이용해서 디버깅할 수 없다는 것이었습니다. 저는 리눅스 컴퓨터가 없는 관계로 utm으로 리눅스 가상머신을 돌리거나 도커를 이용해야했는데 도커가 훨씬 간편하게 돌릴 수 있을 것 같아 도커에 우분투를 설치하고, 거기서 GDB를 이용하여 xv6를 디버깅하기로 결정했습니다!

진행

컨테이너 만들기

우선 도커 컨테이너를 만들었습니다. 지금은 간단하게 디버깅용으로 사용할 우분투 환경이 필요한 것이니 따로 dockerfile이나 docker-compose같은 것은 구성하지 않고 바로 도커 컨테이너를 만들었습니다.

docker run -it -v ~/xv6-riscv-snu:/os --name os ubuntu /bin/bash

이렇게하면 ubuntu 이미지를 이용하여 도커 컨테이너가 생성됩니다. 그 후 /os 폴더와 제 컴퓨터의 ~/xv6-riscv-snu 경로가 볼륨으로 연결됩니다. 그리고 터미널을 통해서 컨테이너에 바로 접근할 수 있죠.

환경 세팅

이후 환경 세팅을 진행해줍니다. 우선은 gcc, vim, gdb정도만 있으면 되겠죠.

apt update
apt-get install gcc vim gdb

진행

제 원래 컴퓨터에는 ~/xv6-riscv-snu 폴더 안에 모든 xv6관련 코드들이 다 있었는데 이 폴더는 지금 도커와 볼륨으로 연결되어있으니 도커 안에서 /os로 접근하면 똑같은 내용을 볼 수 있겠죠? 컨테이너 안에서는 추가적으로 qemu만 설치해주면 되겠습니다.

{{ }}

그러면 이제 우선 os폴더 안에서 make qemu-gdb를 통해서 디버깅할 준비를 해주고 다른 터미널 창에서 gdb kernel/kernel을 입력하고 포트 번호를 입력해 디버깅을 시작해줍니다.

{{ }}

아래는 디버깅을 진행하는 영상입니다. 디버깅 진행 시 사용되는 명령어는 다음과 같습니다.

  • b : breakpoint, 멈출 지점을 정합니다.
  • c : continue, 다음 breakpoint까지 진행합니다.
  • s : step, 한 줄씩 넘어갑니다. 함수를 만나면 내부로 진입합니다.
  • si : stepi, 기계어 단위로 한 줄씩 명령어를 실행합니다.

영상 속 내용은 time이라는 제 custom system call을 만들었는데, 이 시스템 콜안에서 ecall이라는 trap을 발생시켰을 때 어디로 뛰게되는지 보려고 한 것이고, mtvec으로 설정된 timervec으로 뛰는 것을 확인하는 영상입니다. 관련 내용은 제 다른 시스템 콜 관련 글에서 확인하실 수 있습니다.