본문 바로가기
  • _^**_
무근본 IT 지식 공유/무근본 운영체제(OS)

[무근본 OS 만들기] 현재까지의 과정 ② (부트로더-> 커널 엔트리 포인트-> C언어. Kernel32)

by 크리드로얄워터 2023. 3. 26.
반응형

2. 커널(01. Kernel32)

▶ 디렉터리 구성

 

일주일 전에 정리하던 내용을 다시 정리하겠다.

0x10000 번지 부터 512 바이트의 공간을 차지하는 EntryPoint.bin 에서

0x10200 번지 부터 존재하는 Kernel32.bin으로 넘어와야 할 차례다.

Kernel32.bin은 본격적인 C언어 커널부분이다.

그럼 Kernel32.bin은 어떻게 구성되는가? 를 정리해보고자 한다.

 

① C 코드를 넣는다?

- C 코드는 어셈블리어 코드와 달리 컴파일링크 과정을 거쳐서 최종 결과물이 생성됨

* 컴파일

 - 소스 파일을 중간 단계인 오브젝트 파일로 변환하는 과정으로 소스 파일을 해석하여 코드 영역과 데이터 영역으로 나누고, 이러한 메모리 영역에 대한 정보를 생성하는 단계

* 링크

 - 링크 단계는 오브젝트 파일들의 정보를 취합하여 실행 파일에 통합하며, 필요한 라이브러리 등을 연결해주는 역할을 하는 단계.

 

② 엔트리 포인트가 C 코드를 실행하려면 세 가지 조건을 만족해야 함

 i)  C 라이브러리를 사용하지 않게 빌드해야 함  => 작성된 커널 코드만 사용하도록 빌드

 ii) 0x10200 위치에서 실행하게끔 빌드해야 함  => C로 작성한 커널 부분은 빌드할 때 0x10200 위치에서 실행되는 것을 전제로 해야 함.

    커널이 실행되는 어드레스가 중요한 이유는 선형 주소를 참조하게 생성된 코드나 데이터 때문이다.

    C언어에서 전역 변수의 어드레스나 함수의 어드레스를 참조하는 경우, 실제로 존재하는 선형주소로 변환된다. 따라서 메모리에 로딩되는 어드레스가 변한다면, 이러한 값들 역시 변경해줘야

    정상적으로 동작한다.

 iii) 코드나 데이터 외에 기타 정보를 포함하지 않은 순수한 바이너리 파일 형태여야 함

   => 일반적으로 GCC를 통해 실행 파일을 생성하면 ELF 파일 포맷이나 PE 파일 포맷과 같이 특정 OS에서 실행할 수 있는 포맷으로 생성된다.

      이러한 파일 포맷은 실행하는 데 필요한 코드와 데이터 정보 이외의 불필요한 정보를 포함하고 있다.

 

②-1. 오브젝트 파일 링크 - 라이브러리를 사용하지 않고 특정 어드레스에서 실행 가능한 커널 이미지 파일 생성

 - 섹션 재배치 : 실행 파일이 링크될 때 코드나 데이터 이외에 디버깅 관련 정보와 심볼(함수나 변수의 이름) 정보 등이 포함되기 때문에 해준다.

이러한 정보들은 커널을 실행하는 데 직접적인 관련이 없으므로, 최종 바이너리 파일을 생성할 때 이를 제거하려고 섹션을 재배치하는 것.

섹션을 재배치하여 코드와 데이터를 실행 파일 앞쪽으로 이동시키면 손쉽게 나머지 부분을 제거할 수 있음

* 섹션이란? : 실행 파일 또는 오브젝트 파일에 있으며 공통된 속성(코드, 데이터, 각종 심볼과 디버깅 정보 등)을 담는 영역을 뜻한다.

  실행 파일이나 오브젝트 파일에는 무수히 많은 섹션이 있지만 핵심 역할을 하는 섹션은 세 가지가 있다.

      i)  .text 섹션: 실행 가능한 코드가 들어있는 섹션

      ii) .data 섹션: 초기화 된 데이터가 들어있는 섹션. 전역 변수 혹은 0이 아닌 값으로 초기화된 정적 변수 등을 포함

      iii) .bss 섹션: 초기화되지 않은 데이터가 들어 있는 섹션.

    .data 섹션에 포함되는 데이터와 거의 같으나 초기회되지 않은 변수만 포함한다는 것이 차이점.

     => http://visualworld.tistory.com/86 참조

- 링커의 주된 역할: 오브젝트 파일을 모아 섹션을 통합하고 그에 따라 어드레스를 조정하며, 외부 라이브러리에 있는 함수를 연결해주는 것

                     => 링커스크립트 필요 : 링커 스크립트는 파일 구성에 대한 정보가 들어있다. 각 섹션의 배치 순서와 시작 어드레스, 섹션 크기 정렬

                                                    등의 정보를 저장해 놓은 텍스트 형태의 파일이다.

 

②-2. 로딩할 메모리 어드레스와 엔트리 포인트 지정

- 어셈블리어로 작성된 부트로더나 보호 모드 엔트리 포인트처럼 C 코드 역시 로딩될 메모리를 미리 예측하고 그에 맞춰 이미지를 생성하는 것이 중요.

- 만약 이미지를 로딩할 어드레스에 맞춰서 생성하지 않는다면, 전역 변수와 같이 선형 어드레스를 직접 참조하는 코드는 모두 잘못된 어드레스에 접근하기 때문.

  * 메모리에 로딩하는 어드레스를 지정하는 방법

    i) 링커 스크립트를 수정하는 방법    

    

    ii) 링커(LD) 프로그램의 명령줄 옵션으로 지정하는 방식

c:\> x86_64-pc-linux-ld.exe -Ttext 0x10200 Main.o -o Main.elf

* -Ttext 옵션: .text 섹션의 시작 어드레스 지정

- 엔트리 포인트를 Main으로 지정 역시 두 가지 방법이 있음

   i) 링커 스크립트를 수정하는 방법

   ii) 링커(LD) 프로그램의 명령줄 옵션으로 지정하는 방식

   c:\> x86_64-pc-linux-ld.exe -e Main Main.o -o Main.elf

    * -e Main : Main을 엔트리 포인트로 지정

 

 

 

 

 

반응형

댓글