Solaris 模块调试器指南

内存分配日志记录

本节说明内核内存分配器的日志记录功能以及如何使用它们调试系统崩溃。

buftag 数据完整性

如前所述,每个 buftag 的后半部分包含了有关对应缓冲区的额外信息。 此数据中一部分是调试信息,一部分是分配器的专用数据。 尽管此辅助数据可以采用几种不同的形式,但是它统称为“缓冲区控制”或 bufctl 数据。

不过,分配器需要知道缓冲区的 bufctl 指针是否有效,因为该指针也可能由于异常代码而损坏。 分配器通过存储其辅助指针该指针的编码版本,然后交叉检查这两个版本来确认该指针的完整性。

图 9–5 中所示,这些指针是 bcp(缓冲区控制指针)和 bxstat(缓冲区控制 XOR 状态)。 分配器会对 bcp 和 bxstat 进行排列,以便表达式 bcp XOR bxstat 等于已知值。

图 9–5 buftag 中的额外调试数据

图形由上下文说明。

这两个指针中的一个或两个损坏时,分配器可以轻易检测到此类损坏,并会导致系统出现紧急情况。分配缓冲区后,bcp XOR bxstat = 0xa110c8ed ("allocated")。缓冲区空闲时,bcp XOR bxstat = 0xf4eef4ee ("freefree")。


注意 –

您可能会发现重新检查检查已释放的缓冲区: 0xdeadbeef中的示例会有助于确认那里显示的 buftag 指针是否一致。


分配器找到损坏的 buftag 时,会导致系统出现紧急情况,并生成与以下内容类似的消息:

kernel memory allocator: boundary tag corrupted

    bcp ^ bxstat = 0xffeef4ee, should be f4eef4ee

请记住,如果 bcp 已损坏,仍可通过采用 bxstat XOR 0xf4eef4eebxstat XOR 0xa110c8ed(取决于缓冲区是已分配的还是空闲的)的值来对其值进行检索。

bufctl 指针

包含在 buftag 区域中的缓冲区控制 (bufctl) 指针可以具有不同的含义,具体取决于高速缓存的 kmem_flags。 需要特别注意的是,KMF_AUDIT 标志的设置情况不同,具体的行为也会有所不同:如果设置 KMF_AUDIT 标志,则内核内存分配器会为每个缓冲区分配一个 kmem_bufctl_t 结构。 此结构包含有关每个缓冲区的一些最少记帐信息。 如果 设置了 KMF_AUDIT 标志,则分配器会改为分配 kmem_bufctl_audit_tkmem_bufctl_t 的扩展版本)。

本节假定已设置了 KMF_AUDIT 标志。对于未设置此位的高速缓存,可用的调试信息量会减少。

kmem_bufctl_audit_t(简称 bufctl_audit)包含有关此缓冲区中执行的最后一个事务的其他信息。以下示例说明了如何应用 bufctl_audit 宏检查审计记录。 所示的缓冲区是检测内存损坏中使用的示例缓冲区:

> 0x70a9ae00,5/KKn

0x70a9ae00:     5               4ef83

                0               0

                1               bbddcafe

                feedface        139d

                70ae3200        d1befaed

使用如上所述的方法可以很容易地看到 0x70ae3200 指向 bufctl_audit 记录:它是 redzone 后面的第一个指针。 要检查它所指向的 bufctl_audit 记录,请应用 bufctl_audit 宏:

> 0x70ae3200$<bufctl_audit

0x70ae3200:     next            addr            slab

                70378000        70a9ae00        707c86a0

0x70ae320c:     cache           timestamp       thread

                70039928        e1bd0e26afe     70aac4e0

0x70ae321c:     lastlog         contents        stackdepth

                7011c7c0        7018a0b0        4

0x70ae3228:

                kmem_zalloc+0x30

                pid_assign+8

                getproc+0x68

                cfork+0x60

'addr' 字段是对应于此 bufctl_audit 记录的缓冲区的地址。 以下是原始地址:0x70a9ae00。'cache' 字段是指已分配此缓冲区的 kmem_cache。可以使用 ::kmem_cache dcmd 对其进行检查,如下所示:

> 0x70039928::kmem_cache

ADDR     NAME                      FLAG  CFLAG  BUFSIZE  BUFTOTL

70039928 kmem_alloc_24             020f 000000       24      612

'timestamp' 字段表示执行此事务的时间。此时间的表示方式与 gethrtime(3C) 相同。

'thread' 是指向线程的指针,该线程在此缓冲区中执行了最后一个事务。 'lastlog' 和 'contents' 指针指向分配器的事务日志中的位置。 这些日志将在分配器日志记录工具中详细讨论。

通常,bufctl_audit 提供的最有用的信息段是事务发生时记录的栈跟踪。 在这种情况下,事务是在执行 fork(2) 的过程中调用的分配。