Search

'기타 자료'에 해당되는 글 8건

  1. 2013.01.08 Visual Studio 로 커널 만들기 1 3

Visual Studio 로 커널 만들기 1

기타 자료 2013. 1. 8. 08:46 Posted by 알 수 없는 사용자

 

오늘 약간 시간이 남아서 Visual Studio 로 커널 만들기에 대해서 생각 해 봤다.

 

 1. 왜 우리는 GCC를 쓰는가? CYGWIN은 뭔데?

 왜 GCC를 쓰는지는 아직 이해하지 못했다. 무료라서 그런가? 아니면 LD의 디폴트 링킹이 아니라

사용자 정의 스크립트를 이용한 링킹을 하기 위해서?

 

CYGWIN은 윈도우에서 돌아가는 리눅스가 아니다.

윈도우에서 리눅스 코드를 컴파일 할 수 있도록 POSIX호환 API를 제공하는것이다.

 

2. ELF, PE, COFF

이제 우리는 CYGWIN을 이용해서 윈도우에서 윈도우용 코드, 리눅스용 코드를 모두 컴파일 할 수 있게 되었다.

그리고 이러한 코드를 컴파일하면 Object File, 링크 하면 Executable File이 나오게 되는데.

윈도우와 리눅스는 서로 다른 형태의 포맷을 사용한다.

 

윈도우에서 오브젝트 파일과 실행파일의 포맷은 PE/COFF(Portable-Executable / Common Object File Fomat)

리눅스에서는 ELF, Executable and Linking Format 를 사용한다.

 

[COFF, ELF, PE/COFF 의 역사]

 

본래 Object File 포맷의 기원은 Unix의 a.out이었다.

근데 이 포맷은 shared libraries(윈도우에서 DLL), foreign format identification, explicit address linkage를 지원하기에 부족했다.

그리고 Unix-like 시스템들이 AT&T 밖과 안에서 발전함에 따라 이 문제에 대한 해결책이 여러 갈래로 나뉘었다.

 

AT&T의 경우 이 문제를 해결하기 위해 Unix System V 에서 COFF를 처음으로 도입했다.

근데, 이 방식이 너무도 제한되었고(too limited), 불완전했다.

이를테면 섹션 수에 제한이 있었고, 섹션 이름 길이에도 제한이 있었다.

또한 이 포맷에서 포함된 소스 파일이나 사용하는 디버깅 인포메이션이

C와 같은 실제 프로그래밍 언어를 지원하기 어려웠다. 그래서 실제적으로 구현된 COFF는 표준을 위반할 수 밖에 없었다.

 

SVR4가 AT&T에서 나오면서, AT&T는 COFF를 ELF로 교환했다.

 

PE/COFF는 Windows NT용으로 개발되었다. PE/COFF라 불리는 이유는,

Object File을 위해 COFF 헤더를 이용하며, Executable File을 위한 PE 헤더의 구성요소로 COFF를 이용하기 때문이다.

Developed for Windows NT, the PE format (sometimes written as PE/COFF) uses a COFF header for object files, and as a component of the PE header for executable files.

