모든 코드 컴파일 위치가 독립적이지 않은 이유는 무엇입니까?


85

gcc에서 공유 라이브러리를 컴파일 할 때 -fPIC 옵션은 코드를 위치 독립적으로 컴파일합니다. 모든 코드 위치를 독립적으로 컴파일하지 않는 이유 (성능 또는 기타)가 있습니까?


2
그러나 wowest는 완전히 정확하지 않습니다. 많은 함수 호출과 점프는 상대 점프를 사용하므로 이동 한 후 점프 테이블이 필요하지 않습니다.
Unknown

생성 된 어셈블리 코드를 보면 함수의 주소가로드 된 것처럼 보이지만 비 fpic 코드는 단순히 점프로 보입니다. 내가 당신의 진술을 오해하고 있습니까?
ojblass

@ojblass 제가 의미하는 것은 일부 점프는 "0x400000으로 점프"대신 "여기보다 50 개의 명령을 앞서 점프"또는 "5 개의 명령을 뒤로 점프"하는 것과 같습니다. 따라서 -fPIC로 매번 주소를로드해야한다는 것은 전적으로 사실이 아닙니다.
Unknown

Wikipedia 기사 는 좋은 설명을 제공합니다. 기본적으로 일부 아키텍처에서는 상대 주소로 바로 이동할 수있는 직접적인 방법이 없습니다. 따라서 PIC는 해당 arhcs에서 사용하는 데 더 비쌉니다. 자세한 내용은 @EvanTeran의 답변을 참조하십시오.
Alexei Sholik 2013-08-25

답변:


67

그것은 간접을 추가합니다. 위치 독립적 인 코드를 사용하면 함수의 주소를로드 한 다음 점프해야합니다. 일반적으로 함수의 주소는 이미 명령어 스트림에 있습니다.


33

이 기사에서는 PIC의 작동 방식을 설명하고이를 대체 로드 시간 재배치 와 비교합니다 . 귀하의 질문과 관련이 있다고 생각합니다.


16
@Nick : 동의하지 않습니다. 질문자가 도움이된다면 답입니다. 관련 기사 한두 개를 가리키면 풍부한 정보를 얻을 수 있습니다.
Eli Bendersky 2013 년

5
이 게시물에는 결론이 없으며 기사에 대한 링크 만 있습니다. 성능 문제로 인해 PIC가 기본적으로 사용되지 않는다는 단서조차 없습니다.
Nick

10
이 링크가 질문에 답할 수 있지만 여기에 답변의 필수 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 무효화 될 수 있습니다.
Rob

4
@Rob : 생산적인 것은 편집을 제안하고 징징 대는 주석을 사용하지 않는 것입니다. 이 답변은 4 살입니다. 그 당시 SO는 답이 어떻게 보일지에 대한 덜 엄격한 규칙을 가졌습니다
Eli Bendersky

6
이 게시물은 "검토"아래에 표시되어 요청을했습니다. 다른 사람이 신고했습니다. "우는 소리"는 내가 아닌 SO에 의해 자동 생성됩니다.
Rob

27

예, 성능상의 이유가 있습니다. 일부 액세스는 메모리에서 절대 위치를 얻기 위해 효과적으로 다른 간접 계층 아래에 ​​있습니다.

글로벌 변수의 오프셋을 저장하는 GOT (글로벌 오프셋 테이블)도 있습니다. 나에게 이것은 IAT 수정 테이블처럼 보이며 위키피디아와 몇 가지 다른 소스에 따라 위치에 따라 분류됩니다.

http://en.wikipedia.org/wiki/Position_independent_code


23

수락 된 답변 외에도. 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 상대"모드를 추가했습니다 .


1
IIRC MIPS는 PC 상대가 상대 점프를 제외하고도 주소가없는
phuclv

1
이것은 실행중인 주소를 얻기 위해 쉘 코드에서 사용되는 일반적인 기술입니다. 저는 이것을 몇 가지 CTF 솔루션에서 사용했습니다.
sherrellbc

2

완전히 위치 독립적 인 코드를 구현하면 코드 생성기에 제약이 추가되어 더 빠른 작업을 사용하지 못하거나 제약 조건을 유지하기 위해 추가 단계를 추가 할 수 있습니다.

이는 프로세스가 서로의 메모리를 침해하지 않도록 신뢰하고 기본 주소에서 특정 애플리케이션을로드해야하는 가상 메모리 시스템없이 멀티 프로세싱을 수행하는 데 허용되는 절충안 일 수 있습니다.

많은 최신 시스템에서 성능 절충안은 다르며 재배치 로더는 최적화 프로그램이 자유 통치가있는 경우 할 수있는 최선보다 비용이 적게 듭니다 (코드가 처음로드 될 때마다 비용이 듭니다). 또한 가상 주소 공간의 가용성은 애초에 위치 독립성에 대한 대부분의 동기를 숨 깁니다.


1

