익셉션 핸들링기능 자체는 OS 에서 지원하지만 프로그래밍 문법적으로 쉽게 지원하는 언어는 C++ 이다. 물론 C 언어로도 익셉션 핸들링이 가능하긴한데... 일단 여기서는 C++ 컴파일러가 사용하는 Structured Exception Handling 방식을 정리하고자 한다. Vectored Exception Handling 방식은 여기서 논외다... 일단 결과만 정리해서 말하자면 SEH 핸들링 방식을 100% 분석하진 못했다. 매우 복잡하지만 정리하면 다음과 같다.
0. 익셉션 핸들러의 구조
익셉션 핸들러의 구조는 2개의 포인터로 구성된 구조체의 선형 연결리스트이다.
typedef struct _EXCEPTION_REGISTRATION_RECORD { struct _EXCEPTION_REGISTRATION_RECORD *Next; PEXCEPTION_ROUTINE Handler; } EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD;
이 구조체들은 모두 스택에 박혀있고 구조체의 첫번째 멤버가 다음 구조체의 포인터를 의미하며 두번쩨 멤버가 핸들러함수의 주소를 가지고있다. 이 연결리스트의 시작은 FS:0 이 가리키고있다. 익셉션이 발생하면 익셉션핸들링을 하는 kernel32.dll 의 함수는 FS:0 에 들어있는 시작위치부터 참조해서 핸들러들을 하나하나 따라가다가 해당 익셉션을 처리할 의무가 있는놈을 호출하게 되는식이다.
1. 익셉션 핸들러등록
try-catch 문을 쓰거나 except, finally 등의 문을 사용하는 함수에 진입하면 다음과같이 익셉션 핸들러를 fs:0 에 등록한다.
.text:002B14C1 mov ebp, esp
.text:002B14C3 push 0FFFFFFFFh
.text:002B14C5 push offset __ehhandler$_wmain
.text:002B14CA mov eax, large fs:0
.text:002B14D0 push eax
...
.text:002B14F8 lea eax, [ebp+var_C]
.text:002B14FB mov large fs:0, eax
그림으로 보면 아래와 같다
여기서 뭔가 매우 복잡하게 돌아가서 자세히는 모르겠지만 익셉션핸들러의 리스트를 확인하여 실제 catch, except 등에서 정의된 BB 로 뛰게 해주는것 같다.
어쨋든 결론은 SEH 는 개념상 구조는 "스택상에 박혀있는 구조체의 연결리스트" 그리고 각 구조체 속에 핸들러 함수의 주소가 박혀있다 정도로 정리할수 있고, 그 구현방식은 매우매우 복잡하다는 것이다.
'Programming' 카테고리의 다른 글
How ptrace works in Linux (0) | 2014.05.29 |
---|---|
Exception Handling in Linux g++ (0) | 2014.05.27 |
Debugging multi-threaded application with GDB attaching (0) | 2014.03.18 |
Linux DDD Debuger (0) | 2014.03.13 |
Intel PIN Tutorial (1) | 2014.03.06 |