(참조 - http://en.wikipedia.org/wiki/COFF)

(참조 - http://en.wikipedia.org/wiki/Portable_Executable)

(참조 - http://en.wikipedia.org/wiki/Executable_and_Linkable_Format )

 

사실 이런 포맷들이 하는 일은 각 섹션에 대한 자세한 정보를 포함하고 있는 것 뿐이다.

따라서 PE와 ELF는 서로 기능적으로 비슷할 수 밖에 없다.[각주:1] (참조 - http://www.theparticle.com/cs/bc/os/elfpecoff.html)

 

[이진 호환성과 ABI, Application Binary Interface]

 

이렇게 운영체제(플랫폼) 마다 상이한 Executable Binary Format을 ABI, Application Binary Interface 라고 한다.

다시말해서, 운영체제에 탑재된 (실행파일을 위한) 로더가 다르다는 것이다.

동일한 마이크로 프로세서의 바이트코드(기계어 코드)라고 해도 로더를 위한 부가정보가 각 포맷에 포함되기 때문에

로더가 어떤 ABI를 지원하느냐에 따라 실행파일의 상호 호환성이 결정된다.

참고로, 바이너리 호환성에 있어서 포맷 뿐만 아니라 System Call 또한 문제가 될 수 있다.

특정 ABI를 위한 로더와 대상 OS를 위한 System call Wapper를 새로 만들었다 하더라도,

System call 의 Protocal이 OS에 따라 다르기 때문에 문제가 된다.

예를 들어 Linux에서는 시스템 콜 인터럽트가 80h고, Win2K는 시스템 콜 인터럽트가 2Eh다.

결국 인터럽트 후킹까지 해야하는 것이다. [각주:2] (인터럽트 후킹 이야기 존나 이해 안됌.)

(참조 - http://kldp.org/node/70098)

 

[ELF, Executable and Linking Format]

ELF에 대해서는 다음을 참조하라.

- http://recipes.egloos.com/5010841 (친절한 임베디드 시스템 개발자 되기, ELF)

- http://recipes.egloos.com/5011946 (ELF 부터 링크까지)

elf_fileformat.hwp

ELF.pdf

 

[링크]

추가적으로 링크에 대해서 설명하자면

- 1. 컴파일을 통해 만들어진 오브젝트 파일들의 섹션을 통합하고

- 2. 실제 함수 정의부의 위치와 전역변수들의 위치를 라이브러리 파일과 오브젝트 파일에서

조사한 후 Table로 간직하고 있다가, 사용할때 주소를 삽입해 주는 역할을 한다.

(참조 - http://www.iamroot.org/xe/index.php?document_srl=19360&mid=wiki&act=dispWikiHistory)

 

asmlink.gif

(참조 - http://cs.lmu.edu/~ray/notes/x86assembly/)

 

3. 그래서 ELF가 뭐 어쨌다고? VS 로 커널을 어찌 만들건데?

 

(참조 - http://wiki.osdev.org/Visual_Studio)

 

우리가 7장에서 공부 했듯이 사실 OBJCOPY 가 GCC로 컴파일되어 나온

ELF 에서 뽑아내는건 실행에 필요한 데이터들이다.

.TEXT, .DATA .RODATA(= .RDATA) 섹션이 그 3가지다.

 

Visual Studuio 에서도 컴파일 옵션을 잘 주면 이 3가지 섹션만 나오도록 할 수 있고.

단지 앞부분에 섹션 헤더, 도스 스텁과 같은 쓰잘데기 없는 것들이 붙을 뿐이다.

(Visual Studio는 PE와 COFF만 생성할 수 있다는것을 기억해라.)

 

그리고 이 부분을 뛰어 넘어서 텍스트 섹션으로 바로 점프할 수 있다면

우리는 Pure Binary, 즉 기계어 코드 부분을 곧바로 실행시킬 수 있다.

 


개발자를 위한 나만의 운영체제 만들기

저자
노재현 지음
출판사
정보문화사 | 2007-03-05 출간
카테고리
컴퓨터/IT
책소개
OS 개발 입문서. 이 책은 OS를 스스로 개발하는 방법을 설명...
가격비교

'개발자를 위한 나만의 운영체제 만들기' 란 책에서는

이 방법을 사용한다. BootLoader 가 커널을 0x20000에 로드하되, PE부분의 쓸데 없는 정보가

0x0FFF 까지를 차지하므로, 0x21000로 점프하는 것이다.

 

 

난 항상 이 책을 보면서

아 시발 0x20000를 엔트리 포인트로 설정하는데, 왜 BootLoader에서는 0x2000:1000, 즉 0x21000으로 점프하는거야?

라고 생각했는데, 이유가 여기 있었던 것이다.(개객기! 책에 설명도 안해놓고)

 

2013.01.08 수정

[ PE Format의 Address of Entry Point 와도 관련 있다. Text 섹션이 아무리 0x200 시작한다고 해서 0x20200으로 점프 해 봐야

코드 실행 안된다. 링크할때 엔트리 포인트 시작 주소를 0x1000(RVA)로 정했기 때문이다.

1. 따라서 텍스트 섹션을 찾아 내서 0x21000 에 복사 해 주던지(이건 사실 PE를 읽는 커널을 만드는것과 다름 없다. elf-new 찾아가고..시발..)

2. 아니면 코드 섹션의 시작을 0x1000으로 맞추는 수 밖에 없다. 어떻게? 파일 사이즈를 늘려서.

내가 찾아 낸 해답은 전역변수로 const int g[10000]; 하기다. 이거 하면 코드 섹션이 커지더라.

재수정 : 링커 옵션에서 /filealign:0x1000 하면 그냥 됌.

안되면 더 넣고 별 짓 다 하면된다. 코드 섹션의 시작은 파일 사이즈에 따라 다르긴 한데

0x200 부터 시작해서 512bytes, 즉 0x200 단위로 커지는것 같고 맥시멈이 0x1000인것 같다.]

재수정 : 미니멈, 맥시멈은 filealign 링커옵션 값에 따라 달라질 수 있음.

 

 

위에 보면, 부트 로더(512bytes 짜리)에서 뒷부분을 읽어서 0x20000 에 올리고

LDRSEG:1000h 로 점프하는데, 위에 매크로에 보면 알겠지만 LDRSEG 는 0x2000, 즉

세그먼테이션 된 값으로 0x20000이다. 다시 말해서 0x21000 으로 점프한다는 것이다.

 

자, 이제 링커가 0x20000에 뭘 위치하게 하는지 확인 해 보자.

 

EntryPoint16? 어디서 온거당가요?

 

 

entry.asm 에서 PUBLIC 으로 왔다. 이걸 참조하게 한 적이 없는데?

(참고로, PUBLIC은 외부에서 사용할 수 있게 노출하는거고, EXTERN 은 외부에 정의된 내용을 선언하는거다.

C에서의 EXTERN은 두가지 모두로 사용 가능하지만 MASM에서는 구분 해 논 듯 하다.)

참고  -


어셈블리 언어

저자
KIP R. IRVINE 지음
출판사
Pearson Education Korea | 2007-11-22 출간
카테고리
컴퓨터/IT
책소개
이 책은 인텔 IA-32 프로세서를 위한 어셈블리 언어 프로그래...
가격비교

 

 

이미 링커 인풋으로 해놨었다. 시발럼아.

그럼 빌드는 언제 해쓰까?

 

 

아.. Pre-Build Event 였쿠나!!!.

 

 

어쨌든, 이런 방식으로 Entry16(entry.asm내의) 를 0x20000에 로드하고, PE부분의 쓰레기 0x1000을 뛰어 넘어서

Bootloader.asm 에서 0x21000 으로 점프 했으므로. 이 뒷부분 코드를 살펴보자.

 

 

 

GDT 세팅, CR0 세팅 하고

신박하게 $+2 로 jmp 한다. jmp 명령어가 2바이트니까, FJMP16 08h, EntryPoint32 이걸 실행한다는건데

NASM 에서 jmp dword 0x08:EntryPoint32 쯤 되시겠다.

 

왜 그냥 냅둬도 실행할걸 점프하냐는 독자들의 질문에, 저자는 "파이프라이닝" 을 역 이용해서 RealMode 에서 탑재된 명령어를 싸그리 실행시키고 넘어가기 위함이라고 말한다.

다시 말하자면, 파이프라이닝을 이용하면 미리 실행할 명령어를 가져와서 어찌어찌 처리함으로써 성능을 높일 수 있다.

근데, jmp를 이용하면 어디로 분기할지 알 수 없으므로 파이프 라이닝을 이용할 수 없고, 리얼모드에서 탑재된 명령을 모두 실행한 후에야 jmp 명령어 부분을 실행한다는 것이다. ( 이사람은 실행시점을 말하지만, 내생각에는 파이프라이닝 될 수 있도록 컴파일 되지 못하게, 즉, EntryPoint32가 어디 올라갈지 알 수 없으므로 파이프라이닝을 이용할수 없게끔 바이트코드가 구성되는것이지 않을까 생각해봄.)

 

그리고 나서 존나 특이한점이 두 개 있는데 MASM은 FAR JMP와 LGDT 명령어를 지원하지 못해서

이 책의 저자가 스스로 바이트코드를 찾아서 매크로로 만들었다. (NASM이 더 우월한듯 ㅎ_ㅎ)

 

 

그리고 EntryPoint32 의 마지막 부분에서, C언어로 작성된 첫번째 함수인 chobits_init으로 점프한다. 위에서 언급했듯이

EXTERN 되어 있다.

 

 

[Name Mangling]

이때 앞에 '_' 하이픈이 붙는 이유는, 컴파일러가 C파일에는 하이픈을 붙여서 오브젝트 파일에 저장하기(심볼로 노출하고)

때문이다. 이렇게 컴파일러가 함수의 이름을 바꾸는걸 Name Decoration 또는 Name Magling 이라 부르른다.

 

더 정확히 말하면, chobits_init 함수가 cdecl 방식이기 때문에 하이픈 하나만 붙는거다.

stdcall 을 함수 호출 규약으로 사용하면 다른 형태로 변한다.

(참조 - http://thepassion.tistory.com/61)

(참조 - http://no1rogue.blog.me/30095521394)

(참조 - http://en.wikipedia.org/wiki/Name_mangling 위키)

 

cdecl 방식은 호출하는 쪽이 스택에 삽입된 인수를 제거하고

stdcall 은 호출 받는 쪽이 스택을 정리한다.

 

MASM에서는 이를 위해 언어 지정자를 사용할 수 있다.

.MODEL FLAT, C

.MODEL FLAT, STDCALL

와 같이 사용할 언어 지정자를 사용하면, 다른 모듈을 위해 해당 언어가 이해할 수 있는 심볼 형태로 어셈블리 함수를 Export한다.

또한 다른 모듈에서 노출하여 어셈블리 코드에서 사용할 함수를 링커에게 올바르게 알려줄 수 있다.

그리고, 어셈블리 언어에서 C, C++ 함수를 호출하려면 Extern "C" 를 통해 네임 맹글링을 제한해야 한다.

(근데 chobits_init엔 그런거 없던데.. 아마도 그냥 cdecl이라 그런가 봄.)

(참조 - 인텔 어셈블리언어 챕터8 330p, 514p, 528p)

 

존나 존나 존나 존나 빙글빙글빙글 돌아왔다.

아니 시발 그럼 처음부터 LGDT, FJMP 같은거 없으면

NASM 쓰고 OUTPUT을 COFF로 출력한다음에 C랑 같이 Visual Studio에서 링크하면 되잖아

이 씨발!!!!!!!!!!!!!!!

 

참고로 NASM 로 어셈블 할때 OBJ 포맷은 16비트 윈도우, 즉 DOS를 위한 OMF 포맷이고

WIN32 가 PE/COFF 포맷이다.

일반 COFF 포맷은 djgpp 를 위한 것.

(참조 - http://forum.nasm.us/index.php?topic=113.0 실패하고 질문 올린 사람)

(참조 - http://www.nasm.us/doc/nasmdoc7.html : NASM 매뉴얼)

 

그리고 NASM과 CL, LINK를 같이 쓰는 방법은

http://www.tech-juice.org/2011/02/26/assembler-tutorial-hello-world-with-nasm-and-cl-exe-or-link-exe/

http://stackoverflow.com/questions/1023593/how-to-write-hello-world-in-assembler-under-windows

 

NASM 에서 C함수를 호출하는 방법은  

- http://cs.lmu.edu/~ray/notes/x86assembly/ 이거 가 젤 잘나와있음

- http://www.nasm.us/xdoc/2.09.08/html/nasmdoc9.html#section-9.1 (NASM 매뉴얼)

- http://www.cs.uaf.edu/2011/fall/cs301/visual2010/ (NASM with VS2010, 어셈에서 C함수 부르기)

- - http://www.cs.uaf.edu/2010/fall/cs301/lecture/10_13_linker.html

- http://forum.nasm.us/index.php?topic=1029.0 (맨 밑에꺼 읽어보기)

 

4. Writing multiboot PE Kernels using Visual C++

 

사실 이 방법을 피하려면, PE 포맷을 읽을 수 있는 커널을 만들어야 한다.

국내 블로그중에 있었던거 같은데, 지금은 찾질 못하겠고

http://www.brokenthorn.com/Resources/OSDevMSVC.html

 : 여기서 Executing PE Kernel 을 읽어라

아님 아래 두개의 글을 참고해도 좋겠다.

http://ksrenevasan.blogspot.kr/2005/10/writing-multiboot-pe-kernels-using.html (1)

http://ksrenevasan.blogspot.kr/2005/10/writing-multiboot-pe-kernels-using_03.html (2)

 

5. C++ 로 커널 만들기

익히 알고 있듯이(위에서 네임 데코레이션이라고 이미 언급했었다.)

오버로딩으로 인해 C++ 에서는 함수 심볼 명이 abc@xyz1234 와 같이 변한다.

이를 방지 하기 위해 Extern C 를 함수 앞에 붙여주면 된다.

Virtual Function을 안쓰고 클래스만 사용할 것이라면 프로젝트 속성을 바꾸지 않아도 된다.

만약 가상함수를 사용한다면, 기본 라이브러리 무시를 선택해야 한다. [각주:3]

 

(참조 -http://charsyam.tistory.com/entry/CharSyam-OS-Kernel-With-C)

(참조 - http://blog.naver.com/PostView.nhn?blogId=yoosy35&logNo=110035983414)

(참조 - http://kldp.org/node/29882 : 리눅스에서 C++로 커널 개발?)

 

6. 기타 참고

윈도우와 리눅스에서 x86 어셈블리 프로그래밍 하기 NASM, MASM, GAS 차이

- http://cs.lmu.edu/~ray/notes/x86assembly/ (존나 두번세번 읽기)

 

터보 C의 깊은 곳 : 존나 꼭 두번 세번 읽기

근거리, 원거리, 거대 포인터 - http://www.hackerschool.org/HS_Boards/data/Lib_prog/Tc1.txt 

메모리 모델 및 구조 - http://www.hackerschool.org/HS_Boards/data/Lib_prog/Tc2.txt

함수 호출 규약 - http://www.hackerschool.org/HS_Boards/data/Lib_prog/Tc3.txt

어셈블리어 기초 - http://www.hackerschool.org/HS_Boards/data/Lib_prog/Tc4.txt

어셈블리어 기초 2- http://www.hackerschool.org/HS_Boards/data/Lib_prog/Tc5.txt

세그먼트 디렉터 - http://www.hackerschool.org/HS_Boards/data/Lib_prog/Tc6.txt

 

MASM 디렉티브 및 메모리 모델

- http://www.c-jump.com/CIS77/ASM/Directives/lecture.html

MASM 사용법 및 메모리 모델 등

- http://www.hackerschool.org/HS_Boards/data/Lib_prog/MASM.txt

 

 

16비트 MASM, LINK.EXE

- 8086_Assembler.zip

- http://www.asmcommunity.net/board/index.php?topic=25659.0

: 16비트에서 어셈블리 코드를 컴파일할때는 /coff 스위치 대신 /omf 를 써야한다는데.. 이유는..?

MSVC 링커 옵션 - http://msdn.microsoft.com/en-us/library/y0zzbyt4(v=vs.80).aspx

MSVC 링커옵션 : 섹션지정 - http://msdn.microsoft.com/ko-kr/library/sf9b18xk(v=vs.80).aspx

MSVC 링커 옵션 서브 시스템 - http://msdn.microsoft.com/en-us/library/fcc1zstk(v=vs.80).aspx

ML 옵션 - http://cafe425.daum.net/_c21_/bbs_search_read?grpid=1AQQ3&fldid=Nilm&datanum=6&contentval=&docid=1AQQ3

 

 

OSDev MASM 위키 - http://wiki.osdev.org/MASM#Microsoft_Reference_For_ML.EXE

NASM Output Format http://cs.nyu.edu/courses/fall02/V22.0201-001/nasm_doc_html/nasmdoc6.html

 

 

MSVC 로 OS 만들기 - http://www.brokenthorn.com/Resources/OSDevMSVC.html

OSDev Visual Studio 위키 - http://wiki.osdev.org/Visual_Studio

 

 

[기타 잡동사니]

 

어셈블리어로 PE분석기 제작

-어셈블리로PE분석.pdf

 

별 영양가 없는 글. IDE만 Visual Studio고 컴파일러로 gcc 사용.

http://gusc.lv/2012/11/im-writing-my-own-os/

http://gusc.lv/2012/11/im-writing-my-own-os-p2/

http://gusc.lv/2012/11/my-os-part-3/

http://gusc.lv/2012/11/im-writing-my-own-os-intermission/

http://gusc.lv/2012/12/myos-mingw-cross-compiler/

 

yasm + Visual Studio, 뭔가 하긴 하는데 이해할수 엄슴. 별 영양가 없음.

- http://dc0d32.blogspot.kr/2012/02/writing-kernel-in-windows-with-visual.html

-
  1. http://www.theparticle.com/cs/bc/os/elfpecoff.html [본문으로]
  2. http://kldp.org/node/70098 [본문으로]
  3. http://charsyam.tistory.com/entry/CharSyam-OS-Kernel-With-C [본문으로]

'기타 자료' 카테고리의 다른 글

NASM, C, C++ 로 커널 만들기  (0) 2013.01.29
Windbg 정리  (0) 2013.01.27
Windbg + Vmware, Websymbol 세팅  (0) 2013.01.22
각종 디바이스 드라이버 데이터 시트 및 코딩  (0) 2013.01.22
Visual Studio 로 커널 만들기 2  (0) 2013.01.08