Win32 스레드 정보 블록

**TIB (Win32 Thread Information Block)** (TIB)은 Win32의 자료 구조로서 현재 실행 중인 스레드에 대한 정보를 저장하고 있다. 이 구조체는 또한 스레드 환경 블록 (TEB: Thread Environment Block)으로도 알려져 있다. 이 TIB는 공식적으로 윈도 9x에서는 문서화되어 있지 않다. 윈도 NT 시리즈 DDK는 하위 시스템 독립적인 부분을 문서화한 winnt.h에 NT_TIB 구조체를 포함한다. 와인은 확장된 (구체적인 하위 시스템 부분의) TIB를 위한 선언을 포함한다. 수 많은 Win32 프로그램들은 실질적으로 API의 한 부분이라고 할 수 있는 이 문서화되지 않은 필드들을 사용한다. 특히 첫 번째 필드는 마이크로소프트의 자체 컴파일러에서 직접적으로 코드에 의한 참조가 일어난다. TIB는 Win32 API를 호출하지 않고도 프로세스에 대한 많은 정보를 얻기 위해 사용될 수 있다. PEB를 가리키는 포인터를 통해서 IAT에 대한 접근, 프로세스 시작 인수, 이미지 이름 등을 얻을 수 있다.
# TIB의 내용 (32비트 윈도우)
{| class="wikitable" |위치 ! width="5%" |길이 ! width="5%" |윈도우 버전 ! width="40%" |설명 |- | align="right" |FS:[0x00] | align="right" |4 | align="right" |Win9x and NT |현재 Structured Exception Handling (SEH) 프레임 |- | align="right" |FS:[0x04] | align="right" |4 | align="right" |Win9x and NT |스택 베이스 / 스택의 바닥 (높은 주소) |- | align="right" |FS:[0x08] | align="right" |4 | align="right" |Win9x and NT |스택 한계 / 스택의 천장 (낮은 주소) |- | align="right" |FS:[0x0C] | align="right" |4 | align="right" |NT |SubSystemTib |- | align="right" |FS:[0x10] | align="right" |4 | align="right" |NT |Fiber data |- | align="right" |FS:[0x14] | align="right" |4 | align="right" |Win9x and NT |임의 데이터 슬롯 |- | align="right" |FS:[0x18] | align="right" |4 | align="right" |Win9x and NT |Thread Environment Block |- | align="center" colspan="4" | ---- NT subsystem 독립적인 부분 끝 ---- |- | align="right" |FS:[0x1C] | align="right" |4 | align="right" |NT |Environment Pointer |- | align="right" |FS:[0x20] | align="right" |4 | align="right" |NT |프로세스 ID (몇몇 윈도우 버전에서 이 필드는 'DebugContext'로 쓰인다.) |- | align="right" |FS:[0x24] | align="right" |4 | align="right" |NT |현재 스레드 ID |- | align="right" |FS:[0x28] | align="right" |4 | align="right" |NT |활동중인 RPC 핸들 |- | align="right" |FS:[0x2C] | align="right" |4 | align="right" |Win9x and NT |thread-local storage 배열의 선형 주소 |- | align="right" |FS:[0x30] | align="right" |4 | align="right" |NT |Process Environment Block (PEB)의 선형 주소 |- | align="right" |FS:[0x34] | align="right" |4 | align="right" |NT |마지막 오류 번호 |- | align="right" |FS:[0x38] | align="right" |4 | align="right" |NT |Count of owned critical sections |- | align="right" |FS:[0x3C] | align="right" |4 | align="right" |NT |CSR 클라이언트 스레드의 주소 |- | align="right" |FS:[0x40] | align="right" |4 | align="right" |NT |Win32 스레드 정보 |- | align="right" |FS:[0x44] | align="right" |124 | align="right" |NT, Wine |Win32 클라이언트 정보 (NT), user32 private data (Wine), 0x60 = LastError (Win95), 0x74 = LastError (WinME) |- | align="right" |FS:[0xC0] | align="right" |4 | align="right" |NT |Reserved for Wow64. Wow64에서 FastSysCall에 대한 포인터를 포함한다. |- | align="right" |FS:[0xC4] | align="right" |4 | align="right" |NT |Current Locale |- | align="right" |FS:[0xC8] | align="right" |4 | align="right" |NT |FP Software Status Register |- | align="right" |FS:[0xCC] | align="right" |216 | align="right" |NT, Wine |Reserved for OS (NT), kernel32 private data (Wine) herein: FS:[0x124] 4 NT Pointer to KTHREAD (ETHREAD) structure |- | align="right" |FS:[0x1A4] | align="right" |4 | align="right" |NT |예외 코드 |- | align="right" |FS:[0x1A8] | align="right" |18 | align="right" |NT |Activation context stack |- | align="right" |FS:[0x1BC] | align="right" |24 | align="right" |NT, Wine |Spare bytes (NT), ntdll private data (Wine) |- | align="right" |FS:[0x1D4] | align="right" |40 | align="right" |NT, Wine |Reserved for OS (NT), ntdll private data (Wine) |- | align="right" |FS:[0x1FC] | align="right" |1248 | align="right" |NT, Wine |GDI TEB Batch (OS), vm86 private data (Wine) |- | align="right" |FS:[0x6DC] | align="right" |4 | align="right" |NT |GDI Region |- | align="right" |FS:[0x6E0] | align="right" |4 | align="right" |NT |GDI 펜 |- | align="right" |FS:[0x6E4] | align="right" |4 | align="right" |NT |GDI 브러시 |- | align="right" |FS:[0x6E8] | align="right" |4 | align="right" |NT |Real Process ID |- | align="right" |FS:[0x6EC] | align="right" |4 | align="right" |NT |Real Thread ID |- | align="right" |FS:[0x6F0] | align="right" |4 | align="right" |NT |GDI cached process handle |- | align="right" |FS:[0x6F4] | align="right" |4 | align="right" |NT |GDI 클라이언트 프로세스 ID (PID) |- | align="right" |FS:[0x6F8] | align="right" |4 | align="right" |NT |GDI 클라이언트 스레드 ID (TID) |- | align="right" |FS:[0x6FC] | align="right" |4 | align="right" |NT |GDI thread locale information |- | align="right" |FS:[0x700] | align="right" |20 | align="right" |NT |Reserved for user application |- | align="right" |FS:[0x714] | align="right" |1248 | align="right" |NT |Reserved for GL |- | align="right" |FS:[0xBF4] | align="right" |4 | align="right" |NT |마지막 상태 값 |- | align="right" |FS:[0xBF8] | align="right" |532 | align="right" |NT |Static UNICODE_STRING buffer |- | align="right" |FS:[0xE0C] | align="right" |4 | align="right" |NT |deallocation stack에 대한 포인터 |- | align="right" |FS:[0xE10] | align="right" |256 | align="right" |NT |TLS 슬롯, 슬롯 당 4 byte |- | align="right" |FS:[0xF10] | align="right" |8 | align="right" |NT |TLS 링크 (LIST_ENTRY structure) |- | align="right" |FS:[0xF18] | align="right" |4 | align="right" |NT |VDM |- | align="right" |FS:[0xF1C] | align="right" |4 | align="right" |NT |Reserved for RPC |- | align="right" |FS:[0xF28] | align="right" |4 | align="right" |NT |스레드 에러 모드(RtlSetThreadErrorMode) |} FS는 TIB를 저장하는데, TDB(스레드 데이터 베이스)라고 알려진 데이터 블록에 내장되어 있다. TIB는 스레드에 관련된 예외 핸들링 체인과 TLS(thread local storage)에 대한 포인터를 포함한다. 노트: 위의 설명은 오직 x86 32비트 윈도우에서 설명하는 것이다. x86-64 (64-bit) 윈도우에서, GS (FS가 아니라)는 TIB를 가리키는 세그먼트 레지스터로 사용된다. 게다가 위 구조체의 몇몇 변수 슬롯들은 다른 크기를 가진다.
# TIB에 접근하기
현재 스레드의 TIB는 세그먼트 레지스터 FS (x86) 또는 GS (x64)의 오프셋으로 접근할 수 있다. FS:[0]부터 오프셋으로 TIB 필드에 접근하는 것 대신 FS:[0x18]에 저장된 먼저 선형 자기 참조 포인터를 가지는 것이 TIB 필드에 접근하는 보편적인 방식이다. 이 포인터는 포인터 연산 등에 사용될 수 있다. 32-bit x86에서의 C inlined-assembly 예시: // gcc (AT&T-style; inline assembly). void *getTIB() { void *pTIB; __asm__("movl %%fs:0x18, %0" : "=r" (pTIB) : : ); return pTIB; } // Microsoft C void *getTIB() { void *pTIB; __asm { mov EAX, FS:[0x18] mov pTIB, EAX } return pTIB; } // Using Microsoft's intrinsics instead of inline assembly void *getTIB() { return = (void *)__readfsdword(0x18); }
# 관련 문헌
* url-status=dead