반응형

현재 까지 만든 보호 모드의 커널은 엔트리 포인트 소스 파일 하나로 구성되어 있고, 512 바이트로 정렬 되어 OS 이미지 파일에 결합되는 구조를 하고 있다.


이번 포스팅에서는 C 소스 파일을 추가하고, 이를 빌드하여 보호 모드 커널 이미지에 통합할 것이다.


~>C 코드는 어셈블리어 코드와 달리 '컴파일'과 '링크 과정'을 거쳐서 최종 결과물이 생성된다.


컴파일

-소스 파일을 중간 단계인 Object File로 변환하는 과정

-소스 파일을 해석하여 코드 영역과 데이터 영역으로 나눈다.

-이러한 메모리 영역에 대한 정보를  생성하는 단계


그렇다고 C 코드를 빌드해서 합치기만 한다고 보호 모드 엔트리 포인트가 뒷부분의 커널을 실행할 수 있는 것은 아니다.


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

1.C 라이브러리를 사용하지 않게 빌드해야 한다(-ffreestanding 옵션 추가)

~> 부팅된 후 보호 모드 커널이 실행되면 C 라이브러리가 없으므로 라이브러리에 포함된 함수를 호출할 수 없음

~>커널은 자신을 실행하기 위한 최소한의 환경만 설정해서 라이브러리 함수가 정상적으로 실행되지 않는다.


2. 0x10200 위치에서 실행하게끔 빌드해야 한다

~> 0x10000 위치는 이전 포스팅에서 작성했던 한 섹터 크기의 보호 모드 엔트리 포인트가 있으니까 결합된 C 코드는 512바이트 이후인 0x10200의 위치부터 로딩된다.

~>그래서 커널 부분을 빌드할 때 0x10200 위치에서 실행되는 것을 전제로 해야 하고, 해당 위치의 코드는 C 코드 중 가장 먼저 실행되어야 하는 함수가 위치해야 한다.

*커널이 실행되는 어드레스가 중요한 이유

선형 주소를 참조하게 생성된 코드나 데이터 때문

~>C언어에서 전역 변수의 어드레스나 함수의 어드레스를 참조하는 경우 실제로 존재하는 선형 주소로 변환된다.


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


이제부터 오브젝트 파일을 링크해 실행파일을 만들건데 , 그 이전에 실행 파일을 구성하는 섹션의 배치와 로딩될 어드레스, 코드 내에서 가장 먼저 실행될 코드인  엔트리 포인트를 지정해주어야 한다.

섹션(Section)

-실행 파일 또는 오브젝트 파일에 이씅며 공통된 속성(코드, 데이터, 각종 심볼과 디버깅 정보 등)을 담는 영역

-text 섹션

-실행 가능한 코드가 들어있는 섹션

-우리가 작성한 main()이나 함수의 실제 코드가 저장되는 영역

-수정될 일이 거의 없어서 일반적으로 Read-Only로 설정

-data 섹션

-초기화 된 데이터가 들어있는 섹션

-초기화 된 전역 변수(Global Variable) 또는 0이 아닌 값으로 초기화된 정적 변수(Static Variable)를 포함

-데이터를 저장하는 섹션이여서 일반적으로 Read,Write로 설정

-.bss 섹션

-초기화 되지 않은 데이터가 들어있는 섹션

-.data 섹션에 포함되는 데이터와 거의 같지만 초기화 되지 않은 변수만 포함한다는 것이 특징

-해당 섹션은 0으로 초기화 될 뿐, 실제 데이터가 없어서 실행 파일이나 오브젝트 파일 상에는 별도의 영역을 차지하지 않는다.

-하지만 여기서 중요한 point는 '메모리에 로딩되었을 때 코드는 해당 영역 변수들이 초깃값이 0이라 가정한다'

-정상적인 프로그램 실행을 원한다면 메모리에 로딩할때 .bss 영역을 모두 0으로 초기화 해주어야한다.

~>소스 코드를 컴파일하여 생성한 오브젝트 파일은 각 섹션의 크기와 파일 내에 있는 오프셋 정보만 들어 있다.

~>오브젝트 파일은 중간 단계의 생성물로 다른 오브젝트 파일과 합쳐지기 때문

~>합쳐지는 순서에 따라 섹션의 어드레스는 얼마든지 바뀔 수 있다.

~>여기서 오브젝트 파일들을 결합하여 정리하고 실제 메모리에 로딩될 위치를 결정하는 것이 바로 '링커'

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

*하지만 단지 링커로만 이것이 가능한게 아니다. 링커가 실행 파일을 만들려면 파일 구성에 대한 정보가 필요한데 이때 사용하는 '링커 스크립트' 가 필요하다

~>링커 스크립트에는 각 센션의 배치 순서와 시작 어드레스, 섹션 크기 정렬등의 정보를 저장해 놓은 텍스트 형태의 파일이다.

[링커 스크립트]





섹션의 재배치

- 실행 파일이 링크될 때 코드나 데이터 이외에 디버깅 관련 정보와 심볼 정보등이 포함되기 때문

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

-텍스트나 데이터와 관계없는 섹션의 기본구조 전체를 코드 및 데이터 섹션의 뒷 부분으로 이동하거나 코드 및 데이터에 관련된 섹션을 가장 앞으로 이동함으로써 처리할 수 있다.(보통 후자의 경우를 많이 사용)


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

-메모리를 미리 예측하고 그에 맞춰 이미지를 생성하지 않는다면 전역 변수와 같이 선형 어드레스를 직접 참조하는 코드는 모두 잘못된 어드레스에 접근하게 된다.

-링커 스크립트를 수정하는 방법, 링커(LD) 프로그램의 명령줄 옵션으로 지정하는 방식

-전자의 경우 .text 섹션을 수정한다. 해당 섹션을 수정하게 되면 .data와 .bss같은 섹션은 자동으로  .text가 로딩되는 어드레스 이후로 계산된다.


반응형
,