카테고리 없음

mikanos day03 오류 수정

MongHwa 2024. 10. 9. 20:05

[0부터 시작하는 OS 자작 입문] 3장은 "화면표시 연습과 부트로더"로, 부트로더뿐만 아니라 커널을 개발하기 시작하여 부트로더 및 커널을 기동하는 것을 목표로 하고 있습니다. 다양한 내용을 다루고 있습니다만, 여기서 핵심적인 내용을 하나 뽑아보라 하면, 부트로더 Loader.efi에서 커널 Kernel.elf로 진입하는 부분이라고 할 수 있는데요. 어찌된 일인지 책의 내용을 그대로 테스트하면, 책과는 조금 다른 현상이 발생합니다. 
 
 
 
[readelf 명령 후]

중요한 부분은 Entry point address. 커널 파일을 링크 시킬 때 ld.lld 옵션에 --img-base 0x100000을 지정하였기 때문에 그 근처의 값이 나와야 합니다. 다만 책에서는 0x101000으로, 제 실행환경에서는 0x1011b0으로 다른 부분이 나타납니다. 실행 환경의 메모리 상황 상 달라질 수 있다고 넘기면 다음 문제에 봉착하는데,
 
 
[edk2 빌드 이후 QEMU 실행]

부트로더의 소스코드인 Main.c에서의 Print(L"All done\n"); 이 실행되지 않는 것으로 보아 정상적으로 실행된 것처럼 보이지만, 책에서도 언급한 것처럼 커널에서 제대로 halt(hlt)되지 않았을 수도 있기 때문에 QEMU 상에서 레지스터 값을 확인해보도록 합니다.
 
[info registers 명령으로 레지스터 확인]

중요한 레지스터는 RIP인데 어찌된 건지 책에서와 다른 주소가 대입되어 있습니다. 실행환경의 차이일까 생각해보아도 x 명령으로 어셈블리어를 뜯어보면 전혀 다른 엉뚱한 명령어(cmpq)가 대입되어 있다는 것을 알 수 있습니다. 성공적으로 커널로 들어와 halt(hlt)되고 있지 않음을 알 수 있죠.
 
 
 
 
 
[해결 방법]
책의 공식 지원사이트의 issues를 확인해보니 이미 몇몇 분들이 이 문제 상황에 대하여 도움을 구하고 있었습니다. 확인해보니 Clang과 lld의 버전으로 인한 오류가 의심되었고(참고1), 실험 결과 lld의 버전을 14에서 7로 낮추면 해결됨을 알 수 있었습니다(참고1, 참고2)
 
참고2의 댓글에서도 알 수 있듯, 기존 Clang과 lld를 삭제하는 맨 윗줄을 제외한 코드 3줄만 실행하여 lld7을 설치해줍니다. 다시 kernel.elf를 생성하는데, 기존 ld.lld를 방금 설치했던 lld7의 파일 위치로 수정하여 작성한 뒤 생성하도록 합니다. (이는 4장의 Makefile에서도 동일한 방법으로 하면 됩니다.)

 
QEMU를 전처럼 동일하게 실행한 뒤 레지스터를 확인해봅시다.

 
드디어..!