Solaris 模块调试器指南

Redzone(禁区): 0xfeedface

模式 0xfeedface 频繁地在以上缓冲区中出现。 此模式称为 "redzone" 指示器。 通过此模式,分配器(以及调试问题的程序员)可以确定“错误”代码是否超出了缓冲区的边界。 redzone 后面是一些其他信息。 该数据的内容取决于其他因素(请参见内存分配日志记录)。 redzone 及其后缀统称为 buftag 区域。 图 9–1 概述了此信息。

图 9–1 Redzone

通过上下文说明的图形。

如果在高速缓存中设置了 KMF_AUDITKMF_DEADBEEFKMF_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 的空闲缓冲区中,redzone 是使用 0xfeedfacefeedface 填充的。这是确定缓冲区是否空闲的便利方法。

在从 0x70a9ae00 开始的已分配缓冲区中,情况是不同的。请回想一下分配器基础知识,有两种分配类型:

1) 客户机使用 kmem_cache_alloc() 请求的内存,在这种情况下所请求缓冲区的大小等于高速缓存的 bufsize。

2) 客户机使用 kmem_alloc (9F) 请求的内存,在这种情况下所请求缓冲区的大小小于或等于高速缓存的 bufsize。 例如,对 20 个字节的请求将从 kmem_alloc_24 高速缓存得到满足。 分配器会通过在紧邻客户机数据之后放置一个标记(即 redzone 字节)来强制设置缓冲区边界:

0x70a9ae00:     5               4ef83     \

0x70a9ae08:     0               0          +- User Data (allocated)

0x70a9ae10:     1               bbddcafe  /

0x70a9ae18:     feedface        139d    -- REDZONE

0x70a9ae20:     70ae3200        d1befaed  -- Debugging Data

位于 0x70a9ae180xfeedface 后跟一个 32 位的字,其中包含的内容看似一个随机值。 此数字实际上是缓冲区大小的编码表示形式。 要对此数字进行解码并获得已分配缓冲区的大小,请使用以下公式:

size = redzone_value / 251

因此,在本示例中,

size = 0x139d / 251 = 20 bytes.

这表明所请求缓冲区的大小为 20 个字节。 分配器将执行此解码操作,同时会发现 redzone 字节应该位于偏移量为 20 的位置。redzone 字节是十六进制模式 0xbb,如预期的那样存在于 0x729084e4 (0x729084d0 + 0t20)

图 9–2 kmem_alloc(9F) 缓冲区样例

此图形描述 kmem_alloc 缓冲区样例。redzone 字节、未初始化的数据和调试数据均已标记。

图 9–3 说明了此内存布局的常规形式。

图 9–3 Redzone 字节

此图形说明了在用户数据区域结尾后面写入的 redzone 字节。redzone 字节是通过解码索引确定的。

如果分配大小等于高速缓存的 bufsize,则 redzone 字节会覆写 redzone 本身的第一个字节,如图 9–4 中所示。

图 9–4 Redzone 开头的 Redzone 字节

通过上下文说明的图形。

此覆写操作会导致 redzone 的第一个 32 位字为 0xbbedface0xfeedfabb,具体取决于系统运行的硬件的字节存储顺序。


注意 –

为什么分配大小以该方式进行编码? 要对大小进行编码,分配器可使用公式(251 * 大小 + 1)。对大小进行解码时,整数除法将废弃余数 '+1'。 但是,加上 1 是有价值的,因为分配器可以通过测试(大小 % 251 == 1)是否成立来检查大小是否有效。 这样,分配器可防止损坏 redzone 字节索引。