Win32 スレッド情報ブロック

コンテンツへジャンプ
フリー百科事典『ウィキペディア』より
(スレッド環境ブロックからリダイレクト)

スレッド情報ブロックTIB)またはスレッド環境ブロックTEB)は、x86上のWin32におけるデータ構造であり、現在実行中のスレッドに関する情報を格納します。これはOS/2の同様の構造を継承しており、32ビットシステム上ではOS/2と下位互換性があります。[ 1 ]

TIBはWindows 9xでは公式には文書化されていません。Windows NTシリーズのDDK(およびMinGW / ReactOS実装)には、サブシステムに依存しない部分を文書化する構造体が含まれています。TIBが正式に文書化される前から、多くのアプリケーションが既にそのフィールドを使い始めており、それらは事実上APIの一部となっていますNT_TIB特にSEHフレームを含む最初のフィールドは、Microsoft自身のコンパイラによって生成されたコードによって参照されています。[ 1 ] TEBのWin32サブシステム固有の部分は文書化されていませんが、WineにはTEBの定義が含まれています[ 2 ]winnt.hwinternl.h

TIB を使用すると、Win32 API を呼び出さずにプロセスに関する多くの情報を取得できます。例えばGetLastError()、 、のエミュレーションなどが挙げられますGetVersion()。PEB へのポインターを介して、インポートテーブル (IAT)、プロセス起動引数、イメージ名などにアクセスできます。TIB は、32 ビット Windows では FS セグメントレジスタから64ビット Windows では GS セグメントレジスタからアクセスされます。

Windows 上の TIB の内容

[編集]

この表はWineによるMicrosoft Windows内部の作業に基づいています[ 2 ]

バイト/
タイプ
オフセット(32ビット、FS)オフセット(64ビット、GS)Windowsバージョン説明
ポインタFS:[0x00]GS:[0x00]Win9xNT現在の構造化例外処理(SEH)フレーム

注: 64 ビット バージョンの Windows では、代わりにカーネル モードで実行されるスタック アンワインドが使用されます。

