본문 바로가기
System/Linux

PLT(Procedure Linkage Table), GOT(Global Offset Table)

by bbolmin 2012. 5. 7.

 

PLT(Procedure Linkage Table)

PLT는 일종의 실제 호출 코드를 담고 있는 테이블로써 이 내용 참조를 통해 _dl_runtime_resolve가 수행되고, 실제 시스템 라이브러리 호출이 이루어지게 됩니다.

 

GOT(Global Offset Table)

GOT는 PLT가 참조하는 테이블로써 프로시져들의 주소를 가지고 있습니다. PLT가 어떤 외부 프로시져를 호출할 때 이 GOT를 참조해서 해당 주소로 점프하게 됩니다.

 

- printf 함수 호출이 처음일 때

[printf 함수 호출]--->[PLT로 이동]--->[GOT 참조]--->[다시PLT로 이동]--->[_dl_runtime_resolve]--->[GOT 저장 후, 실제 함수 주소로 점프]

 

 

 

- printf 함수 호출이 처음이 아닐 때 (GOT에 실제 printf 주소가 저장되어 있음)

[printf 함수 호출]--->[PLT로 이동]--->[GOT 참조] ===> printf 함수로 점프

위와 같이 한번 호출한 함수는 GOT 참조를 통해서 _dl_runtime_resolve를 다시 거치지 않고 빠르게 수행할 수 있습니다.  

 

 

실제로 위와 같은 구조를 가지는지 확인해보겠습니다. 간단하게 printf를 2번 호출하는 프로그램을 만듭니다.

 

 

그리고 gdb로 열어서 disass main을 해보면 0x8048f0 (puts@plt 영역)에 call하는 것을 볼 수있습니다. (printf 함수가 내부적으로 puts을 호출하나 봅니다.)

 

 

0x8048f0 부분 (plt 영역)을 보면 위에서 봤던것 처럼 puts에 대해서 3단계로 구성되어 있는 것이 보입니다. 그럼 첫 번째 jmp는 당연히 got영역이 됩니다.

 

 

got부분을 보면 위의 plt부분의 2번째를 다시 가리키고 있습니다. (첫 번째 호출이므로)

 

 


이제 처음 호출하는게 아닐때 어떻게 되는지 보겠습니다. 일단 printf 함수를 한번 실행해야 하므로 break를 건후 실행 하겠습니다.

 

이제 printf함수가 한번 실행된 상태이고 다시 got 영역을 확인해보겠습니다.

위와 같이 0x804a000의 값이 바뀐 것을 확인할 수 있습니다.