2009-06-03 5 views
10

나는 하나의 스택 프레임에서 다른 스택 프레임으로 앞뒤로 건너 뛰는 "위험한"프로그램을 C++로 작성했다. 목표는 호출 스택의 가장 낮은 레벨에서 호출자로 건너 뛰고 무언가를 수행 한 다음 다시 호출하여 모든 호출을 건너 뜁니다.PIC 레지스터 (% ebx)의 기능은 무엇입니까?

스택 기본 주소 (%ebp 설정)를 수동으로 변경하고 레이블 주소로 점프하면됩니다. gcc와 icc 모두 함께 스택 손상없이 완전히 작동합니다. 이 일은 멋진 날이었습니다.

이제 동일한 프로그램을 가져와 C로 다시 작성하면 작동하지 않습니다. 특히 gcc v4.0.1 (Mac OS)에서는 작동하지 않습니다. 스택 기본 포인터가 올바르게 설정된 새 스택 프레임으로 이동하면 fprintf을 호출하기 직전에 다음 명령이 실행됩니다. 여기에 나열된 마지막 명령은 역 참조 NULL, 충돌 :

lea 0x18b8(%ebx), %eax 
mov (%eax), %eax 
mov (%eax), %eax 

좀 디버깅을 했어, 내가 알아 낸 것 그 내가 떠나기 전에 관찰 된 값을 사용하여 (스택 프레임을 전환 할 때 수동으로 %ebx 레지스터를 설정하여 처음에 함수), 버그를 수정합니다. 이 등록은 gcc에서 "위치 독립적 코드"를 다룬다는 것을 읽었습니다.

위치 독립적 코드 란 무엇입니까? 위치 독립적 코드는 어떻게 작동합니까? 이 레지스터 포인팅이란 무엇입니까?

+0

setjmp/longjmp를 사용하여 % ebx를 직접 mucking하지 않고도이 기능을 사용할 수 있습니다. –

+2

일반적으로 네, 맞습니다. 이 경우 호출자에게 점프하고 다른 기능을 실행 한 다음 호출 수신자에게 다시 호출 할 수 있어야합니다. setjmp/longjmp를 사용하면 다른 피 호출 함수가 겹쳐 쓸 수 있습니다. –

답변

6

PIC는로드 될 때 동적으로 재배치되는 코드입니다. PIC가 아닌 코드는 링크 시간에 점프 및 호출 주소를 설정합니다. PIC에는 .dll과 마찬가지로 그러한 값이있는 모든 장소를 참조하는 테이블이 있습니다.

이미지가로드되면 로더가 해당 값을 동적으로 업데이트합니다. 다른 체계는 "기본"을 정의하는 데이터 값을 참조하고 대상 주소는 기본에 대한 계산을 수행하여 결정됩니다. 베이스는 일반적으로 로더에 의해 다시 설정됩니다.

마지막으로, 다른 방식은 알려진 상대 오프셋을 호출하는 다양한 트램폴린을 사용합니다. 상대 오프셋에는 로더에 의해 업데이트되는 코드 및/또는 데이터가 포함됩니다.

다른 스키마가 선택되는 데에는 여러 가지 이유가 있습니다. 일부는 빠르게 실행되지만로드는 느립니다. 일부는로드가 빠르지 만 런타임 성능은 떨어집니다.

13

EBX은 글로벌 오프셋 테이블을 가리 킵니다. this reference about PIC on i386을 참조하십시오. 이 링크는 PIC가 어떻게 EBX이 사용되는지를 설명합니다.

+0

GOT - 전역 오프셋 테이블. –

+0

좋은 리소스였습니다. 읽는 데 가치가있는 것. –