Stack unwinding

스택 언와이딩은 프로그램에서 예외가 발생했을 때 예외를 처리하기 위해 호출 스택을 역방향으로 하나씩 정리하며 올라가는 과정입니다.

이 과정은 예외가 발생한 곳까지 반복되며, 예외 처리 함수가 없을 경우 프로그램이 종료될 때까지 반복되며 결국 종료됩니다.

호출 스택을 역방향으로 올라가는 과정에서 try문과 catch문 사이에서 생성되었던 객체들은 메모리 낭비를 방지하기 위해 자동으로 소멸자를 호출하도록 되어있습니다.

RUNTIME_FUNCTION

x64 실행파일은 .pdata라고 불리는 예외 디렉토리가 있으며, 이곳에는 실행 파일 내 스택 프레임을 생성하는 함수 대부분에 대해 RUNTIME_FUNCTION 엔트리가 존재합니다.

해당 구조체에는 함수의 시작과 끝 주소, 그리고 해당 함수의 call stack을 어떻게 되돌릴 수 있는지 알려주는 UNWIND_INFO 구조체를 가리키는 주소가 있습니다.

UNWIND_INFO

이 구조체에서는 함수의 프롤로그에서 어떤 레지스터를 스택에 저장했는지(spill), 그 위치를 기록한 unwide 코드들이 포함되어 있습니다.

또한 함수에 예외 처리 구문이 있을 경우, 해당 핸들러 루틴의 RVA(Relative Virtual Address)를 가리키는 포인터도 저장되어 있습니다.

UNWIND_CODE

이 구조체는 함수의 프롤로그에서 수행되는 각 동작을 기술하는데 사용되며 주로 다음과 같은 정보들을 포함하고 있습니다.

  • 프롤로그에서 스택 포인터를 조정한 크기 (sub rsp, 0x20)

  • 어떤 레지스터가 스택에 스필되었는지 (mov [rsp+8], rbx)

  • 프레임 포인터의 설정 여부 (SET_FPREG)

  • 예외 핸들러 존재 여부

  • 프롤로그 명령어가 적용되는 시점의 오프셋

References

Last updated