[CS] Lazy Binding

Magnolia·2026년 3월 28일

Lazy Binding

동적 링크된 ELF 프로그램에서 함수가 실제로 처음 호출될 때까지 주소 해석을 미루는 기법을 Lazy Binding이라고 한다.

즉, 프로그램이 시작될 때 모든 라이브러리 함수 주소를 계산하는 것이 아니라 필요한 순간에만 계산한다.

이 방식은 프로그램 실행 속도를 개선하고 메모리 사용을 줄이기 위해 사용된다.


ELF 동적 링크 구조

PLT

PLT (Procedure Linkage Table)는 외부 라이브러리 함수를 호출하기 위한 코드가 들어있는 영역이다.

초기 호출 흐름은 다음과 같다.

초기 GOT 상태는 func@got = func@plt + 6 상태이고 그래서 첫 호출 시 다음과 같은 흐름이 만들어진다.

main -> func@plt -> func@got -> plt0 -> _dl_runtime_resolve -> func

두번째 호출 흐름은 다음과 같다.

main -> func@plt -> jmp [func@got] -> libc func

GOT

GOT (Global Offset Table)는 실제 함수 주소가 저장되는 테이블이다.

func@got -> libc func 주소
...

하지만 Lazy Binding에서는 프로그램 시작 시 GOT에 실제 주소가 들어있지 않다.


GOT 동작 과정

함수를 처음 호출할 때 plt가 먼저 호출되고 plt에서는 got를 참조하기 때문에 got로 jump하게 된다. 그리고 _dl_runtime_resolve 함수가 호출된다.


_dl_runtime_resolve

_dl_runtime_resolve(struct link_map *l, ElfW(Word) reloc_arg) ;

해당 함수의 인자는 reloc_offsetlink_map이다. 우선 reloc_offset은 아래의 구조체의 시작 주소를 얻기 위해 사용된다.

  • 32bit : JMPREL(.rel.plt) 영역에서 해당 함수의 Elf32_Rel 구조체의 오프셋 (주소 오프셋)
  • 64bit : RELA(.rela.plt) 영역에서 해당 함수의 Elf64_Rela 구조체의 오프셋 (구조체 배열의 인덱스)

64bit에서는 reloc_arg = index

실제 relocation entry 주소는 rela = JMPREL + reloc_arg * sizeof(Elf64_Rela)

이기 때문에 오프셋이라기보다 인덱스에 가깝긴하다.

link_map 구조체는 링커가 런타임에서 라이브러리 함수들을 메모리에 매핑시킬 때 사용하는 구조체이다.


_dl_fixup

_dl_fixup(struct link_map *l, ElfW(Word) reloc_arg) ;

_dl_runtime_resolve 함수가 호출된 후 호출되는 함수는 _dl_fixup 함수이다. 해당 함수가 호출될 때 Elf32_Sym 구조체와 Elf64_Sym 구조체가 참조된다. 해당 구조체는 함수의 심볼테이블 엔트리에 해당된다.


이후 과정

  • 함수 이름의 시작 주소를 인자로 _dl_lookup_symbol_x() 함수 호출
  • 함수 이름을 해시값으로 바꿔서 do_lookup_x() 함수에서 검사
  • 실제 라이브러리 영역에서의 심볼 테이블 인덱스 확보
  • 인덱스를 가지고 라이브러리 상에서의 오프셋 확보
  • 로드된 라이브러리 파일에서 해당 함수의 Elf32_Sym 구조체 주소에 접근
  • Elf32_sym->st_value는 실제 함수의 상대주소를 가진 상태

-> **libc base + Elf32_Sym->value = 실제 함수 주소

resolved_addr = l->l_addr + sym->st_value
l->l_addr = libc base


호출 순서

_dl_runtime_resolve() -> _dl_fixup() -> _dl_lookup_symbol_x() -> do_lookup_x()
  • __DT_STRTAB 영역의 string 문자열을 가지고 함수의 주소를 가지고 오기 때문에 해당 영역의 문자열의 값을 변경할 수 있다면 임의의 함수 호출이 가능하다.

0개의 댓글