위치 독립 코드
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
위치 독립 코드는 메모리 상의 특정 주소에 종속되지 않고 어느 위치에서든 실행될 수 있는 코드를 의미한다. 초기 컴퓨터에서는 각 프로그램이 특정 주소에 로드되어야 했지만, 위치 독립 코드의 개발로 인해 메모리 재배치, 공유 모듈, 공유 라이브러리 사용이 가능해졌다. 현대 운영체제에서는 공유 라이브러리, 보안 강화, 특히 ASLR과 함께 사용되는 PIE(Position-Independent Executable) 실행 파일 구현에 활용된다. 다양한 운영체제에서 PIE를 지원하며, 안드로이드 롤리팝부터는 PIE 사용을 강제하고 있다. 위치 독립 코드는 메모리 효율성을 높이고 보안을 강화하는 데 기여한다.
더 읽어볼만한 페이지
- 라이브러리 - 바이너리 재컴파일러
- 라이브러리 - 동적 링크 라이브러리
동적 링크 라이브러리(DLL)는 윈도우 운영체제에서 프로그램 실행 시 필요한 코드와 데이터를 제공하며, 여러 프로그램에서 공유되어 메모리 효율성을 높이고 모듈성을 향상시키는 라이브러리 형식이다. - 운영체제 기술 - 프로세스
프로세스는 컴퓨터에서 실행되는 프로그램의 인스턴스로, 운영 체제가 시스템 자원을 효율적으로 관리하며 멀티태스킹 환경에서 독립적인 실행 흐름을 유지한다. - 운영체제 기술 - 커널 (컴퓨팅)
커널은 운영 체제의 핵심으로, 하드웨어와 소프트웨어 간 상호 작용을 관리하며 시스템 보안, 자원 관리, 하드웨어 추상화, 프로세스 스케줄링, 프로세스 간 통신, 다중 작업 환경 지원 등의 기능을 제공하고, 모놀리식, 마이크로, 혼합형 커널 등으로 구현되며 가상화 및 클라우드 컴퓨팅 환경에서 중요성이 커지고 있다. - 파일 포맷 - 바로 가기
바로 가기는 운영체제에서 파일, 폴더, 프로그램, 웹 페이지에 대한 참조를 제공하는 기능 및 파일로, 사용자들이 원본에 빠르게 접근하도록 GUI 환경의 사용성을 향상시킨다. - 파일 포맷 - EXE
EXE 파일 형식은 운영 체제에 따라 다양한 종류가 있는 실행 파일의 한 형태로, DOS MZ 실행 파일에서 PE, PE32+까지 발전해 왔으며, 코드, 데이터, 스택을 별도 관리하고 재배치 항목을 통해 실행 환경에 유연하게 대응하는 특징을 가진다.
위치 독립 코드 | |
---|---|
'개요' | |
'정의' | '메모리의 특정 위치에 관계없이 올바르게 실행되는 기계어 코드' |
'특징' | '공유 라이브러리에서 특히 중요함' |
'영문명' | 'Position-independent code (PIC)' |
'동작 방식' | |
'코드 내 주소 지정' | '절대 주소 대신 상대 주소를 사용하여 메모리 내 위치에 독립적으로 동작' |
'데이터 접근' | '전역 오프셋 테이블 (GOT)을 통해 전역 변수에 접근' |
'함수 호출' | '프로시저 연결 테이블 (PLT)을 통해 외부 함수를 호출' |
'장점' | |
'코드 공유' | '여러 프로세스 간에 코드 공유가 가능하여 메모리 사용량 감소' |
'보안 강화' | '주소 공간 배치 랜덤화 (ASLR)와 함께 사용하여 보안 강화' |
'단점' | |
'성능 저하' | '상대 주소 계산 및 GOT/PLT 접근으로 인해 성능 저하 가능성 존재' |
'코드 크기 증가' | 'GOT/PLT 항목으로 인해 코드 크기 증가 가능성 존재' |
'구현' | |
'컴파일러 옵션' | '-fpic 또는 -fPIC 컴파일러 옵션을 사용하여 생성' |
'링커' | '공유 라이브러리 생성 시 위치 독립 실행 파일로 링크' |
'활용' | |
'공유 라이브러리' | '대부분의 현대 운영체제에서 공유 라이브러리 생성에 사용' |
'동적 로딩' | '플러그인 및 동적 로딩 모듈에서 사용' |
2. 역사
초기 컴퓨터에서는 코드가 특정 주소에 종속되어 실행되었다. 여러 작업을 동시에 실행하려면 운영자가 작업들이 필요로 하는 주소가 겹치지 않도록 주의 깊게 스케줄링해야 했다. 예를 들어, 급여 지급 프로그램과 수취 계정 프로그램이 모두 같은 주소에서 작동하도록 구축된 경우, 동시에 실행할 수 없었다. 이러한 문제를 해결하기 위해 더 유연한 위치 독립 코드가 발명되었다. 위치 독립 코드는 운영자가 임의의 주소에 로드하여 실행할 수 있었다.
MMU이 제공하는 동적 주소 변환 기능은 각 프로세스에 별도의 주소 공간을 할당하여 위치 독립 코드의 필요성을 줄였다. 위치 독립 코드는 위치 종속 코드보다 효율이 떨어졌기 때문에 동적 주소 변환이 더 나은 해결책으로 여겨졌다.
하지만 여러 작업이 동일한 코드를 공유할 때 메모리 낭비 문제가 발생했다. 완전히 동일한 프로그램을 실행하는 두 작업이 있을 때, 동적 주소 변환은 프로그램의 유일한 실체를 물리 메모리에 로드하고 이를 두 작업의 가상 주소 공간에 매핑하여 메모리 사용을 최적화했다.
서로 다른 프로그램이라도 많은 코드를 공유하는 경우가 많았다. 예를 들어, 급여 지급 프로그램과 수취 계정 프로그램은 많은 서브루틴을 공유할 수 있었다. 이러한 경우, 공유 모듈(공유 라이브러리는 공유 모듈의 일종) 개념이 도입되었다. 공유 모듈은 물리 메모리에 한 번만 로드되어 여러 프로그램의 가상 주소 공간에 매핑되어 메모리 사용량을 절약했다.
위치 독립 코드는 애플리케이션뿐만 아니라 OS 자체에서도 사용되었다. 초기 페이징 방식은 가상 주소 공간을 사용하지 않았기 때문에, OS는 필요에 따라 개별 모듈을 로드하고 덮어써야 했다. OS 모듈은 비어 있는 메모리에서 작동 가능해야 했으므로 위치 독립 코드로 작성되었다.
가상 기억의 발명으로 OS 자체도 광대한 가상 주소 공간을 가질 수 있게 되었고, 각 OS 모듈에 별도의 영구적인 가상 주소를 할당할 수 있게 되면서 OS 모듈의 위치 독립 코드 사용은 사라졌다.
2. 1. 초기 컴퓨터 환경
초기의 컴퓨터들에서 코드는 위치 의존적이었다. 각 프로그램은 특정 주소에서 실행되도록 빌드되었고 로드되었다. 여러 작업들을 동시에 실행하기 위해서는 작업들이 같은 주소를 사용하지 않도록 해야 했다. 예를 들어, 급여 프로그램과 회계 프로그램이 모두 32K 주소에서 실행되도록 빌드되었다면 동시에 실행될 수 없었다.초기 컴퓨터 환경에서는 운영 체제가 없었고, 멀티태스킹 기능도 없었다. 프로그램은 주기억장치에 로드되거나 자기 드럼에 저장되어 거기서 직접 실행되었다. 한 번에 하나의 프로그램만 실행되었기 때문에, 이러한 환경에서는 위치 독립 코드의 필요성이 크지 않았다.
IBM 701, UNIVAC I과 같은 초기 컴퓨터들은 프로그램이 특정 주소에 로드되어 실행되도록 설계되었다.
2. 2. 위치 독립 코드의 등장
초기 컴퓨터에서 코드는 위치 의존적이었다. 각 프로그램은 특정 주소에서 실행되도록 빌드되었고, 동시에 여러 작업을 실행하려면 각 작업이 같은 주소를 사용하지 않도록 해야 했다. 예를 들어, 32K 주소에서 실행되도록 빌드된 급여 프로그램과 회계 프로그램은 동시에 실행될 수 없었다. 때로는 프로그램의 여러 버전을 만들어 각각 다른 로드 주소에 빌드하기도 했다.이러한 상황을 개선하기 위해 프로그램이 메모리에 로드될 때 재배치하는 기능이 필요했다. 이를 통해 프로그램의 한 복사본만 필요하게 되었지만, 한 번 로드된 프로그램은 움직일 수 없었다.
멀틱스(1964)와 같은 세그먼트된 시스템에서는 프로그램의 주소가 현재 세그먼트에 상대적이기 때문에 코드가 본질적으로 위치 독립적이었다.
비 세그먼트 시스템에서도 이러한 제약을 제거하기 위해 위치 독립 코드가 개발되었다. 위치 독립 프로그램은 메모리의 어느 주소에나 로드될 수 있었다.
하지만 동적 주소 변환(MMU가 제공하는 기능)의 발명으로 모든 프로세스가 자신의 독립적인 주소 공간을 가질 수 있게 되면서, 위치 독립 코드의 필요성은 근본적으로 줄어들었다. 그러나 같은 코드를 동시에 여러 작업이 사용하는 경우에는 가상 공간의 낭비가 발생했다. 만약 두 작업이 완전히 똑같은 프로그램이라면, 동적 주소 변환은 시스템이 두 작업의 주소 32K를 실제 메모리의 같은 위치로 매핑하여 프로그램의 단일 사본만 유지하도록 하는 해결책을 제공했다.
서로 다른 프로그램이 같은 코드를 공유할 수도 있었다. 예를 들어, 급여 프로그램과 회계 프로그램은 모두 똑같은 서브루틴을 포함할 수 있었다. 공유된 모듈(공유 라이브러리는 공유된 모듈의 한 형태)은 한 번 로드되어 두 주소 공간에 매핑되었다.
2. 3. 동적 주소 변환과 공유 라이브러리
동적 주소 변환(MMU가 제공하는 기능)의 발전은 각 프로세스에 독립적인 주소 공간을 제공함으로써 위치 독립 코드의 필요성을 어느 정도 감소시켰다. 그러나 같은 코드를 사용하는 여러 작업들이 동시에 실행될 경우 가상 공간의 낭비가 발생했다. 예를 들어, 두 작업이 완전히 동일한 프로그램을 실행하는 경우, 동적 주소 변환은 시스템이 두 작업의 주소를 실제 메모리의 같은 위치에 매핑하여 프로그램의 단일 사본만 유지하도록 했다.하지만 서로 다른 프로그램들이 공통 코드를 공유하는 경우가 많았다. 예를 들어, 급여 프로그램과 회계 프로그램은 모두 동일한 서브루틴을 포함할 수 있었다. 이러한 상황에서 공유 모듈(공유 라이브러리는 공유 모듈의 한 형태) 개념이 등장했다. 공유 라이브러리는 한 번 로드되어 여러 프로그램의 주소 공간에 매핑될 수 있었다. 이를 통해 메모리 사용량을 줄이고 효율성을 높일 수 있었다.
2. 4. 현대 운영 체제에서의 발전
현대 운영 체제에서 위치 독립 코드는 공유 라이브러리뿐만 아니라 보안 강화에도 활용되고 있다. '''위치 독립 실행 파일'''(PIE: Position-independent executables)은 주소 공간 배치 난수화(ASLR)와 함께 사용되어 Return-to-libc 공격과 같은 보안 위협을 완화하는 데 기여한다.[13][14]macOS와 iOS는 각각 버전 10.7 및 4.3부터 PIE 실행 파일을 완전히 지원한다. OpenBSD는 2013년 5월 1일에 출시된 OpenBSD 5.3부터 대부분의 아키텍처에서 기본적으로 PIE를 활성화했다.
/bin
및 /sbin
디렉터리의 실행 파일과 같은 정적으로 연결된 바이너리에서 PIE에 대한 지원은 2014년 말경에 추가되었다. 페도라 23부터는 PIE 활성화를 기본값으로 한 빌드 패키지를 제공한다. 우분투 17.10은 모든 아키텍처에서 기본적으로 PIE를 활성화했다. 안드로이드는 젤리빈에서 PIE에 대한 지원을 활성화하고 롤리팝에서 비 PIE 링커 지원을 제거했다.3. 기술적 사항들
공유 라이브러리 내 프로시저 호출은 일반적으로 작은 프로시저 링크 테이블 스텁을 통해 이루어지며, 최종 함수를 호출한다. 이를 통해 공유 라이브러리는 이전에 로드된 라이브러리의 함수 호출을 상속받을 수 있다.[1]
위치 독립 코드의 데이터 참조는 전역 변수 주소를 저장하는 전역 오프셋 테이블(GOT)을 통해 이루어진다. 컴파일 유닛 또는 객체 모듈 당 하나의 GOT가 존재하며, 코드에서 고정된 오프셋을 가진다(라이브러리 링크 전까지는 알 수 없음). 링커는 모듈을 링크하여 공유 라이브러리를 생성할 때 GOT들을 합병하고 코드의 최종 오프셋을 설정한다. 이후 공유 라이브러리 로딩 시 오프셋 조정은 필요하지 않다.[1]
전역 변수 접근 시 위치 독립 함수는 현재 프로그램 카운터 값을 통해 GOT의 절대 주소를 결정한다. 이는 스택(x86) 또는 특정 레지스터(파워PC, SPARC, MIPS)에서 반환 값을 얻는 가짜 함수 호출 형태를 띨 수 있다. 모토로라 68000, Motorola 6809, WDC 65C816, Knuth's MMIX, ARM, x86-64 등의 프로세서 아키텍처는 프로그램 카운터 오프셋을 통해 데이터를 참조하여 위치 독립 코드를 더 작고 효율적으로 만든다.[1]
3. 1. 프로시저 호출
공유 라이브러리 내의 프로시저 호출은 일반적으로 작은 프로시저 링크 테이블(PLT) 메서드 스텁을 통해 이루어지며, 이 스텁이 결정적인 함수를 호출한다. 이는 특히 공유 라이브러리가 자체 버전을 사용하는 대신 이전에 로드된 라이브러리에서 특정 함수 호출을 상속받을 수 있게 해준다.[1]3. 2. 데이터 참조
위치 독립 코드에서 데이터 참조는 일반적으로 전역 오프셋 테이블(GOT)을 통해 이루어진다. GOT는 접근되는 모든 전역 변수의 주소를 저장하며, 컴파일 단위 또는 객체 모듈 당 하나씩 존재한다.[1] 링커가 공유 라이브러리를 생성하기 위해 모듈을 링크할 때, GOT들을 합병하고 코드에서 최종 오프셋을 설정한다. 이후에 공유 라이브러리를 로딩할 때 오프셋을 조정할 필요는 없다.[1]전역 변수에 접근하는 위치 독립 함수들은 현재 프로그램 카운터 값을 통해 GOT의 절대 주소를 결정한다. 이는 가짜 함수 호출 형태를 갖거나, 특정 레지스터를 이용하는 방식으로 이루어진다.[1] 모토로라 68000, ARM, x86-64 등 몇몇 프로세서 아키텍처는 프로그램 카운터의 오프셋을 통해 데이터를 참조하여 위치 독립 코드를 더 작고 효율적으로 만든다.[1]
3. 3. 프로그램 카운터 상대 주소 지정
모토로라 68000, ARM, x86-64 등 일부 프로세서 아키텍처는 프로그램 카운터 상대 주소 지정을 지원한다.[1] 이 기능은 위치 독립 코드를 더 작고 효율적으로 만들며, 레지스터 요구를 줄여 성능을 향상시킨다.[1]4. 운영 체제별 구현
마이크로소프트 윈도우와 유닉스 계열 운영 체제는 위치 독립 코드 구현 방식에 차이가 있다.
윈도우의 DLL은 32비트 버전에서 위치 독립 코드를 사용하지 않아, 유닉스 계열의 공유 라이브러리와는 다르게 동작한다. DLL은 메모리에 로드된 후 재배치되어야 하며, 프로세스 간 공유가 어려울 수 있다.[7] 시스템 DLL은 주로 사전에 다른 고정 주소에 매핑되지만, 필요에 따라 임의 주소에 로드될 수 있도록 재배치 정보를 포함한다. 윈도우에서는 이 공유 기법을 "메모리 매핑"이라고 부른다. DLL은 생성 시 "희망하는" 기본 주소(RVA)를 지정하지만, 동일한 주소를 가진 여러 DLL이 존재할 경우 겹치는 DLL은 링크 시 재배치된다. 윈도우 로더는 실행 파일을 로드할 때 각 DLL이 올바른 주소에 로드되었는지 확인하고, 필요하면 재배치한다.[8] 64비트 버전 윈도우에서는 x64의 명령 포인터 상대 어드레싱 지원으로 DLL에 위치 독립 코드를 사용하고 재배치 방식은 사용하지 않는다.[9]
macOS나 리눅스와 같은 유닉스 계열 플랫폼은 윈도우와 달리 위치 독립 코드를 적극적으로 활용하며, 사전 바인딩(prebinding) 방식도 지원한다. macOS에서는 이를 prebinding이라고 하며, 리눅스에는 같은 기능을 제공하는 `prelink` 프로그램이 있다.
4. 1. 마이크로소프트 윈도우
마이크로소프트 윈도우의 동적 링크 라이브러리(DLL)는 일반적인 위치 독립 코드를 사용하지 않지만, 재배치(relocation)를 통해 주소 충돌 문제를 해결한다.[12] 윈도우 비스타 이전 버전에서는 DLL 로더가 각 프로세스 내에서 재배치를 수행하여 프로세스 간 공유가 불가능했지만, 윈도우 비스타 이후 버전에서는 커널 메모리 관리자가 DLL 재배치를 수행하여 여러 프로세스 간 공유를 가능하게 하고, 주소 공간 배치 난수화(ASLR)를 지원한다.32비트 버전 윈도우에서 DLL은 위치 독립 코드를 사용하지 않아 유닉스 계열 시스템의 공유 라이브러리와는 다르다. 따라서 DLL을 메모리에 로드한 후 재배치해야 하며, 프로세스 간 공유가 불가능할 수 있다.[7] 이러한 제약을 완화하기 위해 대부분의 시스템 DLL은 사전에 다른 고정 주소에 매핑되어 있지만, 필요에 따라 임의 주소에 로드할 수 있도록 재배치 정보를 포함하고 있다.
DLL은 생성 시 "희망하는" 기본 주소(RVA)를 지정하지만, 여러 DLL이 동일한 주소를 가질 경우 겹치는 DLL은 재배치된다. 윈도우 로더는 실행 파일을 로드할 때 각 DLL이 올바른 주소에 로드되었는지 확인하고, 필요한 경우 재배치한다. 이를 통해 실행 파일은 여러 프로세스 간 공유될 수 있지만, DLL 자체는 공유되지 않을 수 있다.[8]
64비트 버전 윈도우에서는 x64 아키텍처의 명령 포인터 상대 어드레싱 지원 덕분에 DLL에 위치 독립 코드를 사용하고 재배치 방식을 폐지했다.[9]
4. 2. 유닉스 계열 시스템 (Linux, macOS, *BSD 등)
macOS와 iOS는 각각 버전 10.7과 4.3에서 위치 독립 실행 파일(PIE)을 완전히 지원한다.[13][14] OpenBSD는 2013년 5월 1일 릴리스된 5.3 이후로 대부분의 아키텍처에서 기본값으로 PIE를 활성화했다.[15]/bin
및 /sbin
디렉터리의 실행 파일과 같은 정적으로 연결된 바이너리에서 PIE에 대한 지원은 2014년 말경에 추가되었다. 페도라 23부터 PIE 활성화를 기본값으로 한 빌드 패키지를 제공한다. 우분투 17.10은 모든 아키텍처에서 기본적으로 PIE를 활성화했다. 젠투의 새 프로필은 이제 기본적으로 PIE를 지원하며, 2017년 7월경 데비안은 기본적으로 PIE를 활성화했다.4. 3. 안드로이드
안드로이드는 젤리빈에서 PIE를 지원하기 시작했고, 롤리팝부터는 비 PIE 링커 지원을 제거하여 PIE 사용을 강제하고 있다.5. 한국 정보통신 환경에 주는 의의
위치 독립 코드는 주소 공간 배치 난수화(ASLR)와 함께 사용되어 Return-to-libc 공격과 같은 익스플로잇 공격을 어렵게 만들어 보안을 강화한다. 이는 PaX나 Exec Shield 같은 보안 중심 리눅스 배포판에서 사용된다.[13][14][17]
5. 1. 보안 강화
주소 공간 배치 난수화(ASLR)와 함께, PIE는 바이너리에서 실행 가능한 코드의 오프셋을 알아야 하는 익스플로잇을 사용하는 공격 (예: Return-to-libc 공격) 시 공격자가 실행 가능한 코드가 어디에 있는지 알 수 없게 하여 보안을 강화한다.[13][14] 이는 PaX나 Exec Shield 같은 보안 중심 리눅스 배포판에서 사용된다.[17]참조
[1]
간행물
Shared Libraries in SunOS
https://www.cs.corne[...]
[2]
서적
The Multics system; an examination of its structure
MIT Press
[3]
논문
Virtual Memory, Processes, and Sharing in Multics
https://multicians.o[...]
Association for Computing Machinery
2024-07-21
[4]
웹사이트
Address Space Layout Randomization
https://lettieri.iet[...]
[5]
서적
Linkers and Loaders
Morgan-Kauffman
1999-10
[6]
웹사이트
Position Independent Code internals
http://www.gentoo.or[...]
2009-12-03
[7]
웹사이트
The End of DLL Hell
http://msdn2.microso[...]
2007-04-26
[8]
웹사이트
An In-Depth Look into the Win32 Portable Executable File Format
http://msdn.microsof[...]
2012-01-28
[9]
웹사이트
MSDN Magazine - Under the Hood - Programming for 64-bit Windows
http://msdn.microsof[...]
2011-02-09
[10]
서적
Linkers and Loaders
Morgan-Kauffman
2016-03-17
[11]
웹인용
Position Independent Code internals
http://www.gentoo.or[...]
2009-12-03
[12]
문서
https://view.officea[...]
[13]
웹인용
iphone - Non-PIE Binary - The executable 'project name' is not a Position Independent Executable. - Stack Overflow
http://stackoverflow[...]
[14]
웹인용
iOS Developer Library
https://developer.ap[...]
[15]
웹인용
OpenBSD 5.3 Release
http://www.openbsd.o[...]
2014-10-10
[16]
웹인용
Heads Up: Snapshot Upgrades for Static PIE
http://undeadly.org/[...]
2014-12-24
[17]
문서
http://fedoraproject[...]
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com