[DESCRIPTION]
踩内存通常很难排查,原因在于踩内存的时候不一定崩溃,所以我们要千方百计加强各种内存检查。
在quick start里有专题讲解踩内存问题:
- MediaTek On-Line> Quick Start> 踩内存专题分析
kernel中使用的内存大部分来自slub,因此slub的调试非常重要。
slub本身是自带调试功能的,不过只有
eng版本有开,user、userdebug默认关闭。
以下列出slub的调试功能:
kernel-3.18/include/linux/slab.h
[C/C++]
hide
1
2
3
4
5
6
7
|
#define SLAB_DEBUG_FREE 0x00000100UL /* DEBUG: Perform (expensive) checks on free */
#define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */
#define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */
#define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */
|
red zone可以检查内存越界问题,但由于slub的设计是固定大小的内存池,导致有部分空间是没有使用的(比如:申请1字节,slub给你8字节,7字节没有被使用),这导致了有些小范围越界无法被检查出来。
为了能检查到所有越界的行为,就必须记录申请时的大小,然后根据实际大小设定red zone区域。以下讲解方法。
[SOLUTION]
前提是打开了CONFIG_SLUB_DEBUG,CONFIG_SLUB_DEBUG_ON
1. 修改slab_alloc_node相关的函数,传入申请的内存大小,并初始化red zone。
1) 修改slab_alloc_node()函数,多添加一个参数size和相关代码:
[C/C++]
hide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
static
__always_inline
void
*slab_alloc_node(
struct
kmem_cache *s,
size_t
size
/* 添加size参数 */
, gfp_t gfpflags,
int
node, unsigned
long
addr)
{
......
if
(unlikely(gfpflags & __GFP_ZERO) && object)
memset
(object, 0, s->object_size);
/* 添加这段代码 */
if
(object && (s->flags&SLAB_RED_ZONE)) {
size = s->object_size - size;
set_freepointer(s, object, (
void
*)(
uintptr_t
)size);
if
(size)
memset
((
void
*)object + s->object_size - size, SLUB_RED_ACTIVE, size);
/* 初始化red zone */
}
/* 添加结束 */
slab_post_alloc_hook(s, gfpflags, object);
return
object;
}
|
2) 所有调用slab_alloc_node()函数的函数都要修改,多添加一个参数size:
[C/C++]
hide
1
2
3
|