목차
• 컴퓨터 시스템7장 : 링커
• 링킹이란?
• 컴파일 시스템
• 링킹
• 정적 연결
• 심볼 해석
• 재배치
• 라이브러리
• 라이브러리
• 정적 라이브러리
• 동적 라이브러리
• 부록
• 참고 사이트
• 교재 외 참고 서적
3.
Notice
• 컴퓨터 시스템책과 다르다
• 컴퓨터 시스템은 리눅스를 중심으로 한다.
• 스터디에서는 Windows 리버싱에 도움될 내용에 초점을 맞추었다. 따라서 Windows 형식에 맞추었다.
• ->책을 한 번쯤 따로 읽어볼 것. PE 파일 형식이 아니라 ELF 파일 형식을 기준으로 써 있는데, 핵심은 비슷하니 이해할 수 있다.
• 링킹에 대해서는 가볍게 개념만 볼 것임
• 링킹 자체보다는 라이브러리를 자세히 볼 것이다
• 리버싱에서 라이브러리를 다루게 되므로
프로그램은(코드는) 다른 프로그램에의해 다른 형태로 번역된다
• 고급 언어로 프로그래밍한 코드가 실행 가능 파일이 되는 과정을 알아보자
• 사람이 알아들을 수 있는 고급 언어(예 : C언어)는 네 단계에 걸쳐 실행 가능 프로그램이 된다
• 전처리, 컴파일, 어셈블, 링크
• 각각 전처리기, 컴파일러, 어셈블러, 링커에 의해 실행
• 이 네 프로그램을 합쳐서 컴파일 시스템이라고 부름
• Text파일인 고급 언어 소스 코드에서 실행 가능한 프로그램인 binary 파일(text보다 광범위한)이 된다.
전처리기 컴파일러
Hello.c Hello.i
어셈블러 링커
Hello.s Hello.exeHello.o
소스 코드
(txt)
수정된
소스 코드
(txt)
어셈블리 코드
(txt)
재배치 기능한
object 프로그램
(binary)
실행 기능한
object 프로그램
(binary)
6.
프로그램은(코드는) 다른 프로그램에의해 다른 형태로 번역된다
• 전처리기
• C언어에서 #문자로 시작하는 디렉티브를 처리해 줌
• 주석 제거
전처리기 컴파일러
Hello.c Hello.i
어셈블러 링커
Hello.s Hello.exeHello.o
소스 코드
(txt)
수정된
소스 코드
(txt)
어셈블리 코드
(txt)
재배치 기능한
object 프로그램
(binary)
실행 기능한
object 프로그램
(binary)
7.
• 전처리기만 실행하여hello.i 파일을 얻었다.
• Include한 헤더파일에 써 있는 내용을 붙였다.
• Define한 NUM을 상수로 대체했다.
프로그램은(코드는) 다른 프로그램에 의해 다른 형태로 번역된다
8.
• 헤더에는 함수의원형만 써 있다.
• 실제로 함수 코드를 사용할 수 있도록
하는 일은 Link 과정에서 이루어진다.
프로그램은(코드는) 다른 프로그램에 의해 다른 형태로 번역된다
9.
• 컴파일러
• 수정된C언어를 어셈블리어로 번역함
전처리기 컴파일러
Hello.c Hello.i
어셈블러 링커
Hello.s Hello.exeHello.o
소스 코드
(txt)
수정된
소스 코드
(txt)
어셈블리 코드
(txt)
재배치 기능한
object 프로그램
(binary)
실행 기능한
object 프로그램
(binary)
프로그램은(코드는) 다른 프로그램에 의해 다른 형태로 번역된다
10.
• hello.i 파일을컴파일하여 hello.s 파일을 얻었다.
• 붙여진 헤더파일 내용에서 printf 함수의 형태를 얻는다. 그것을 보고 함수에 인자를 넣는 코드를 만들 수 있다.
• 실제 함수 코드가 없기 때문에(라이브러리에 있기 때문에) 함수가 어떤 인자를 요구하는 지 알 수 없다.
• 그것을 알려주기 위해서 함수의 형태(원형)에 대한 정보가 들어있는 헤더를 포함한다.
• 적절한 어셈블리 코드를 만들기 위해 함수 원형에 대한 정보가 필요했다. 어셈블리 코드를 만들었으므로 삭제된다.
프로그램은(코드는) 다른 프로그램에 의해 다른 형태로 번역된다
11.
• 어셈블러
• 어셈블리어코드를 기계어로 번역
• 실행 파일의 뼈대를 만듦
• 결과물은 더 이상 text 파일이 아님 (=사람이 읽기 위한 파일이 아님)
• 기계가 읽기 위한 파일
전처리기 컴파일러
Hello.c Hello.i
어셈블러 링커
Hello.s Hello.exeHello.o
소스 코드
(txt)
수정된
소스 코드
(txt)
어셈블리 코드
(txt)
재배치 기능한
object 프로그램
(binary)
실행 기능한
object 프로그램
(binary)
프로그램은(코드는) 다른 프로그램에 의해 다른 형태로 번역된다
12.
프로그램은(코드는) 다른 프로그램에의해 다른 형태로 번역된다
◦ 참고 : 목적파일?
◦ 목적파일은 세 가지 형태가 있다.
◦ 재배치 가능 목적파일(Relocatable object file)
◦ o나 obj 등을 확장자로 하는 파일
◦ 다른 재배치 가능 목적 파일들과 결합하여 실행 가능 목적파일을 생성한다.
◦ 실행 가능 목적파일(Executable object file)
◦ exe 등을 확장자로 하는 파일
◦ 공유 목적파일(Shared object file)
◦ dll 등을 확장자로 하는 파일
◦ 로드타임 또는 런타임 시에 동적으로 링크되고 메모리에 로드될 수 있는 특수한 유형의 재배치 가능 목적 파일
13.
• 빨간 테두리속에 있는 것이 기계어
코드 영역
• 그 외 부분에는 PE 헤더, data영역 등
실행에 필요한 정보가 있다
프로그램은(코드는) 다른 프로그램에 의해 다른 형태로 번역된다
14.
• 링커
• 다른재배치 가능한 object 프로그램과 합침
• 여러 C 파일로 나누어 코딩한 경우
• 다른 C 파일들로 생성한 재배치 가능 object 프로그램과 연결하여 하나의 실행 가능 object 프로그램을 만듦
• 외부 함수를 이용할 수 있도록 해 줌
• 외부 함수도 object 파일에 있음
전처리기 컴파일러
Hello.c Hello.i
어셈블러 링커
Hello.s Hello.exeHello.o
소스 코드
(txt)
수정된
소스 코드
(txt)
어셈블리 코드
(txt)
재배치 기능한
object 프로그램
(binary)
실행 기능한
object 프로그램
(binary)
프로그램은(코드는) 다른 프로그램에 의해 다른 형태로 번역된다
15.
• 실행 가능목적 파일 완성!
• 완성된 PE헤더를 가진다.
• (코드는 저 밑에 있음)
프로그램은(코드는) 다른 프로그램에 의해 다른 형태로 번역된다
16.
링킹?
◦ 링킹(Linking)이란?
◦ 여러개로 나눠진 오브젝트 파일들을 하나로 합치는 작업
◦ 오브젝트 파일들과 Static library의 내용을 합친다.
◦ Dynamic library를 이용할 수 있도록 준비해준다.
◦ 컴파일 때 뿐만 아니라, 로더에 의해 실행되는 로드 타임에, 심지어 실행 시간 동안에도 수행될 수 있다.
◦ 앞에서 얘기한 링킹은 컴파일시의 링킹이다.
◦ 로드 타임에는 Dynamic library를 실제로 이용할 수 있도록 링크한다.
◦ 프로그램에 직접 코드를 써 넣으면 실행 시간에도 수행될 수 있다.
◦ Dynamic Library의 명시적 연결
◦ 초기 컴퓨터 시스템에서는 수동으로 링킹을 해야 했다. 현대에는 링커라고 불리는 프로그램을 이용하여 수행한다.
17.
링킹?
◦ 링커를 이용하면독립적인 컴파일이 가능하게 된다.
◦ 큰 코드를 하나의 소스파일로 구성하는 대신 여러 개의 소스 파일로 구성할 수 있다.
◦ Ex) 커다란 C파일에 전부 쓰는 대신 여러 개의 C파일에 나누어 쓸 수 있다.
◦ 컴파일은 각각의 C파일을 대상으로 한다.
◦ 따라서 하나의 파일을 수정한 뒤 새 EXE를 만든다면, 수정된 C파일만 재컴파일 한 뒤 나머지 C파일의 object file과 링킹
한다.
◦ 여러 파일에 나누어 쓰는 것의 장점
◦ 수정되지 않은 내용에 대한 불필요한 컴파일이 줄어 컴파일 시간이 줄어든다.
◦ 관리가 편하다.
18.
링킹?
◦ 왜 링킹을공부하나?
◦ 큰 프로그램 작성에 도움이 된다.
◦ 링크 에러를 이해하는 데 도움이 된다.
◦ 어떻게 프로그램이 만들어 지는 지 더 잘 이해하게 된다.
◦ 공유 라이브러리에 대해 이해할 수 있다.
정적 연결
◦ 컴파일시, 재배치 가능한 목적파일을 합치는 것
◦ 과정
◦ 1. 심볼 해석
◦ 심볼은 함수, 전역변수, 정적변수(static) 등에 대응된다.
◦ 다른 소스파일에서 만든 함수, 전역 변수를 이용할 수 있게 한다.
◦ 2. 재배치(Relocation)
◦ 각 파일들은 파일의 처음부터 시작된다. 이것들을 모아서 하나에 파일에 넣을 것이므로, 파일이 재배치 되어야 한다.
◦ 각 object 파일에서 코드, 데이터 등을 알맞은 섹션에 재배치 한다.
◦ 모든 주소 참조들을 바뀐 환경에 알맞게 수정한다.
21.
심볼 해석
◦ 아래와같이 다른 소스 코드에서 정의한 전역 변수, 함수를 이용하기 위한 과정
◦ 이용한 함수 이름, 전역변수 이름 등을 이용한다.
22.
심볼 해석
◦ 링커는오브젝트 파일을 해석하면서 다음과 같은 테이블 이용한다.
◦ 1. 모듈 m에 정의되고 다른 모듈들에 의해서 참조될 수 있는 전역 심볼
◦ Static이 아닌 함수와 전역변수가 있다.
◦ 2. 모듈 m에서 참조하지만 다른 모듈에 의해 정의된 전역 심볼
◦ 다른 모듈 내에서 정의된 static이 아닌 전역변수와 함수
◦ 3. 모듈 m만 이용할 수 있는 지역 심볼
◦ Static인 함수와 전역 변수
◦ 지역변수는 지역 심볼에 속하지 않는다.
◦ 다른 모듈에서 불러 쓸 수도 없다.
◦ 지역변수의 위치는 어셈블리어 수준에서 이미 완료되었다. (스택 계산)
23.
심볼 해석
◦ 코드들은컴파일 과정을 통해 어셈블리어로 컴파일 된다.
◦ 이 때, 전역변수나 함수 이름은 그대로 써 있다.
◦ 어셈블리어 파일이 컴파일 되어 재배치 가능한 오브젝트 파일이 된다.
◦ 이 때, 코드(기계어)에서는 전역변수나 함수 이름 대신에 그 전역 변수가 저장된 주소나 함수의 주소를 쓴다.
◦ 만약 자신이 정의한 것이 아니라면(참조한 것이라면)
◦ 일단 주소에는 0을 채운다.
◦ 참조할 테이블에 써 둔다. 참조할 테이블에는 어느 위치의 주소를 수정해야 하는지도 써 있다.
◦ 재배치 가능한 오브젝트 파일을 모아서 링크한다. 실행 가능한 오브젝트 파일을 만든다.
◦ 링크 시 함께 링크하는 다른 재배치 가능한 오브젝트파일에서, 참조 테이블에 써 둔 것이 있는지 살펴본다.
◦ 끝까지 살펴봤는데 아무 데도 없다면 링크 에러를 내고 실행 가능한 오브젝트 파일을 만드는 데 실패한다.
24.
심볼 해석
◦ 재배치가능한 오브젝트 파일에는 각자 어떤 심볼을 정의하고 어떤 심볼을 참조하는지 써 있다.
◦ 링크 시 함께 링크하는 다른 재배치 가능한 오브젝트파일에서 해당 심볼을 찾아본다.
Code1.c에서
정의된 전역 심볼
• num
• main
Code1.c Code2.c
Code2.c에서
정의된 전역 심볼
• func
Code1.c에서
참조하는 전역
심볼
• func
Code2.c에서
참조하는 전역
심볼
• num
25.
심볼 해석
◦ 어느주소에 수정 값을 넣어야 하는지 적혀있다.
Text 섹션의 0x10 위치부터 num2의 주소가 들어가야
한다.
26.
심볼 해석
◦ 서로다른 모듈이 같은 이름의 전역변수를 정의하면 어떻게 처리될까?
◦ 심볼에는 강한 심볼과 약한 심볼이 있다.
◦ 강한 심볼 : 함수, 초기화 된 전역변수
◦ 약한 심볼 : 비초기화 전역변수
◦ 다음과 같은 규칙으로 처리된다.
◦ 동일한 이름을 갖는 복수의 강한 심볼 -> 컴파일 에러
◦ 동일한 이름의 강한 심볼과 약한 심볼들 -> 강한 심볼을 선택
◦ 동일한 이름의 약한 심볼들 -> 무엇을 선택하든 관계 없음
27.
재배치
◦ 각각의 소스코드는 각각의 재배치 가능 오브젝트 파일을 생성한다.
◦ 각각의 파일은 파일의 처음부터 시작한다.
◦ 각자가 자신의 파일 내에서의 주소를 쓴다.
◦ 이들을 모아서 합치면 원래 주소를 이용할 수 없다.
◦ 다른 오브젝트 파일에서 온 코드와 데이터들이 앞뒤에 있다.
◦ 따라서 이들을 재배치 해 주어야 한다.
◦ Code1.obj의 text영역과 Code2.obj의 text영역을 합쳐야 한다.
◦ 함수 call이나 jmp에 이용된 주소(특히 절대 주소일 경우)를 알맞게 수정
◦ Data영역 등도 합쳐야 한다.
◦ 전역변수 주소를 수정한다.
◦ 앞서 0으로 채워 두었던, 다른 모듈에서 참조한 전역변수의 주소를 채운다.
Code1.obj Code2.obj
Mov 1, dword ptr[100] Mov 2, dword ptr[100]
Mov 2, dword ptr[200]
Mov 1, dword ptr[100]
Excutable.exe
28.
라이브러리
◦ 정적 연결에서는라이브러리를 연결해주는 일도 한다.
◦ 라이브러리에는 정적 라이브러리와 동적 라이브러리가 있다.
◦ 정적 라이브러리는 정적 연결에서 전부 처리되고, 동적 라이브러리는 일부 처리된다.
◦ 바로 뒤에서 알아보자!
라이브러리
◦ 라이브러리가 없었을때, 어떤 방법을 이용하여 유사한 효과를 얻었을까?
◦ 컴파일러가 모든 표준 함수 호출을 인식하고 직접 적절한 코드를 생성한다.
◦ 장점 : 프로그래머에게 편리
◦ 단점 : 컴파일러가 매우 무거워 짐
◦ 실제로 적은 수의 표준 함수를 이용하는 파스칼 언어는 이 방법을 택한다.
◦ C는 표준 함수가 매우 많다. 따라서 적용할 수 없다.
◦ 모든 표준 C함수를 하나의 재배치 가능 목적 모듈에 넣고, 프로그래머가 자신의 코드와 링크한다.
◦ 장점 : 표준 함수들의 구현을 컴파일러의 구현과 분리할 수 있고, 프로그래머에게 편리하다.
◦ 단점 : 모든 실행 파일들이 표준 함수들의 모음 전체의 복사본을 포함하게 되어 디스크 공간과 메모리를 극도로 낭비한다. 또한 단 하나의 표준 함수를 수정하더라도 전체를 재컴파일 해
야 하며, 모든 실행파일과 링크해야 한다
◦ 각각의 표준 함수를 각각의 재배치 파일로 생성한다.
◦ 장점 : 라이브러리를 수정했을 때 큰 소스코드 덩어리를 재컴파일 할 필요가 없다. (컴파일 시간이 줄어 듬)
◦ 단점 : 함수 하나하나 링크해야 한다. 프로그래머에게 불편하다.
31.
라이브러리
◦ 이러한 방법들로인한 단점을 보완하기 위해 라이브러리가 생겼다.
◦ 여러 함수를 모아둔 라이브러리를 링크함으로써 함수를 이용할 수 있다.
◦ 함수를 일일이 링크하는 것보다는 간단하다.
◦ 오브젝트 파일 전체를 합쳐서 실행 가능한 파일을 만드는 것이 아니라 필요한 함수의 코드만을 합쳐서 만든다.
◦ 또한 동적 라이브러리는 실행 파일에 코드를 합치지 않고도 함수를 이용하게 해 준다.
◦ 오른쪽은 C 런타임 라이브러리라 불리는 라이브러리이다.
◦ printf 등 ANSI 표준 C함수들이 들어있다.
32.
라이브러리
◦ 라이브러리에는 두종류가 있다.
◦ 정적 라이브러리(static library)
◦ 정적 라이브러리는 컴파일 시 실행 파일에 함수 코드를 넣는다.
◦ 장점
◦ 아예 실행 파일에 함수의 코드를 써 넣으므로 한 번 링크하면 추가적인 링킹 과정의 필요가 없다.
◦ 실행의 독립성이 있다.
◦ 단점
◦ 실행파일의 크기가 커 진다.
◦ 각 실행 파일이 라이브러리의 코드를 가지고 있으므로 비효율 적이다.
◦ 동적 라이브러리(Dynamic library)
◦ 메모리와 디스크를 아끼기 위해 생겼다.
◦ 메모리에 하나의 라이브러리를 올려 둔다. 이것을 공유해 쓴다.
◦ 실행파일에 직접 코드를 넣지 않는다. 실행파일에 동적 라이브러리를 실행하기 위한 준비를 해 둔다.
◦ 로드 시간에 함수의 주소를 얻어온다.
◦ 장점
◦ 정적 라이브러리에 비해 메모리를 낭비하지 않는다.
◦ 단점
◦ 프로그램을 로딩하는 시간이 길어진다.
◦ 잘못 이용하면 해결하기 어려운 버그들을 만날 수 있다.
33.
라이브러리
◦ 동적 라이브러리(DLL)은한 번 누군가가 이용하면 물리 메모리(RAM + 하드디스크)에 상주한다.
◦ 다른 프로그램이 같은 DLL을 이용하려고 하면 또 다른 복사본을 이용하지 않고, 가상메모리에만 매핑해 준다.
◦ 가상메모리를 이용한 공유에 대한 자세한 설명은 가상메모리에서 하겠음
◦ 한 프로세스를 위한 가상메모리를 실행 파일 뿐만 아니라 DLL 파일로도 구성한다.
◦ DLL은 실행 파일에 포함되지 않지만, 매핑된 가상메모리 주소를 이용하여 접근이 가능해진다.
◦ 정적 라이브러리는 위와 같이 공유할 수 없다. 프로그램이 각자 자신의 코드영역에 적어 둔 함수 코드를 이용한다.
34.
정적 라이브러리
◦ 링커가lib 파일에서 이용하는 함수와 obj 파일을 합쳐서 실행 파일을 생성한다.
◦ 라이브러리와 합치기 전 컴파일을 할 때, 라이브러리 함수의 이름과 형태를 알 필요가 있다.
◦ 그래서 헤더파일이 필요하다.
◦ Stdio.h와 같은 유명한 헤더 파일들은 특정한 위치(비주얼 스튜디오가 알고있는 위치)에 저장되어 있다.
◦ 직접 만든 라이브러리의 헤더 파일은 위와 같은 경로에 두거나, 직접 경로를 설정해 주어야 한다.
◦ 편의를 위해 프로젝트 파일과 함께 두겠다.(파일을 찾을 때 살펴보는 곳 중 하나는 같은 디렉토리이기 때문이다)
35.
정적 라이브러리 실습– 라이브러리 만들
기
• 프로젝트를 만들고, 정적 라이브러리를 체크한다.
• C파일에는 함수 정의를, 헤더 파일에는 함수 선언을 적는다.
• 헤더파일은 라이브러리를 이용할 프로그램을
컴파일하기 위해 필요하다.
36.
정적 라이브러리 실습– 라이브러리 만들
기
• 컴파일하면 .lib 파일이 생성된다.
• 라이브러리를 이용하려는 코드와 같은 곳에
둔다.
• 파일을 찾을 위치를 선정해 줄 수도
있지만, 편의를 위해 이렇게 했다.
• 또한 헤더파일도 같은 곳에 두자.
37.
정적 라이브러리 실습– 라이브러리 만들
기
• 사용할 라이브러리 이름
• 원래 라이브러리 전부 써 주어야 하지만, 비주얼
스튜디오에서 프로젝트 설정에 적어주면 생략할 수 있다.
38.
동적 라이브러리
◦ 정적연결에서는 동적 라이브러리를 이용하기 위한 준비를 해 준다.
◦ 프로그램 로딩 시 이 준비된 정보를 이용하여 DLL을 이용할 수 있게 설정한다.
◦ 정확히 어떤 작업을 하는지에 대해서는 리버싱 PE헤더에서 다루겠음
◦ 동적 연결에서 동적 라이브러리를 이용할 수 있도록 해 준다.
◦ 정적 연결에서 준비해 준 정보를 이용하여 함수의 주소를 구한다.
◦ 구한 주소를 테이블에 저장한다.
◦ 동적 라이브러리는 두 가지 사용법이 있다.
◦ 암시적 연결
◦ 정적 라이브러리처럼 lib 파일과 헤더 파일을 이용하는 방법
◦ 명시적 연결
◦ 소스 코드에서 직접 DLL을 찾고 함수를 이용하는 방법
39.
동적 라이브러리 실습– 라이브러리 만들
기
Win32 프로젝트 – 응용프로그램종류 DLL, 추가옵션 빈
프로젝트 – 소스 파일 추가, 확장자 cpp
40.
동적 라이브러리 실습– 라이브러리 만들
기
위는 DLL 소스 코드이다.
아래는 헤더파일 내용이다.
41.
동적 라이브러리 실습– 라이브러리 만들
기
함수를 C형식으로 만들라는 의미 (컴파일러에게 알려줌)
• C++은 오버로딩이 된다. 그것은 컴파일 시 함수의
인자에 따라서 이름에 추가적인 정보를 저장하기
때문이다. 즉, 이름이 달라진다. 다른 언어에서 그 DLL을
사용하고자 한다면 extern “C”를 붙여주어야 한다. 이
문장을 붙이면 컴파일 시 함수의 이름을 바꾸지 않는다.
• 아니면 extern “C”를 빼고 소스코드 확장자를 c로 해도
됨
extern “C”없이 컴파일한 경우 함수 이름 extern “C” 하고 컴파일한 경우, 혹은 확장자가 c인 경우 함수 이름
42.
동적 라이브러리 실습– 라이브러리 만들
기
함수를 export 할 거라는 의미
• 이 지시자가 있어야 export와 관련된 정보를 적어준다(PE의 export directory 등)
• __declspec에 dllexport를 인자로 주면 export 함수라는 의미가 된다.
• __declspec에 dllimport를 인자로 주면 이 함수를 dll로부터 가져올 것이라는 의미가 된다.
• DLL을 이용하는 소스 코드에서 이용한다. 보통은 헤더파일에 써 둔다. 이 헤더파일을
include하면 함수를 import한다는 사실을 알 수 있다.
• 기타 __declspec의 인자로 들어갈 수 있는 것들이 궁금하다면 부록의 참고 사이트를 보자
43.
동적 라이브러리 실습– 암시적 연결
• 헤더파일과 컴파일 결과로 생성된 라이브러리
파일을 라이브러리를 이용할 프로젝트의 폴더에
넣어주자.
• 여기서의 lib는 정적 라이브러리에서의 lib 파일과는
다르다.
• 이 lib 파일에는 함수 코드가 들어있지 않다.
• DLL이 제공하는 함수의 정보(이름)을 가지고
있다.
동적 라이브러리 실습– 명시적 연결
보통 과제 할 때 만드는 평범한 프로젝트를 새로 만들고 코드를 쓰자
이 코드가 하는 일
• DLL을 불러온다.
• DLL 파일에서, 사용할 함수의 코드를 찾는다.
• 찾은 함수를 함수 포인터에 넣고, 이용한다.
• 실행하기 전, dll은 이 프로그램을 컴파일하여 만든 EXE와 같은 디렉토리에 옮기자.
• DLL 파일을 찾는 경로
• 해당 DLL을 이용하는 EXE가 있는 디렉터리
• 프로세스의 현재 디렉터리
• Windows 시스템 디렉터리
• Windows 디렉터리
• PATH 환경변수에 등록되어 있는 모든 디렉터리
46.
동적 라이브러리 실습– 명시적 연결
불러올 DLL의 핸들이 저장될 공간 선언
• 핸들은 windows에서, 각종 대상(object)에게 OS가 발급해 주는 것이다. (주민등록번호같은
것)
• 핸들을 통해서 object를 사용할 수 있다.
• 대상을 빠르게 구분하기 위해 정수형을 사용하며 중복되지 않는다.
• 핸들에 대해 궁금하다면 부록의 참고 사이트를 보자
47.
동적 라이브러리 실습– 명시적 연결
함수 포인터 선언
• DLL에서 찾은 함수를 가리킬 함수 포인터이다.
48.
동적 라이브러리 실습– 명시적 연결
DLL 파일 로딩
• LoadLibrary에 DLL의 경로를 적어준다. 이 예에서는 EXE파일과 DLL 파일을 같은 폴더에 두었으므로 이름만
적었다.
• LoadLibrary 함수가 성공하면 가져온 DLL의 핸들을 반환한다. 그 값을 hDll에 저장했다.
49.
동적 라이브러리 실습– 명시적 연결
DLL 파일에 저장된 Add함수의 위치 찾기
• GetProcAddress는 인자로 주어진 핸들과 문자열을 이용하여 주소를 반환한다.
그 주소를 함수 포인터로 캐스팅하여 Add에 저장했다.
동적 라이브러리 실습– 명시적 연결
정리하자면
• LoadLibrary 함수를 호출하여 DLL을 가상메모리에 올린다.
• 해당 DLL을 처음 이용한다면 물리 메모리에도 새로 올라간다.
• GetProcAddress 함수를 호출하여 이용하고 싶은 함수의 주소를 찾는다.
• 함수 포인터에 넣고 이용한다.
• FreeLibrary 함수를 호출하여 DLL을 가상메모리에서 내린다.
• 해당 DLL을 유일하게 이용했다면 물리 메모리에서도
내려가겠다.
53.
동적 라이브러리
◦ 명시적연결을 이용하면 동적으로 라이브러리를 가상메모리에 해제하거나 올릴 수 있다.
◦ 암시적 연결을 이용한다면 그럴 수 없다.
◦ 필요할 때 잠깐 쓰고 해제할 수 있다.
◦ 암시적 연결을 이용할 때도 LoadLibrary와 GetProcAddress 함수를 호출한다.
◦ 프로그램을 로딩할 때, 로더가 이 함수를 호출한다.
◦ 위 함수를 호출하여 얻은 함수 주소를 미리 준비한 영역에 적어준다.
◦ 기계어 코드는 미리 준비된 영역의 주소를 이용하도록 써 있다.
◦ 미리 어느 곳에 어떤 함수의 주소를 쓸 지 지정해두고, 기계어 코드에서 그 주소를 이용하게 한다. 로딩시에 약속된 위치
에 함수의 주소를 써 준다.
◦ DLL을 공유하는 프로세스가 더이상 없을 때 DLL이 물리 메모리에서 해제된다.