System/Linux2012. 5. 7. 14:28

 

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의 값이 바뀐 것을 확인할 수 있습니다.

 

 

 

Posted by bbolmin

댓글을 달아 주세요

  1. plt와 got에 대한 설명이 알기쉽게 되있네요
    발췌해갑니다 ^^

    2015.10.26 23:16 신고 [ ADDR : EDIT/ DEL : REPLY ]
  2. 그림과 설명이 참 깔끔하네요! 저도 발췌해갑니다~~

    2015.11.24 22:02 신고 [ ADDR : EDIT/ DEL : REPLY ]
  3. hi

    친절한 설명 감사합니다 발췌해갈게욧

    2015.12.23 23:38 [ ADDR : EDIT/ DEL : REPLY ]
  4. DUMMY

    좋은 설명이군요 발췌해가겠습니다 ㅠㅠ ~

    2015.12.30 14:15 [ ADDR : EDIT/ DEL : REPLY ]
  5. printf 함수가 puts 함수가 된 건 컴파일러 최적화의 영향이 아닐까 조심스레 추측해 봅니다. stdout으로 보내는, 서식 없고 개행으로 끝나는 문자열은 puts 함수로 출력하는 편이 비용이 덜 드니까요.

    2016.07.08 13:48 [ ADDR : EDIT/ DEL : REPLY ]
  6. siso

    설명이 너무 좋아요 저도 발췌해 갈게용~~

    2016.11.19 23:06 [ ADDR : EDIT/ DEL : REPLY ]