ポインタFS:[0x04]GS:[0x08]Win9x と NTスタックベース / スタックの底部(上位アドレス)
ポインタFS:[0x08]GS:[0x10]Win9x と NTスタック制限 / スタックの上限(下位アドレス)
ポインタFS:[0x0C]GS:[0x18]NTSubSystemTib
ポインタFS:[0x10]GS:[0x20]NTファイバーデータ
ポインタFS:[0x14]GS:[0x28]Win9x と NT任意のデータスロット
ポインタFS:[0x18]GS:[0x30]Win9x と NTTEBの線形アドレス
NTサブシステム非依存部分の終了。以下はWin32依存 。
ポインタFS:[0x1C]GS:[0x38]NT環境ポインタ
ポインタFS:[0x20]GS:[0x40]NTプロセスID(一部のWindowsディストリビューションではこのフィールドは次のように使用されますDebugContext
4FS:[0x24]GS:[0x48]NT現在のスレッドID
ポインタFS:[0x28]GS:[0x50]NTアクティブRPCハンドル
ポインタFS:[0x2C]GS:[0x58]Win9x と NTスレッドローカルストレージ配列の線形アドレス
ポインタFS:[0x30]GS:[0x60]NTプロセス環境ブロック(PEB)の線形アドレス
4FS:[0x34]GS:[0x68]NT最後のエラー番号
4FS:[0x38]GS:[0x6C]NT所有クリティカルセクションの数
ポインタFS:[0x3C]GS:[0x70]NTCSRクライアントスレッドのアドレス
ポインタFS:[0x40]GS:[0x78]NTWin32 スレッド情報
124FS:[0x44]GS:[0x80]NT、ワインWin32 クライアント情報 (NT)、user32 プライベート データ (Wine)、0x60 = LastError (Win95&98)、0x74 = LastError (WinME)
ポインタFS:[0xC0]GS:[0x100]NTWow64用に予約されています。Wow64内のポインターが含まれますFastSysCall
4FS:[0xC4]GS:[0x108]NT現在のロケール
4FS:[0xC8]GS:[0x10C]NTFPソフトウェアステータスレジスタ
216FS:[0xCC]GS:[0x110]NT、ワインOS(NT)、kernel32プライベートデータ(Wine)用に予約されています
:FS:[0x124] 4 NT KTHREADETHREAD)構造体 へのポインタ
4FS:[0x1A4]GS:[0x2C0]NT例外コード
18FS:[0x1A8]GS:[0x2C8]NTアクティベーションコンテキストスタック
24FS:[0x1BC]GS:[0x2E8]NT、ワイン予備バイト(NT)、ntdllプライベートデータ(Wine)
40FS:[0x1D4]GS:[0x300]NT、ワインOS (NT)、ntdll プライベート データ (Wine) 用に予約済み
1248FS:[0x1FC]GS:[0x350]NT、ワインGDI TEB バッチ (OS)、vm86 プライベート データ (Wine)
4FS:[0x6DC]GS:[0x838]NTGDI地域
4FS:[0x6E0]GS:[0x840]NTGDIペン
4FS:[0x6E4]GS:[0x848]NTGDIブラシ
4FS:[0x6E8]GS:[0x850]NT実プロセスID
4FS:[0x6EC]GS:[0x858]NT実スレッドID
4FS:[0x6F0]GS:[0x860]NTGDIキャッシュプロセスハンドル
4FS:[0x6F4]GS:[0x868]NTGDI クライアント プロセス ID (PID)
4FS:[0x6F8]GS:[0x86C]NTGDI クライアント スレッド ID (TID)
4FS:[0x6FC]GS:[0x870]NTGDIスレッドロケール情報
20FS:[0x700]GS:[0x878]NTユーザーアプリケーション用に予約済み
1248FS:[0x714]GS:[0x890]NTGL用に予約済み(内部についてはwineのrefを参照)[ 2 ]
4FS:[0xBF4]GS:[0x1250]NT最終ステータス値
532FS:[0xBF8]GS:[0x1258]NT静的UNICODE_STRINGバッファ
ポインタFS:[0xE0C]GS:[0x1478]NTとも呼ばれるこのDeallocationStackフィールドは、スタックバッファの実際の開始アドレスを決定し、真のスタック制限を定義します。この制限は、スタック制限フィールドよりも数ページ少なくなります。これは、スタック制限フィールドが、スタックの増大を管理するために使用されるガードページを含んでいるためです。[ 3 ]
ポインタ[]FS:[0xE10]GS:[0x1480]NTTLSスロット、スロットあたり4/8バイト、64スロット
8FS:[0xF10]GS:[0x1680]NTTLSリンク(LIST_ENTRY構造)
4FS:[0xF18]GS:[0x1690]NTVDM
4FS:[0xF1C]GS:[0x1698]NTRPC用に予約済み
4FS:[0xF28]GS:[0x16B0]NTスレッドエラーモード(RtlSetThreadErrorMode
4FS:[0xF78]GS:[0x1748]NT保証スタックバイト
これは完全な表ではありません。FS:[0xfb4] / GS:[17c8]までのすべてのフィールドについては、wine refを参照してください。[ 2 ]新しいWindowsのバージョンでは、TIBのサイズがさらに拡張され、Windows 10では最大0x1000/0x1838まで拡張されます。追加されたフィールドの一部は削除され、定義の競合が発生します。[ 4 ]

FS(32ビット)またはGS(64ビット)は、TDB(スレッドデータベース)と呼ばれるデータブロックに埋め込まれたTIBにマッピングされます。TIBには、スレッド固有の例外処理チェーンとTLS(スレッドローカルストレージ)へのポインタが含まれています。スレッドローカルストレージは、C言語のローカルストレージとは異なります。

TIBに保存されるスタック情報

[編集]

プロセスは、TIB に格納されている情報を適宜更新する限り、そのスレッドのスタック0x8を自由に移動できる必要があります。この問題で重要なフィールドは、スタック ベース、スタック制限、割り当て解除スタック、保証されたスタック バイトです。これらはそれぞれ、64 ビットのオフセット、0x100x1478に格納されます0x1748。さまざまな Windowsカーネル関数がこれらの値を読み書きしますが、これは特に、スタック オーバーフローを他の読み取り/書き込みページ フォールトと区別するためです (保証されたスタック バイト内のスタック制限内で保護されているページへの読み取りまたは書き込みを行うと、アクセス違反ではなくスタック オーバーフロー例外が生成されます)。割り当て解除スタックが重要なのは、Windows API によって保護されているページの量を変更できるためです。関数では、SetThreadStackGuarantee現在のスペースの読み取りと拡張の両方が可能です。それを読み取るために、GuaranteedStackBytesフィールドを読み取り、拡張するために、スタック ページをアンコミットするために を使用します。 を設定せずにスタック制限を設定すると、でDeallocationStack異常な動作が発生する可能性がありますSetThreadStackGuarantee。たとえば、スタック制限が間違った値に上書きされます。さまざまなライブラリが を呼び出します。SetThreadStackGuaranteeたとえば、.NET CLR はそれを使用してスレッドのスタックをセットアップします。

TIBへのアクセス

[編集]

現在のスレッドの TIB には、セグメントレジスタFS (x86) または GS (x64)のオフセットとしてアクセスできます。

TIBフィールドへは、 からのオフセットでアクセスするのでFS:[0]はなく、まず に格納されている自己参照型の線形ポインタを取得します。このポインタは、ポインタ演算で使用したり、構造体ポインタFS:[18h]にキャストしたりできます

Microsoft Windows SDKなどを使用すると、プログラマはwinnt.hnamedで定義されたインライン関数を使用してNtCurrentTeb、現在のスレッド情報ブロックのアドレスをとして返すことができますNT_TIB *[ 5 ]

IA-32アーキテクチャの代替アクセス方法は次のとおりです。

// gcc (AT&T スタイルのインライン アセンブリ)。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 サポートされていないアーキテクチャです#endif return pTIB ; }               
// gcc (名前付きアドレス空間、-O1 または -ftree-ter のインラインアセンブリバージョンと同じ)。void * getTIB ( void ) { #if defined(__x86_64__) || defined(__amd64__) #ifndef __SEG_GS #error サポートされていない GCC バージョン#endif return * ( void * __seg_gs * ) 0x30 ; #elif defined(__i386__) #ifndef __SEG_FS #errorサポートされていない GCC バージョン#endif return * ( void * __seg_fs * ) 0x18 ; #else #error サポートされていないアーキテクチャ#endif }            
// Microsoft C __declspec ( naked ) void * getTIB () { __asm mov EAX , FS : [ 18 h ] __asm ret }        
// インラインアセンブリの代わりに Microsoft の組み込み関数を使用する (X86 と X64 の両方のアーキテクチャで動作します) void * getTIB () { #ifdef _M_IX86 return ( void * ) __readfsdword ( 0x18 ); #elif _M_AMD64 return ( void * ) __readgsqword ( 0x30 ); #else #error サポートされていないアーキテクチャ#endif }        

参照

[編集]

参考文献

[編集]
  1. ^ a b Pietrek, Matt (1996年5月). 「Under The Hood」 . Microsoft Systems Journal . 2009年6月14日時点のオリジナルよりアーカイブ。 2010年7月7日閲覧
  2. ^ a b c d "wine winternl.h: typedef struct _TEB" . GitHub . wine-mirror. 2019年10月29日.
  3. ^ 「スタックガードページの詳細」 2022年2月3日。
  4. ^ チャペル、ジェフ。「TEB」
  5. ^ 「NtCurrentTeb関数」 . Microsoft Docs . 2019年11月20日閲覧

さらに読む

[編集]
[編集]

    スレッド情報ブロックTIB)またはスレッド環境ブロックTEB)は、x86上のWin32におけるデータ構造であり、現在実行中のスレッドに関する情報を格納します。これはOS/2の同様の構造を継承しており、32ビットシステムではOS/2と下位互換性があります。[1]

    TIBはWindows 9xでは公式に文書化されていません。Windows NTシリーズのDDK(およびMinGW / ReactOS実装)には、サブシステムに依存しない部分を文書化する構造体が含まれています。TIBが正式に文書化される前から、多くのアプリケーションが既にそのフィールドを使い始めており、それらは事実上APIの一部となっていますNT_TIB特に SEHフレームを含む最初のフィールドは、Microsoft独自のコンパイラによって生成されたコードによって参照されています。[ 1 ] TEBのWin32サブシステム固有の部分は文書化されていませんが、WineにはTEBの定義が含まれています[2]winnt.hwinternl.h

    TIB を使用すると、Win32 API を呼び出さずにプロセスに関する多くの情報を取得できます。例えばGetLastError()、 、のエミュレーションなどが挙げられますGetVersion()。PEB へのポインターを介して、インポートテーブル (IAT)、プロセス起動引数、イメージ名などにアクセスできます。TIB は、32 ビット Windows では FS セグメントレジスタから64ビット Windows では GS セグメントレジスタからアクセスされます。

    Windows 上の TIB の内容

    この表はWineによるMicrosoft Windows内部の作業に基づいています[2]

    バイト/
    タイプ
    オフセット(32ビット、FS)オフセット(64ビット、GS)Windowsバージョン説明
    ポインタFS:[0x00]GS:[0x00]Win9xNT現在の構造化例外処理(SEH)フレーム

    注: 64 ビット バージョンの Windows では、代わりにカーネル モードで実行されるスタック アンワインドが使用されます。

    ポインタFS:[0x04]GS:[0x08]Win9x と NTスタックベース / スタックの底部(上位アドレス)
    ポインタFS:[0x08]GS:[0x10]Win9x と NTスタック制限 / スタックの上限(下位アドレス)
    ポインタFS:[0x0C]GS:[0x18]NTSubSystemTib
    ポインタFS:[0x10]GS:[0x20]NTファイバーデータ
    ポインタFS:[0x14]GS:[0x28]Win9x と NT任意のデータスロット
    ポインタFS:[0x18]GS:[0x30]Win9x と NTTEBの線形アドレス
    NTサブシステム非依存部分の終了。以下はWin32依存 。
    ポインタFS:[0x1C]GS:[0x38]NT環境ポインタ
    ポインタFS:[0x20]GS:[0x40]NTプロセスID(一部のWindowsディストリビューションではこのフィールドは次のように使用されますDebugContext
    4FS:[0x24]GS:[0x48]NT現在のスレッドID
    ポインタFS:[0x28]GS:[0x50]NTアクティブRPCハンドル
    ポインタFS:[0x2C]GS:[0x58]Win9x と NTスレッドローカルストレージ配列の線形アドレス
    ポインタFS:[0x30]GS:[0x60]NTプロセス環境ブロック(PEB)の線形アドレス
    4FS:[0x34]GS:[0x68]NT最後のエラー番号
    4FS:[0x38]GS:[0x6C]NT所有クリティカルセクションの数
    ポインタFS:[0x3C]GS:[0x70]NTCSRクライアントスレッドのアドレス
    ポインタFS:[0x40]GS:[0x78]NTWin32 スレッド情報
    124FS:[0x44]GS:[0x80]NT、ワインWin32 クライアント情報 (NT)、user32 プライベート データ (Wine)、0x60 = LastError (Win95&98)、0x74 = LastError (WinME)
    ポインタFS:[0xC0]GS:[0x100]NTWow64用に予約されています。Wow64内のポインターが含まれますFastSysCall
    4FS:[0xC4]GS:[0x108]NT現在のロケール
    4FS:[0xC8]GS:[0x10C]NTFPソフトウェアステータスレジスタ
    216FS:[0xCC]GS:[0x110]NT、ワインOS(NT)、kernel32プライベートデータ(Wine)用に予約されています
    :FS:[0x124] 4 NT KTHREADETHREAD)構造体 へのポインタ
    4FS:[0x1A4]GS:[0x2C0]NT例外コード
    18FS:[0x1A8]GS:[0x2C8]NTアクティベーションコンテキストスタック
    24FS:[0x1BC]GS:[0x2E8]NT、ワイン予備バイト(NT)、ntdllプライベートデータ(Wine)
    40FS:[0x1D4]GS:[0x300]NT、ワインOS (NT)、ntdll プライベート データ (Wine) 用に予約済み
    1248FS:[0x1FC]GS:[0x350]NT、ワインGDI TEB バッチ (OS)、vm86 プライベート データ (Wine)
    4FS:[0x6DC]GS:[0x838]NTGDI地域
    4FS:[0x6E0]GS:[0x840]NTGDIペン
    4FS:[0x6E4]GS:[0x848]NTGDIブラシ
    4FS:[0x6E8]GS:[0x850]NT実プロセスID
    4FS:[0x6EC]GS:[0x858]NT実スレッドID
    4FS:[0x6F0]GS:[0x860]NTGDIキャッシュプロセスハンドル
    4FS:[0x6F4]GS:[0x868]NTGDI クライアント プロセス ID (PID)
    4FS:[0x6F8]GS:[0x86C]NTGDI クライアント スレッド ID (TID)
    4FS:[0x6FC]GS:[0x870]NTGDIスレッドロケール情報
    20FS:[0x700]GS:[0x878]NTユーザーアプリケーション用に予約済み
    1248FS:[0x714]GS:[0x890]NTGL用に予約済み(内部についてはwine refを参照)[2]
    4FS:[0xBF4]GS:[0x1250]NT最終ステータス値
    532FS:[0xBF8]GS:[0x1258]NT静的UNICODE_STRINGバッファ
    ポインタFS:[0xE0C]GS:[0x1478]NTとも呼ばれるこのDeallocationStackフィールドは、スタックバッファの実際の開始アドレスを決定し、真のスタック制限を定義します。この制限はスタック制限フィールドよりも数ページ少なくなります。これは、スタック制限フィールドがスタックの増加を管理するために使用されるガードページを含んでいるためです。[3]
    ポインタ[]FS:[0xE10]GS:[0x1480]NTTLSスロット、スロットあたり4/8バイト、64スロット
    8FS:[0xF10]GS:[0x1680]NTTLSリンク(LIST_ENTRY構造)
    4FS:[0xF18]GS:[0x1690]NTVDM
    4FS:[0xF1C]GS:[0x1698]NTRPC用に予約済み
    4FS:[0xF28]GS:[0x16B0]NTスレッドエラーモード(RtlSetThreadErrorMode
    4FS:[0xF78]GS:[0x1748]NT保証スタックバイト
    これは完全な表ではありません。FS:[0xfb4] / GS:[17c8]までのすべてのフィールドについては、wine refを参照してください。[2]新しいWindowsバージョンでは、TIBのサイズがさらに拡張され、Windows 10では最大0x1000/0x1838まで拡張されています。追加されたフィールドの一部は削除され、定義の競合が発生しています。[4]

    FS(32ビット)またはGS(64ビット)は、TDB(スレッドデータベース)と呼ばれるデータブロックに埋め込まれたTIBにマッピングされます。TIBには、スレッド固有の例外処理チェーンとTLS(スレッドローカルストレージ)へのポインタが含まれています。スレッドローカルストレージは、C言語のローカルストレージとは異なります。

    TIBに保存されるスタック情報

    プロセスは、TIB に格納されている情報を適宜更新する限り、そのスレッドのスタック0x8を自由に移動できる必要があります。この問題で重要なフィールドは、スタック ベース、スタック制限、割り当て解除スタック、保証されたスタック バイトです。これらはそれぞれ、64 ビットのオフセット、0x100x1478に格納されます0x1748。さまざまな Windowsカーネル関数がこれらの値を読み書きしますが、これは特に、スタック オーバーフローを他の読み取り/書き込みページ フォールトと区別するためです (保証されたスタック バイト内のスタック制限内で保護されているページへの読み取りまたは書き込みを行うと、アクセス違反ではなくスタック オーバーフロー例外が生成されます)。割り当て解除スタックが重要なのは、Windows API によって保護されているページの量を変更できるためです。関数では、SetThreadStackGuarantee現在のスペースの読み取りと拡張の両方が可能です。それを読み取るために、GuaranteedStackBytesフィールドを読み取り、拡張するために、スタック ページをアンコミットするために を使用します。 を設定せずにスタック制限を設定すると、でDeallocationStack異常な動作が発生する可能性がありますSetThreadStackGuarantee。たとえば、スタック制限が間違った値に上書きされます。さまざまなライブラリが を呼び出します。SetThreadStackGuaranteeたとえば、.NET CLR はそれを使用してスレッドのスタックをセットアップします。

    TIBへのアクセス

    現在のスレッドの TIB には、セグメントレジスタFS (x86) または GS (x64)のオフセットとしてアクセスできます。

    TIBフィールドへは、 からのオフセットでアクセスするのでFS:[0]はなく、まず に格納されている自己参照型の線形ポインタを取得します。このポインタは、ポインタ演算で使用したり、構造体ポインタFS:[18h]にキャストしたりできます

    Microsoft Windows SDKなどを使用すると、プログラマはwinnt.hnamedで定義されたインライン関数を使用してNtCurrentTeb、現在のスレッド情報ブロックのアドレスをとして返すことができますNT_TIB *[5]

    IA-32アーキテクチャの代替アクセス方法は次のとおりです。

    // gcc (AT&T スタイルのインライン アセンブリ)。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 サポートされていないアーキテクチャです#endif return pTIB ; }               
    // gcc (名前付きアドレス空間、-O1 または -ftree-ter のインラインアセンブリバージョンと同じ)。void * getTIB ( void ) { #if defined(__x86_64__) || defined(__amd64__) #ifndef __SEG_GS #error サポートされていない GCC バージョン#endif return * ( void * __seg_gs * ) 0x30 ; #elif defined(__i386__) #ifndef __SEG_FS #errorサポートされていない GCC バージョン#endif return * ( void * __seg_fs * ) 0x18 ; #else #error サポートされていないアーキテクチャ#endif }            
    // Microsoft C __declspec ( naked ) void * getTIB () { __asm mov EAX , FS : [ 18 h ] __asm ret }        
    // インラインアセンブリの代わりに Microsoft の組み込み関数を使用する (X86 と X64 の両方のアーキテクチャで動作します) void * getTIB () { #ifdef _M_IX86 return ( void * ) __readfsdword ( 0x18 ); #elif _M_AMD64 return ( void * ) __readgsqword ( 0x30 ); #else #error サポートされていないアーキテクチャ#endif }        

    参照

    参考文献

    1. ^ ab Pietrek, Matt (1996年5月). 「Under The Hood」. Microsoft Systems Journal . 2009年6月14日時点のオリジナルよりアーカイブ。 2010年7月7日閲覧
    2. ^ abcd "wine winternl.h: typedef struct _TEB". GitHub . wine-mirror. 2019年10月29日.
    3. ^ 「スタックガードページの詳細」2022年2月3日。
    4. ^ チャペル、ジェフ.「TEB」.
    5. ^ "NtCurrentTeb 関数". Microsoft Docs . 2019年11月20日閲覧

    さらに読む

    • NTinternals.net の TEB レイアウト
    • 構造化例外処理とTIB
    • TIBの最初のスロットの説明
    • TEBの分野ごとの説明
    • さまざまな Windows バージョンの TEB 定義
    「https://en.wikipedia.org/w/index.php?title=Win32_Thread_Information_Block&oldid=1329371019」から取得
    Original text
    Rate this translation
    Your feedback will be used to help improve Google Translate