gcc에서 공유 라이브러리를 컴파일 할 때 -fPIC 옵션은 코드를 위치 독립적으로 컴파일합니다. 모든 코드 위치를 독립적으로 컴파일하지 않는 이유 (성능 또는 기타)가 있습니까?
gcc에서 공유 라이브러리를 컴파일 할 때 -fPIC 옵션은 코드를 위치 독립적으로 컴파일합니다. 모든 코드 위치를 독립적으로 컴파일하지 않는 이유 (성능 또는 기타)가 있습니까?
답변:
예, 성능상의 이유가 있습니다. 일부 액세스는 메모리에서 절대 위치를 얻기 위해 효과적으로 다른 간접 계층 아래에 있습니다.
글로벌 변수의 오프셋을 저장하는 GOT (글로벌 오프셋 테이블)도 있습니다. 나에게 이것은 IAT 수정 테이블처럼 보이며 위키피디아와 몇 가지 다른 소스에 따라 위치에 따라 분류됩니다.
수락 된 답변 외에도. PIC 코드 성능을 많이 손상시키는 한 가지는 x86에서 "IP 상대 주소 지정"이 없다는 것입니다. "IP 상대 주소 지정"을 사용하면 현재 명령 포인터에서 X 바이트 인 데이터를 요청할 수 있습니다. 이것은 PIC 코드를 훨씬 더 간단하게 만들 것입니다.
점프와 호출은 일반적으로 EIP에 상대적이므로 실제로 문제가되지는 않습니다. 그러나 데이터에 액세스하려면 약간의 추가 속임수가 필요합니다. 때때로 레지스터는 코드에 필요한 데이터에 대한 "기본 포인터"로 임시 예약됩니다. 예를 들어, 일반적인 기술은 x86에서 호출이 작동하는 방식을 남용하는 것입니다.
call label_1
.dd 0xdeadbeef
.dd 0xfeedf00d
.dd 0x11223344
label_1:
pop ebp ; now ebp holds the address of the first dataword
; this works because the call pushes the **next**
; instructions address
; real code follows
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way
이 기술 및 기타 기술은 데이터 액세스에 간접 계층을 추가합니다. 예를 들어, gcc 컴파일러에서 사용하는 GOT (전역 오프셋 테이블)입니다.
x86-64는 작업을 훨씬 더 간단 하게 만드는 "RIP 상대"모드를 추가했습니다 .
완전히 위치 독립적 인 코드를 구현하면 코드 생성기에 제약이 추가되어 더 빠른 작업을 사용하지 못하거나 제약 조건을 유지하기 위해 추가 단계를 추가 할 수 있습니다.
이는 프로세스가 서로의 메모리를 침해하지 않도록 신뢰하고 기본 주소에서 특정 애플리케이션을로드해야하는 가상 메모리 시스템없이 멀티 프로세싱을 수행하는 데 허용되는 절충안 일 수 있습니다.
많은 최신 시스템에서 성능 절충안은 다르며 재배치 로더는 최적화 프로그램이 자유 통치가있는 경우 할 수있는 최선보다 비용이 적게 듭니다 (코드가 처음로드 될 때마다 비용이 듭니다). 또한 가상 주소 공간의 가용성은 애초에 위치 독립성에 대한 대부분의 동기를 숨 깁니다.
오늘날 운영 체제와 컴파일러는 기본적으로 모든 코드를 위치 독립적 코드로 만듭니다. -fPIC 플래그없이 컴파일을 시도하면 코드는 잘 컴파일되지만 경고 만 표시됩니다. OS와 같은 Windows는이를 달성하기 위해 메모리 매핑이라는 기술을 사용합니다.
질문은 2009 년으로 거슬러 올라갑니다. 10 년이 지났고 이제 모든 코드는 실제로 위치 독립적입니다. 이것은 이제 운영 체제와 컴파일러에 의해 시행됩니다. 옵트 아웃 할 수있는 방법이 없습니다. 모든 코드는 PIE로 강제 컴파일되고 -no-pic / -no-pie 플래그는이 ASLR 변명의 일부로 무시됩니다. 그 이유는 보안 강화를 가장하여 이전에 빠른 앱의 속도를 낮추고 새로운 하드웨어를 판매하기 위함입니다. 그것은 완전히 비합리적입니다. 왜냐하면 이제 큰 메모리 크기로 인해 모든 앱을 정적으로 컴파일하면서 지옥의 동적 연결을 전혀 없앨 수 있기 때문입니다.
사람들이 리얼 모드를 조용히 받아들이고 다른 자유를 빼앗기 던 이전에도 마찬가지였습니다. 그리고 MMU는 컨텍스트 전환 및 주소 변환 지연으로 인해 상당한 속도 저하를 초래합니다. 과학자들이 물리학 실험을 샘플링하는 데 사용하는 것과 같이 성능이 중요한 시스템에서는 MMU를 찾을 수 없습니다.
당신은 불평하지 않습니다. 왜냐하면 당신의 코드가이 모든 훈련 바퀴에 의해 장애가되고 있다는 사실조차 모르기 때문입니다. 내가 뭐라고 말할 수 있니? 지금 PIC로 2 배 더 느린 소프트웨어를 즐기십시오! 더욱이, LLVM의 출현으로 곧 x86 인라인 어셈블리에 액세스 할 수없는 JIT (관리 코드)가 적용되어 C / C ++ 코드가 더욱 느려질 것입니다. "안보를 위해 자유를 희생하는 사람은 누구도받을 자격이 없습니다."