또한 대부분의 최신 프로세서 (대부분의 최신 OS에서 사용)의 가상 메모리 하드웨어는 많은 코드 (모든 사용자 공간 앱, mmap 등의 기발한 사용을 제외)가 위치 독립적 일 필요가 없음을 의미합니다. 모든 프로그램은 0에서 시작한다고 생각하는 자체 주소 공간을 갖습니다.


4
그러나 VM-MMU가있는 경우에도 동일한 .so 라이브러리가 다른 실행 파일에서 사용될 때 메모리에 한 번만로드되도록하려면 PIC 코드가 필요합니다.
mmmmmmmm

1

position-independent code 추가 레지스터가 필요하기 때문에 대부분의 아키텍처에서 성능 오버 헤드가 있습니다.

따라서 이것은 성능 목적입니다.


0

오늘날 운영 체제와 컴파일러는 기본적으로 모든 코드를 위치 독립적 코드로 만듭니다. -fPIC 플래그없이 컴파일을 시도하면 코드는 잘 컴파일되지만 경고 만 표시됩니다. OS와 같은 Windows는이를 달성하기 위해 메모리 매핑이라는 기술을 사용합니다.


-5

질문은 2009 년으로 거슬러 올라갑니다. 10 년이 지났고 이제 모든 코드는 실제로 위치 독립적입니다. 이것은 이제 운영 체제와 컴파일러에 의해 시행됩니다. 옵트 아웃 할 수있는 방법이 없습니다. 모든 코드는 PIE로 강제 컴파일되고 -no-pic / -no-pie 플래그는이 ASLR 변명의 일부로 무시됩니다. 그 이유는 보안 강화를 가장하여 이전에 빠른 앱의 속도를 낮추고 새로운 하드웨어를 판매하기 위함입니다. 그것은 완전히 비합리적입니다. 왜냐하면 이제 큰 메모리 크기로 인해 모든 앱을 정적으로 컴파일하면서 지옥의 동적 연결을 전혀 없앨 수 있기 때문입니다.

사람들이 리얼 모드를 조용히 받아들이고 다른 자유를 빼앗기 던 이전에도 마찬가지였습니다. 그리고 MMU는 컨텍스트 전환 및 주소 변환 지연으로 인해 상당한 속도 저하를 초래합니다. 과학자들이 물리학 실험을 샘플링하는 데 사용하는 것과 같이 성능이 중요한 시스템에서는 MMU를 찾을 수 없습니다.

당신은 불평하지 않습니다. 왜냐하면 당신의 코드가이 모든 훈련 바퀴에 의해 장애가되고 있다는 사실조차 모르기 때문입니다. 내가 뭐라고 말할 수 있니? 지금 PIC로 2 배 더 느린 소프트웨어를 즐기십시오! 더욱이, LLVM의 출현으로 곧 x86 인라인 어셈블리에 액세스 할 수없는 JIT (관리 코드)가 적용되어 C / C ++ 코드가 더욱 느려질 것입니다. "안보를 위해 자유를 희생하는 사람은 누구도받을 자격이 없습니다."


이는 사실에 대한 진술 일뿐입니다. 10 년 전 PIC는 선택 사항 이었지만 현재는 기본이며 필수입니다. 비 PIE 코드가 추가 OS 릴리스에서 지원 될 것 같지 않습니다. Windows 9x 이후 리얼 모드 지원이 중단 된 것과 같습니다. 따라서 어떻게 든 OS를 잠금 해제하고 지원을 다시 활성화하지 않는 한 PIC 사용 여부에 대한 질문은 이론적 인 컴퓨터 과학 주제가됩니다. 사람들이 PIC에 대해 알아야 할 가장 중요한 것은 컴파일러가 지금까지 정적 컴파일을 지원할만큼 충분히 느리고 대부분의 DLL의 정적 버전이 있다는 것입니다.
SmugLispWeenie

1
처음 몇 문장은 사실에 대한 진술입니다. 나머지는 음모에 가까운 의견입니다.
Mitch Lindgren

글쎄, 사람들과 이야기하고 그것에 대한 의견을 물어보십시오. 나는 개인적으로 PIC와 non-PIC가 이념의 문제가되었다는 것을 발견했습니다. PIC는 코드가 대량 생산되고 모든 사람이 동일한 사본을 얻는 공산주의와 동등한 프로그래밍입니다. Non-PIC는 동일한 코드의 경쟁 버전이 많은 자본주의와 동등한 프로그래밍입니다. 따라서 더 좌파 적 사고 방식을 가진 사람들은 PIC를 무의식적으로 지원하여 자신이 좋아하는 이데올로기가 적어도 컴퓨팅에서 작동 할 수 있다는 점을 증명합니다. 이 같은 사람들은 개인적으로 수정 된 libpng를 사용하지 말라고 조언 할 것입니다.
SmugLispWeenie

2
프로그래밍 웹 사이트에서 정치적 폭언을 할 수 없습니까? 감사합니다
Ryan McCampbell
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.