위치 독립 코드
Position-independent code이 글은 검증을 위해 추가 인용문이 필요합니다. : 구애받지 코드 뉴스 · · · 학자 · JSTOR ( 1월) ( 템플릿 삭제 및 시기 ) |
컴퓨팅에서 PIC(Position[1] Independent Code)[2] 또는 PIE(Position Independent[1] Executable)는 프라이머리 메모리 어딘가에 배치되어 절대 주소에 관계없이 올바르게 실행되는 기계 코드입니다.PIC는 일반적으로 공유 라이브러리에서 사용되며, 각 프로그램주소 공간의 다른 메모리(예를 들어 다른 공유 라이브러리)와 중복되지 않는 위치에 동일한 라이브러리 코드를 로드할 수 있습니다.또한 PIC는 MMU가 [3]없는 오래된 컴퓨터 시스템에서도 사용되었기 때문에 운영체제는 MMU가 없는 시스템의 단일 주소 공간 내에서도 애플리케이션을 서로 멀리할 수 있었습니다.
위치 비의존 코드는 수정 없이 임의의 메모리 주소로 실행할 수 있다.이는 올바르게 [1]기능하기 위해 특정 위치에 로드해야 하는 절대 [1]코드 및 링커 또는 프로그램 로더가 실행 전에 프로그램을 수정하여 특정 메모리 [1]위치에서만 실행할 수 있도록 하는 LTL([1]Load-Time Locatable) 코드와는 다릅니다.위치 독립 코드를 생성하는 것은 컴파일러의 기본 동작이지만 절대 주소 사용을 허용하지 않는 등 일부 언어 기능의 사용에 제한이 있을 수 있습니다(위치 독립 코드는 상대 주소 지정을 사용해야 합니다).특정 메모리 주소를 직접 참조하는 명령어는 실행 속도가 빨라질 수 있습니다.이 명령어를 동등한 상대 주소 지정 명령어로 대체하면 실행 속도가 약간 느려질 수 있습니다.다만, 최신의 프로세서는 그 차이를 거의 무시할 [4]수 있습니다.
역사
IBM 701[5](1952년 4월 29일)이나 UNIVAC I(1951년 3월 31일)와 같은 초기 컴퓨터에서는 각 프로그램이 특정 주소로 로드되어 실행되도록 제작되었습니다.그 초기 컴퓨터들은 운영체제가 없었고 멀티태스킹이 가능하지도 않았다.프로그램은 메인 스토리지에 로드되어(또는 거기서 직접 실행할 수 있도록 자기 드럼에 저장됨) 한 번에 하나씩 실행됩니다.이러한 운영 컨텍스트에서는 위치 독립 코드가 필요하지 않았습니다.
IBM System/360(1964년 4월 7일)은 코드 위치 독립성을 염두에 두고 UNIVAC [6]III와 유사한 잘린 어드레싱으로 설계되었습니다.잘린 어드레싱에서는, 메모리 주소는 베이스 레지스터와 오프셋으로부터 계산된다.프로그램 시작 시 프로그래머는 베이스 레지스터를 로드하여 주소성을 확립해야 합니다.일반적으로 프로그래머는 USING 의사 연산으로도 어셈블러에 알립니다.프로그래머는 진입점 주소(일반적으로 R15)를 포함하는 것으로 알려진 레지스터에서 베이스 레지스터를 로드하거나 BALR(Branch And Link, Register 형식) 명령을 사용하여 다음 시퀀셜 명령의 주소를 베이스 레지스터에 저장할 수 있습니다.이 명령은 각 명령에서 명시적으로 또는 암묵적으로 코드화됩니다.프로그램내의 스토리지 장소를 참조.코드 또는 데이터에 여러 개의 기본 레지스터를 사용할 수 있습니다.이러한 명령에서는 풀 24, 31, 32 또는 64비트주소(4 또는 8바이트)를 보유할 필요가 없고, 대신 베이스 레지스터 번호(4비트 부호화)와 12비트주소 오프셋(12비트 부호화)을 보유할 필요가 있기 때문에 필요한 메모리는 2바이트뿐입니다.
이 프로그래밍 기술은 IBM S/360 유형 시스템에서 표준입니다.오늘날의 IBM System/z까지 사용되었습니다.어셈블리 언어로 코딩할 때 프로그래머는 위에서 설명한 바와 같이 프로그램의 주소성을 확립해야 하며 동적으로 할당된 스토리지를 위해 다른 기본 레지스터를 사용해야 합니다.이러한 어드레싱은 컴파일러가 자동으로 처리합니다.
IBM의 초기 운영 체제 DOS/360(1966)은 가상 스토리지를 사용하지 않았지만(System S/360의 초기 모델은 가상 스토리지를 지원하지 않았기 때문에), PHASE name,* JCL(Job Control Language) 문을 통해 로드하는 동안 프로그램을 임의(또는 자동으로 선택된) 스토리지 위치에 배치할 수 있었습니다.
따라서 가상 스토리지가 없는 S/360 시스템에서는 어떤 스토리지 위치에서도 프로그램을 로드할 수 있지만, 이를 위해서는 해당 프로그램을 저장할 수 있는 충분한 크기의 연속 메모리 영역이 필요했습니다.메모리 플래그멘테이션은 크기가 다른 모듈을 로드하거나 언로드할 때 발생할 수 있습니다.가상 스토리지에는 이러한 제한이 없습니다.
DOS/360 및 OS/360은 PIC를 지원하지 않지만 OS/360의 과도 SVC 루틴은 재배치 가능한 주소 상수를 포함할 수 없으며 재배치 없이 과도 영역에서 실행될 수 있습니다.
가상 스토리지는 IBM 최초의 멀티태스킹 운영 및 시분할 운영 체제 TSS/360을 지원하기 위해 (1965년) IBM System/360 모델 67에 처음 도입되었습니다. 이후 버전의 DOS/360(DOS/VS 등) 및 이후 IBM 운영 체제에서는 모두 가상 스토리지를 사용했습니다.잘린 어드레싱은 기본 아키텍처의 일부로 유지되며 여러 모듈을 동일한 가상 주소 공간에 로드해야 하는 경우에도 여전히 유용합니다.
비교 방식 버로스 MCP와 같은 버로우 B5000(1961년)과 Multics,(1964년)을 일찍 분절된 시스템으로 페이징 시스템과 같은 IBMTSS/360(1967년)[를]나 기본과 bounds[b]시스템과 같은 GECOS에 GE625와 EXEC에 유니 백 1107년, 코드 또한 본질적으로 위치 독립, 이후 주소에 있는 프로그램이 상대적으로. curren절대가 아닌 t 세그먼트.
동적 주소 변환(MMU에 의해 제공되는 기능)의 발명은 모든 프로세스가 독자적인 주소 공간(주소의 범위)을 가질 수 있기 때문에 원래 위치 독립 코드의 필요성을 줄였습니다.그러나 동일한 코드를 사용하여 여러 작업을 동시에 수행하면 물리적 메모리가 낭비됩니다.두 작업이 완전히 동일한 프로그램을 실행하는 경우 동적 주소 변환은 두 개의 다른 작업의 주소 32K를 프로그램의 단일 복사본을 포함하는 동일한 바이트의 실제 메모리에 매핑하는 것만으로 해결 방법을 제공합니다.
다른 프로그램이 공통 코드를 공유할 수 있습니다.예를 들어 급여 프로그램과 외상매출금 프로그램은 모두 동일한 종류의 서브루틴을 포함할 수 있다.공유 모듈(공유 라이브러리는 공유 모듈의 한 형태)이 한 번 로드되어 2개의 주소 공간에 매핑됩니다.
기술적 세부사항
공유 라이브러리 내의 프로시저 콜은 일반적으로 스몰프로시저 링크테이블 스텁을 통해 이루어지며, 그 후에 최종 함수를 호출합니다.이를 통해 공유 라이브러리는 자신의 버전을 사용하는 대신 이전에 로드된 라이브러리에서 특정 함수 호출을 상속할 수 있습니다.
위치에 의존하지 않는 코드로부터의 데이터 참조는 일반적으로 액세스되는 모든 글로벌 변수의 주소를 저장하는 Global Offset Table(GOT; 글로벌오프셋 테이블)을 통해 간접적으로 이루어집니다.컴파일 유닛 또는 오브젝트 모듈마다 1개의 GOT가 있으며, 이 GOT는 코드에서 고정된 오프셋에 위치합니다(라이브러리가 링크될 때까지 이 오프셋을 알 수 없습니다).링커는 모듈을 연결하여 공유 라이브러리를 생성할 때 GOT를 병합하고 코드로 최종 오프셋을 설정합니다.나중에 공유 라이브러리를 로드할 때 오프셋을 조정할 필요가 없습니다.
글로벌 데이터에 액세스하는 위치 독립 함수는 자체 현재 프로그램 카운터 값이 주어진 GOT의 절대 주소를 결정하는 것으로 시작합니다.이것은 종종 스택(x86) 상의 반환값을 특정 표준 레지스터(SPARC, MIPS) 또는 특수 레지스터(POWER/PowerPC/Power ISA)에서 얻기 위해 가짜 함수 호출의 형태를 취합니다.이 값은 미리 정의된 표준 레지스터로 이동하거나 해당 표준 레지스터(PA-RISC, Alpha 및 ES/903)로 가져올 수 있습니다.Motorola 68000, Motorola 6809, WDC 65C816, Knuth의 MMIX, ARM 및 x86-64와 같은 일부 프로세서 아키텍처에서는 프로그램 카운터에서 오프셋으로 데이터를 참조할 수 있습니다.이는 특히 위치 독립 코드를 더 작게 만들고 레지스터 요구량을 줄여 효율성을 높이는 것을 목표로 합니다.
Windows DLL
Microsoft Windows 의 Dynamic Link Library(DLL; 다이나믹 링크 라이브러리)에서는, CALL 명령의 배리언트 E8 이 사용됩니다(다음 명령에 대한 콜 근접, 상대, 변위).DLL이 로드될 때 이러한 지침을 수정할 필요는 없습니다.
일부 글로벌 변수(예를 들어 문자열 리터럴 배열, 가상 함수 테이블)는 동적 라이브러리의 코드 섹션에 각각 있는 데이터 섹션에 객체의 주소를 포함할 것으로 예상되므로 글로벌 변수의 저장된 주소는 DLL이 로드된 주소를 반영하도록 업데이트해야 합니다.다이내믹 로더는 글로벌 변수에 의해 참조되는 주소를 계산하여 해당 글로벌 변수에 값을 저장합니다.이것에 의해, 이러한 글로벌 변수를 포함한 메모리 페이지의 카피 온 라이트(copy-on-write)가 트리거 됩니다.코드가 있는 페이지와 코드 또는 글로벌 데이터에 대한 포인터가 포함되지 않은 글로벌 변수가 있는 페이지는 프로세스 간에 공유된 상태로 유지됩니다.이 작업은 임의의 주소로 동적 라이브러리를 로드할 수 있는 모든 OS에서 수행해야 합니다.
Windows Vista 이후의 Windows 버전에서는 DLL 및 실행 파일의 재배치는 커널 메모리 매니저에 의해 이루어지며, 커널 메모리 매니저는 재배치된 바이너리를 여러 프로세스에서 공유합니다.이미지는 항상 기본 주소에서 재배치되어 주소 공간 레이아웃 랜덤화(ASLR)[7]를 실현합니다.
Vista보다 이전 버전의 Windows에서는 이미지의 런타임 재배치를 피하기 위해 링크 시 충돌하지 않는 고정 주소로 시스템 DLL을 사전 링크해야 합니다.이러한 이전 버전의 Windows에서의 런타임 재배치는 각 프로세스의 컨텍스트 내에서 DLL 로더에 의해 실행되며, 결과적으로 각 이미지의 재배치된 부분은 프로세스 간에 공유할 수 없게 됩니다.
Windows 에서의 DLL 의 처리는, 이전의 OS/2 순서와는 다릅니다.OS/2는 세 번째 대안을 제시하여 위치 독립적이지 않은 DLL을 메모리의 전용 "공유 영역"에 로드하고 로드된 후 매핑합니다.DLL의 모든 사용자는 동일한 메모리 내 복사본을 사용할 수 있습니다.
멀티틱스
Multics에서 각 절차는[c] 개념적으로 코드 세그먼트와 링크 세그먼트를 가집니다.코드 세그먼트에는 코드만 포함되어 있으며 링크 섹션은 새 링크 세그먼트의 템플릿 역할을 합니다.포인터 레지스터 4(PR4)는 절차의 링크 세그먼트를 가리킵니다.프로시저를 호출하면 PR4가 콜처의 링크 세그먼트에 포인터와 함께 로드되기 전에 스택에 저장됩니다.그 절차를은 동적 연결 메커니즘은으로 성공한 Segment로 나타나 표(한국), 새로운 연결 부분 구축, 호출자의 연결 부분에서 그들의 세그먼트 번호를 뒤로 하고 간접 poin의 깃발을 다시 설정한 절차와 그 연계 부분 추가할 수 있는 첫번째 전화에 함정을 유발하는 것은 깃발로 간접적인 포인터 pair[8]을 사용한다.기r 쌍
TSS
IBM S/360 Time Sharing System(TSS/360 및 TSS/370)에서 각 절차는 읽기 전용 공개 CSPET 및 쓰기 가능한 개인 프로토타입 섹션(PSECT)을 가질 수 있습니다.발신자는, 루틴의 V상수를 General Register 15(GR15)에 로드해, 루틴의 PSECT의 R상수를, GR13이라고 [9]하는 세이브 영역의 19번째 워드에 카피한다.
다이내믹[10] 로더는 첫 번째 페이지에 장애가 발생할 때까지 프로그램 페이지를 로드하거나 주소 상수를 확인하지 않습니다.
위치에 구애받지 않는 실행 파일
PIE(Position Independent Executable)는 전적으로 위치 독립 코드로 만들어진 실행 가능한 이진 파일입니다.시스템에 따라서는 PIC 실행 파일만 실행되지만 사용되는 다른 이유도 있습니다.PIE 바이너리는 보안에 중점을 둔 일부 Linux 배포에서 사용되며, PaX 또는 Exec Shield가 주소 공간 레이아웃 랜덤화를 사용하여 공격자가 바이너리 실행 가능 코드의 오프셋을 알고 있는 공격(예: Return-to-libc 공격)을 통해 보안 공격 중에 기존 실행 가능한 코드가 어디에 있는지 알 수 있습니다.
애플의 macOS와 iOS는 각각 버전 10.7과 4.3을 기준으로 PIE 실행 파일을 완전히 지원합니다. PIE가 아닌 실행 파일이 Apple App Store에 승인을 위해 제출될 때 경고가 발생하지만 아직 까다로운 요구사항이[when?] 없으며 PIE가 아닌 응용 프로그램이 [11][12]거부되지 않았습니다.
OpenBSD는 2013년 [13]5월 1일에 출시된 OpenBSD 5.3 이후 대부분의 아키텍처에서 기본적으로 PIE를 사용하도록 설정되어 있습니다.의 실행 파일 등 정적으로 링크된 바이너리에서의 PIE 지원/bin
그리고./sbin
디렉토리는 [14]2014년 말에 추가되었습니다.openSUSE는 2015-02년에 PIE를 기본값으로 추가했습니다.Fedora 23부터 Fedora 유지보수는 [15]PIE를 디폴트로 유효하게 한 패키지를 구축하기로 결정했습니다.Ubuntu 17.10에서는 모든 [16]아키텍처에서 기본적으로 PIE가 활성화되어 있습니다.Gentoo의 새로운 프로파일은 [17]디폴트로 PIE를 지원하게 되었습니다.2017년 7월경,[18] Debian은 디폴트로 PIE를 유효하게 했습니다.
Android는 Jelly[19] Bean에서 PIE를 지원하며 롤리팝에서 [20]PIE 이외의 링커 지원을 제거했습니다.
「 」를 참조해 주세요.
메모들
레퍼런스
- ^ a b c d e f "Types of Object Code". iRMX 86 Application Loader Reference Manual (PDF). Intel. pp. 1-2, 1-3. Retrieved 2017-08-21.
[…] Absolute code, and an absolute object module, is code that has been processed by LOC86 to run only at a specific location in memory. The Loader loads an absolute object module only into the specific location the module must occupy. Position-independent code (commonly referred to as PIC) differs from absolute code in that PIC can be loaded into any memory location. The advantage of PIC over absolute code is that PIC does not require you to reserve a specific block of memory. When the Loader loads PIC, it obtains iRMX 86 memory segments from the pool of the calling task's job and loads the PIC into the segments. A restriction concerning PIC is that, as in the PL/M-86 COMPACT model of segmentation […], it can have only one code segment and one data segment, rather than letting the base addresses of these segments, and therefore the segments themselves, vary dynamically. This means that PIC programs are necessarily less than 64K bytes in length. PIC code can be produced by means of the BIND control of LINK86. Load-time locatable code (commonly referred to as LTL code) is the third form of object code. LTL code is similar to PIC in that LTL code can be loaded anywhere in memory. However, when loading LTL code, the Loader changes the base portion of pointers so that the pointers are independent of the initial contents of the registers in the microprocessor. Because of this fixup (adjustment of base addresses), LTL code can be used by tasks having more than one code segment or more than one data segment. This means that LTL programs may be more than 64K bytes in length. FORTRAN 86 and Pascal 86 automatically produce LTL code, even for short programs. LTL code can be produced by means of the BIND control of LINK86. […]
- ^ "Position Independent Executables (PIE)".
- ^ 러바인, 존 R.(2000년)[1999년 10월]." 제8장:Loading과 overlays".Linkers과 Loaders.모건 카우프만 시리즈 소프트웨어 공학 및 프로그래밍(1판)에.샌 프란시스코 미국:모건 카우프만.를 대신하여 서명함. 170–171.아이 에스비엔 1-55860-496-0.온라인 컴퓨터 도서관 센터 42413382.아이 에스비엔 978-1-55860-496-4.그 2012-12-05에 원래에서 Archived.2020-01-12 Retrieved.코드:[1][2]Errata:[3]
- ^ Gabert, Alexander (January 2004). "Position Independent Code internals". Hardened Gentoo. Retrieved 2009-12-03.
[…] direct non-PIC-aware addressing is always cheaper (read: faster) than PIC addressing. […]
- ^ "701 Announced", IBM, 1952-04-29
- ^ Reference Manual UNIVAC III Data Processing System (PDF). Sperry Rand Corporation. 1962. UT-2488.
- ^ "Advances in Memory Management for Windows". View.officeapps.live.com. Retrieved 2017-06-23.
- ^ "Section 6 Virtual Address Formation", DPS/LEVEL 68 & DPS 8M MULTICS PROCESSOR MANUAL (PDF) (Rev. 1 ed.), Honeywell Information Systems Inc., 1982, pp. 6–21, AL39
- ^ "Section 3: TSS for the: Svslcm Programmer". IBM Time Sharing System Concepts and Facilities (PDF) (Seventh ed.). April 1978. p. 61. GC28-2003-6.
- ^ IBM System/360 Time Sharing System Dynamic Loader (PDF) (Fourth ed.). September 1971. GY28-2031-3.
- ^ "iphone - Non-PIE Binary - The executable 'project name' is not a Position Independent Executable. - Stack Overflow". stackoverflow.com.
- ^ "iOS Developer Library". apple.com.
- ^ "OpenBSD 5.3 Release". 2013-05-01. Retrieved 2020-05-09.
- ^ "Heads Up: Snapshot Upgrades for Static PIE". 2014-12-24. Retrieved 2014-12-24.
- ^ "Changes/Harden All Packages - FedoraProject". fedoraproject.org.
- ^ "Ubuntu Foundations Team - Weekly Newsletter, 2017-06-15". 2017-06-15. Retrieved 2017-06-17.
- ^ "New 17.0 profiles in the Gentoo repository". 2017-11-30. Retrieved 2017-12-10.
- ^ Liang, Mudong (2017-08-08). "When did Debian decide to enabled PIE by default?". debian.org. Retrieved 2021-07-06.
- ^ "Security Enhancements in Android 1.5 through 4.1 - Android Open Source Project". Android Open Source Project.
- ^ "Security Enhancements in Android 5.0 - Android Open Source Project". Android Open Source Project.