Solaris モジューラデバッガ

レッドゾーン (0xfeedface)

上記のバッファーには、0xfeedface のパターンが頻繁に現れています。このパターンは、レッドゾーンインジケータと呼ばれるものです。これによって、アロケータ (および問題のデバッギングを行なっているプログラマ) は、「バグのある」コードがバッファーの境界を超えているかどうかを判断することができます。レッドゾーンのあとに追加の情報があります。このデータの内容はほかの要因によって異なります (「メモリー割り当てログ」を参照)。レッドゾーンとそのあとのデータ領域は、まとめて buftag 領域と呼ばれます。図 9–1 に、この情報の要約を示します。

図 9–1 レッドゾーン

この図はレッドゾーンを示しています。

バッファーのキャッシュに KMF_AUDITKMF_DEADBEEF、または KMF_REDZONE フラグが設定されている場合には、そのキャッシュの各バッファーに buftag が付加されます。buftag の内容は、KMF_AUDIT が設定されているかどうかにより異なります。

前述のメモリー領域を個別のバッファーに分解すると、次のように簡単になります。

0x70a9add8:     deadbeef        deadbeef  \
0x70a9ade0:     deadbeef        deadbeef   +- User Data (free)
0x70a9ade8:     deadbeef        deadbeef  /
0x70a9adf0:     feedface        feedface  -- REDZONE
0x70a9adf8:     70ae3260        8440c68e  -- Debugging Data

0x70a9ae00:     5               4ef83     \
0x70a9ae08:     0               0          +- User Data (allocated)
0x70a9ae10:     1               bbddcafe  /
0x70a9ae18:     feedface        139d    -- REDZONE
0x70a9ae20:     70ae3200        d1befaed  -- Debugging Data

0x70a9ae28:     deadbeef        deadbeef  \
0x70a9ae30:     deadbeef        deadbeef   +- User Data (free)
0x70a9ae38:     deadbeef        deadbeef  /
0x70a9ae40:     feedface        feedface  -- REDZONE
0x70a9ae48:     70ae31a0        8440c54e  -- Debugging Data

0x70a9add80x70a9ae28 の未使用バッファーでは、レッドゾーンには 0xfeedfacefeedface が使用されています。これは、バッファーが未使用であることを判断する便利な方法です。

0x70a9ae00 で始まる割り当て済みバッファーでは、状況は異なります。「アロケータの基礎」で説明したとおり、割り当てには、次の 2 つのタイプがあります。

1) クライアントが、kmem_cache_alloc() を使用してメモリーを要求した場合。この場合には、要求されたバッファーのサイズは、キャッシュの bufsize と等しくなります。

2) クライアントが、kmem_alloc(9F) を使用してメモリーを要求した場合。この場合には、要求されたバッファーのサイズは、キャッシュの bufsize 以下になります。たとえば、20 バイトの要求は、kmem_alloc_24 キャッシュによって満たされます。アロケータは、クライアントデータのすぐ後にマーカーとしてレッドゾーンバイトを調整して強制的にバッファー境界を合わせます。

0x70a9ae00:     5               4ef83     \
0x70a9ae08:     0               0          +- User Data (allocated)
0x70a9ae10:     1               bbddcafe  /
0x70a9ae18:     feedface        139d    -- REDZONE
0x70a9ae20:     70ae3200        d1befaed  -- Debugging Data

0x70a9ae18 にある 0xfeedface の後ろには、ランダムな値のように見える 32 ビットのワードがあります。この数字は、実際にはバッファーサイズの符号化された表現です。この数字を復号化して割り当て済みバッファーのサイズを知るには、次の公式を使用します。

size = redzone_value / 251

たとえば、この例では次のようになります。

size = 0x139d / 251 = 20 bytes.

これは、要求されたバッファーのサイズが 20 バイトであることを示しています。アロケータはこの復号化操作を行なって、レッドゾーンバイトがオフセット 20 であることを知ります。レッドゾーンバイトは 16 進数パターン 0xbb です。これは予想通り、0x729084e4 (0x729084d0 + 0t20) に存在しています。

図 9–2 kmem_alloc(9F) バッファーの例

この図は kmem_alloc バッファーの例を表しています。レッドゾーンバイト、初期化されていないデータ、デバッグデータに印が付いています。

図 9–3 に、メモリー配置の一般的形式を示します。

図 9–3 レッドゾーンバイト

この図は、ユーザーデータ領域のあとに書き込まれるレッドゾーンバイトを示しています。レッドゾーンバイトは、インデックスを復号化することで判定されます。

割り当てサイズがキャッシュの bufsize と同じである場合には、図 9–4 に示すように、レッドゾーン自体の最初のバイトにレッドゾーンバイトが上書きされます。

図 9–4 レッドゾーンの先頭にあるレッドゾーンバイト

この図はレッドゾーンを示しています。

この上書きの結果、レッドゾーンの最初の 32 ビットワードは 0xbbedface または 0xfeedfabb になります。このどちらになるかは、システムを実行しているハードウェアのエンディアンによります。


注 –

割り当てサイズがこのような方法で符号化されるのはなぜでしょうか。サイズを符号化するとき、アロケータは公式 (251 * size + 1) を使用します。サイズを復号化する際には、整数の割り算を行い、余りの「+1」は捨てられます。しかし、アロケータは (size % 251 == 1) になるかをテストすることによって、サイズが有効かどうかをチェックできるので、この 1 の加算 (「+1」) は貴重な役割を果たします。このようにして、アロケータはレッドゾーンバイトインデックスの破壊に対処します。