Blocco informazioni thread Win32 - Win32 Thread Information Block
In informatica , il Win32 Thread Information Block (TIB) è una struttura di dati in Win32 su x86 che memorizza le informazioni sul thread attualmente in esecuzione . È anche noto come Thread Environment Block (TEB) per Win32. Deriva da ed è compatibile con le versioni precedenti su sistemi a 32 bit con una struttura simile in OS / 2 .
Il TIB è ufficialmente non documentato per Windows 9x. La serie DDK di Windows NT (così come l'implementazione MinGW / ReactOS) include una struttura NT_TIB in winnt.h che documenta la parte indipendente del sottosistema. Anche prima che TIB fosse effettivamente documentato, molte applicazioni hanno già iniziato a utilizzare i suoi campi che sono effettivamente una parte dell'API . Il primo campo contenente il frame SEH, in particolare, è direttamente referenziato dal codice prodotto dal compilatore di Microsoft. La parte specifica del sottosistema Win32 del TEB non è documentata, ma Wine include una definizione TEB in winternl.h.
Il TIB può essere utilizzato per ottenere molte informazioni sul processo senza chiamare l'API Win32. Gli esempi includono l'emulazione di GetLastError (), GetVersion (). Tramite il puntatore al PEB è possibile accedere alle tabelle di importazione (IAT), agli argomenti di avvio del processo, al nome dell'immagine, ecc. Si accede dal registro dei segmenti FS su Windows a 32 bit e GS su Windows a 64 bit.
Contenuti del TIB su Windows
Questa tabella si basa sul lavoro di Wine sugli interni di Microsoft Windows .
| Byte / tipo |
offset (32 bit, FS) | offset (64 bit, GS) | Versioni di Windows | Descrizione |
|---|---|---|---|---|
| puntatore | FS: [0x00] | GS: [0x00] | Win9x e NT | Frame SEH ( Structured Exception Handling )
corrente Nota: la versione a 64 bit di Windows utilizza invece lo svolgimento dello stack eseguito in modalità kernel . |
| puntatore | FS: [0x04] | GS: [0x08] | Win9x e NT | Stack Base / Parte inferiore della pila (alto indirizzo) |
| puntatore | FS: [0x08] | GS: [0x10] | Win9x e NT | Limite dello stack / soffitto dello stack (indirizzo basso) |
| puntatore | FS: [0x0C] | GS: [0x18] | NT | SubSystemTib |
| puntatore | FS: [0x10] | GS: [0x20] | NT | Dati sulla fibra |
| puntatore | FS: [0x14] | GS: [0x28] | Win9x e NT | Slot dati arbitrario |
| puntatore | FS: [0x18] | GS: [0x30] | Win9x e NT | Indirizzo lineare di TEB |
| Fine della parte indipendente del sottosistema NT ; sotto sono Win32 -dipendenti | ||||
| puntatore | FS: [0x1C] | GS: [0x38] | NT | Puntatore ambientale |
| puntatore | FS: [0x20] | GS: [0x40] | NT | ID processo (in alcune distribuzioni Windows questo campo viene utilizzato come "DebugContext") |
| puntatore | FS: [0x24] | GS: [0x48] | NT | ID thread corrente |
| puntatore | FS: [0x28] | GS: [0x50] | NT | Maniglia RPC attiva |
| puntatore | FS: [0x2C] | GS: [0x58] | Win9x e NT | Indirizzo lineare dell'array di archiviazione locale del thread |
| puntatore | FS: [0x30] | GS: [0x60] | NT | Indirizzo lineare del PEB ( Process Environment Block ) |
| 4 | FS: [0x34] | GS: [0x68] | NT | Ultimo numero di errore |
| 4 | FS: [0x38] | GS: [0x6C] | NT | Conteggio delle sezioni critiche di proprietà |
| puntatore | FS: [0x3C] | GS: [0x70] | NT | Indirizzo del thread del client CSR |
| puntatore | FS: [0x40] | GS: [0x78] | NT | Informazioni sul thread Win32 |
| 124 | FS: [0x44] | GS: [0 x 80] | NT, vino | Informazioni client Win32 (NT), dati privati user32 (Wine), 0x60 = LastError (Win95 e 98), 0x74 = LastError (WinME) |
| puntatore | FS: [0xC0] | GS: [0x100] | NT | Riservato a Wow64. Contiene un puntatore a FastSysCall in Wow64. |
| 4 | FS: [0xC4] | GS: [0x108] | NT | Impostazioni locali correnti |
| 4 | FS: [0xC8] | GS: [0x10C] | NT | Registro di stato del software FP |
| 216 | FS: [0xCC] | GS: [0x110] | NT, vino | Riservato per OS (NT), dati privati kernel32 (Wine) qui: FS: [0x124] 4 puntatore NT alla struttura KTHREAD (ETHREAD) |
| 4 | FS: [0x1A4] | GS: [0x2C0] | NT | Codice di eccezione |
| 18 | FS: [0x1A8] | GS: [0x2C8] | NT | Stack del contesto di attivazione |
| 24 | FS: [0x1BC] | GS: [0x2E8] | NT, vino | Byte di riserva (NT), dati privati ntdll (Wine) |
| 40 | FS: [0x1D4] | GS: [0 x 300] | NT, vino | Riservato per OS (NT), dati privati ntdll (Wine) |
| 1248 | FS: [0x1FC] | GS: [0 x 350] | NT, vino | GDI TEB Batch (OS), dati privati vm86 (Wine) |
| 4 | FS: [0x6DC] | GS: [0x838] | NT | Regione GDI |
| 4 | FS: [0x6E0] | GS: [0x840] | NT | Penna GDI |
| 4 | FS: [0x6E4] | GS: [0x848] | NT | Spazzola GDI |
| 4 | FS: [0x6E8] | GS: [0x850] | NT | ID processo reale |
| 4 | FS: [0x6EC] | GS: [0x858] | NT | ID thread reale |
| 4 | FS: [0x6F0] | GS: [0x860] | NT | Handle di processo memorizzato nella cache GDI |
| 4 | FS: [0x6F4] | GS: [0x868] | NT | ID processo client GDI (PID) |
| 4 | FS: [0x6F8] | GS: [0x86C] | NT | ID thread client GDI (TID) |
| 4 | FS: [0x6FC] | GS: [0x870] | NT | Informazioni sulle impostazioni internazionali del thread GDI |
| 20 | FS: [0x700] | GS: [0x878] | NT | Riservato per l'applicazione dell'utente |
| 1248 | FS: [0x714] | GS: [0x890] | NT | Riservato per GL (Vedi ref. Vino per interni) |
| 4 | FS: [0xBF4] | GS: [0x1250] | NT | Ultimo valore di stato |
| 532 | FS: [0xBF8] | GS: [0x1258] | NT | Buffer UNICODE_STRING statico |
| puntatore | FS: [0xE0C] | GS: [0x1478] | NT | Conosciuto anche come DeallocationStack, stabilisce il vero indirizzo iniziale del buffer dello stack, da qui il limite dello stack reale: è di poche pagine inferiore al campo del limite dello stack (che nasconde le pagine di guardia utilizzate per rilevare gli overflow dello stack). |
| puntatore [] | FS: [0xE10] | GS: [0x1480] | NT | Slot TLS, 4/8 byte per slot, 64 slot |
| 8 | FS: [0xF10] | GS: [0x1680] | NT | Collegamenti TLS (struttura LIST_ENTRY) |
| 4 | FS: [0xF18] | GS: [0x1690] | NT | VDM |
| 4 | FS: [0xF1C] | GS: [0x1698] | NT | Riservato per RPC |
| 4 | FS: [0xF28] | GS: [0x16B0] | NT | Modalità errore thread (RtlSetThreadErrorMode) |
| 4 | FS: [0xF78] | GS: [0x1748] | NT | Byte di stack garantiti |
| Questa non è la tabella completa; vedi wine ref per tutti i campi fino a FS: [0xfb4] / GS: [17c8]. Le versioni più recenti di Windows estendono ulteriormente la dimensione del TIB, fino a 0x1000 / 0x1838 in Windows 10. Alcuni dei campi aggiunti vengono rimossi, portando a definizioni in conflitto. | ||||
FS (per 32 bit) o GS (per 64 bit) esegue il mapping a un TIB che è incorporato in un blocco di dati noto come TDB (thread data base). Il TIB contiene la catena di gestione delle eccezioni specifica del thread e il puntatore al TLS (archiviazione locale del thread). L'archiviazione locale del thread non è la stessa dell'archiviazione locale C.
Informazioni sullo stack memorizzate nel TIB
Un processo dovrebbe essere libero di spostare lo stack dei suoi thread fintanto che aggiorna di conseguenza le informazioni memorizzate nel TIB. Alcuni campi sono fondamentali in questa materia: base dello stack, limite dello stack, stack di deallocazione e byte dello stack garantiti, rispettivamente memorizzati con offset 0x8, 0x10, 0x1478 e 0x1748 in 64 bit. Diverse funzioni del kernel di Windows leggono e scrivono questi valori, specialmente per distinguere gli stack overflow da altri errori di pagina di lettura / scrittura (una lettura o una scrittura su una pagina protetta tra i limiti dello stack negli stack byte garantiti genererà un'eccezione di overflow dello stack invece di violazione). Lo stack di deallocazione è importante perché l'API di Windows permette di modificare la quantità di pagine custodite: la funzione SetThreadStackGuarantee permette sia di leggere lo spazio corrente che di ingrandirlo. Per leggerlo, legge il campo GuaranteedStackBytes e per ingrandirlo utilizza deve annullare il commit delle pagine dello stack. L'impostazione dei limiti di stack senza l'impostazione di DeallocationStack causerà probabilmente un comportamento strano in SetThreadStackGuarantee. Ad esempio, sovrascriverà i limiti dello stack con valori errati. Diverse librerie chiamano SetThreadStackGuarantee, ad esempio .NET CLR lo utilizza per impostare lo stack dei loro thread.
Accesso al TIB
È possibile accedere al TIB del thread corrente come offset del registro di segmento FS (x86) o GS (x64).
Non è comune accedere ai campi TIB tramite un offset da FS:[0] , ma piuttosto ottenere prima un puntatore autoreferenziale lineare ad esso memorizzato in FS:[18h] . Quel puntatore può essere utilizzato con l'aritmetica del puntatore o essere convertito in un puntatore a struttura .
Utilizzando Microsoft Windows SDK o simile, un programmatore può utilizzare una funzione inline definita in winnt.h named NtCurrentTeb che restituisce l'indirizzo del Thread Information Block corrente come NT_TIB * .
I metodi alternativi di accesso per le architetture IA-32 sono i seguenti:
// gcc (AT&T-style inline assembly).
void *getTIB(void) {
register void *pTIB;
#if defined(__x86_64__) || defined(__amd64__)
__asm__("movq %%gs:0x30, %0" : "=r" (pTIB));
#elif defined(__i386__)
__asm__("movl %%fs:0x18, %0" : "=r" (pTIB));
#else
#error unsupported architecture
#endif
return pTIB;
}
// gcc (named address spaces, same as the inline assembly version on -O1 or -ftree-ter).
void *getTIB(void) {
#if defined(__x86_64__) || defined(__amd64__)
#ifndef __SEG_GS
#error unsupported GCC version
#endif
return *(void *__seg_gs *) 0x30;
#elif defined(__i386__)
#ifndef __SEG_FS
#error unsupported GCC version
#endif
return *(void *__seg_fs *) 0x18;
#else
#error unsupported architecture
#endif
}
// Microsoft C
__declspec(naked)
void *getTIB() {
__asm mov EAX, FS:[18h]
__asm ret
}
// Using Microsoft's intrinsics instead of inline assembly (works for both X86 and X64 architectures)
void *getTIB() {
#ifdef _M_IX86
return (void *)__readfsdword(0x18);
#elif _M_AMD64
return (void *)__readgsqword(0x30);
#else
#error unsupported architecture
#endif
}
Guarda anche
Riferimenti
Ulteriore lettura
- Pietrek, Matt (marzo 1996). Segreti di programmazione di Windows 95 (pdf) . IDG. pp. 136–138 . ISBN 978-1-56884-318-6 . Estratto 2010-07-17 .