본문 바로가기

[Debugging] Tips

[리눅스커널] 크래시 유틸리티(Crash-Utility): 슬랩 페이지의 갯수를 확인하는 방법

크래시 유틸리티 프로그램을 실행할 때 페이지 디스크립터가 위치한 vmemmap의 범위는
'ffffffbc00000000 - ffffffbdffffffff'와 같습니다.
 
crash64: kernel image: ffffff96ff280000 - ffffff9702265000
crash64:      vmemmap: ffffffbc00000000 - ffffffbdffffffff
 
kmalloc 슬랩 캐시를 확인해보겠습니다.
 
crash64> p kmalloc_caches
kmalloc_caches = $1 =
 {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffc6008fdc80, 0xffffffc6008fdb00, 0xffffffc6008fd980, 0xffffffc6008fd800, 0xffffffc6008fd680, 0xffffffc6008fd500, 0xffffffc6008fd380}
 
0xffffffc6008fdb00 주소에 해당하는 슬랩 캐시의 정체는 다음과 같습니다.
 
crash64> struct kmem_cache.name 0xffffffc6008fdb00
  name = 0xffffff9700f6e049 "kmalloc-256"
 
페이지 디스크립터 구조체를 보면 포인터 형인 slab_cache 필드가 있습니다.
crash64> struct page
struct page {
    unsigned long flags;
...
        struct {
            union {
                struct list_head slab_list;
                struct {
                    struct page *next;
                    int pages;
                    int pobjects;
                };
            };
            struct kmem_cache *slab_cache;
            void *freelist;
...
 
crash64_kaslr> struct page.slab_cache
struct page {
  [0x18]         struct kmem_cache *slab_cache;
}
 
그래서 슬랩 캐시의 주소 검색을 통해 해당 슬랩 캐시의 페이지 갯수를 확인할 수 있습니다.
 
crash64_kaslr> search 0xffffffc6008fdb00
ffffff80156ab8a0: ffffffc6008fdb00
ffffff97012c4a00: ffffffc6008fdb00
ffffffbf18023e98: ffffffc6008fdb00
...
 
vmemmap의 시작 주소가 ffffffbc00000000 이므로 ffffff80156ab8a0와 ffffff97012c4a00 주소에 위치한 슬랩 캐시의 주소는 별 의미가 없습니다.
 
vmemmap 메모리 공간에서 "kmalloc-256" 슬랩 캐시를 포함하는 페이지 디스크립터의 갯수는 880개입니다.
 
crash64> search 0xffffffc6008fdb00 | wc -l
882
 
// 880 = 882 - 2
 
이번에는 "kmalloc-128" 슬랩 캐시의 페이지 디스크립터의 갯수를 확인하겠습니다.
 
crash64_kaslr> struct kmem_cache.name 0xffffffc6008fdb00 
  name = 0xffffff9700f6e03d "kmalloc-128"
 
엄청난 갯수의 페이지 디스크립터를 사용하고 있습니다.
 
crash64> search  0xffffffc6008fdc80 | wc -l
891606
 
vmemmap의 범위('ffffffbc00000000 - ffffffbdffffffff') 밖의 주소가 포함하는 "kmalloc-128" 슬랩 캐시의 갯수는
16이므로, 891590(891606 - 16) 개의 페이지를 소진하고 있습니다.
 
crash64> search  0xffffffc6008fdc80
ffffff80083ab670: ffffffc6008fdc80
ffffff80083ab6f8: ffffffc6008fdc80
ffffff800951bc20: ffffffc6008fdc80
ffffff800951bc30: ffffffc6008fdc80
ffffff800951bc50: ffffffc6008fdc80
ffffff800958b8b0: ffffffc6008fdc80
ffffff800958b8c0: ffffffc6008fdc80
ffffff80145bbba0: ffffffc6008fdc80
ffffff8015a0bab0: ffffffc6008fdc80
ffffff8015e9bb30: ffffffc6008fdc80
ffffff801647b6d0: ffffffc6008fdc80
ffffff801772b830: ffffffc6008fdc80
ffffff8017a5b830: ffffffc6008fdc80
ffffff8017a5b840: ffffffc6008fdc80
ffffff8021223ab0: ffffffc6008fdc80
ffffff97012c49f8: ffffffc6008fdc80
 
"kmalloc-128" 슬랩 오브젝트의 Leak을 확인할 필요가 있습니다.
 
 
# Reference: For more information on 'Linux Kernel';
 
디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1
 
디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2