본문 바로가기

[Debugging] Tips

커널 오브젝트 Kernel Object - rbtree debugging(parent directory) - (2)

Crash Tool로 커널 오브젝트의 rbtree를 디버깅해서 parent node를 확인하는 방법에 대해 간단히 소개하고자 해요.
 
아래와 같은 커널 오브젝트가 있다고 가정해보아요. Sys node의 위치는 /sys/devices/system/cpu/cpu3 이겠죠?
현재 struct kobject->cpu는 "cpu3"을 가르키고 있는데요, 그럼 이 커널 오브젝트의 상위 directory는 어떻게 검색할 수 있을까요?
  (struct kobject *) (struct kobject *)0xDEF78018 = 0xDEF78018 -> (
    (char *) name = 0xDE211780 -> "cpu3",
    (struct list_head) entry = ((struct list_head *) next = 0xDEF8401C, (struct list_head *) prev = 0x
    (struct kobject *) parent = 0xDEADA288,
    (struct kset *) kset = 0xDEAF6540,
    (struct kobj_type *) ktype = 0xC12E9DF0,
    (struct kernfs_node *) sd = 0xDE213240 -> (
      (atomic_t) count = ((int) counter = 12 = 0x0C),
      (atomic_t) active = ((int) counter = 0 = 0x0),
      (struct kernfs_node *) parent = 0xDEADBC00,
      (char *) name = 0xDE211840 -> "cpu3",
      (struct rb_node) rb = (
        (long unsigned int) __rb_parent_color = 3735926096 = 0xDEADB550,
        (struct rb_node *) rb_right = 0xDE215C10,
        (struct rb_node *) rb_left = 0xDE2069D0),
 
역시 crash tool에서 rbtree를 파싱할 수 있는 기능을 제공해요.
struct kobject->sd가 갖고 있는 0xDE213240 인스턴스로 parent directory에 대한 rb_node가 있는 struct kernfs_node->rb에 접근이 가능하거든요.
crash> tree -t rbtree -o kernfs_node.rb -N 0xDE213240
de213230
deadbbf0
de862470
de862cb0
de861ff0
 
위 Output 값은 뭘 의미할까요? 좀 복잡한데요.
아래 struct kernfs_node 구조체를 보면 struct kernfs_elem_attr attr 멤버가 보이죠?
 
위 Output은 struct kernfs_elem_attr가 위치한 주소를 가르키고 있거든요.
struct kernfs_elem_attr->notify_next 오프셋이 0x10이니 0x10만큼 더해줘야 해요.
struct kernfs_elem_attr {
const struct kernfs_ops *ops;
struct kernfs_open_node *open;
loff_t size;
struct kernfs_node *notify_next;
};
(where)
struct kernfs_node {
atomic_t count;
atomic_t active;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
// .. 생략..
union {
struct kernfs_elem_dir dir;
struct kernfs_elem_symlink symlink;
struct kernfs_elem_attr attr;
};
.
뭔 소리인지 모르겠다구요? 커널 오브젝트로 디렉토리를 아래 콜 트레이스로 등록되거든요.
나중에 상세 분석할 시간을 갖도록 할께요. 핵심 함수는 kernfs_create_dir_ns/kernfs_new_node 이에요. 
\\vmlinux\kernfs/dir\__kernfs_new_node+0x60
\\vmlinux\slub\kmem_cache_alloc+0x254
\\vmlinux\kernfs/dir\__kernfs_new_node+0x60
\\vmlinux\kernfs/dir\kernfs_new_node+0x2C
\\vmlinux\kernfs/dir\kernfs_create_dir_ns+0x28
\\vmlinux\sysfs/dir\sysfs_create_dir_ns+0x5C
\\vmlinux\kobject\kobject_add_internal+0xAC
\\vmlinux\kobject\kobject_add+0x50
\\vmlinux\base/core\device_add+0x11C
 
이제 확인할 시간이에요.
(struct kernfs_node *)(0xde213230+0x10) = 0xDE213240 -> (
    count = (counter = 12),
    active = (counter = 0),
    parent = 0xDEADBC00,
    name = 0xDE211840 -> "cpu3",
(struct kernfs_node *)(0xdeadbbf0+0x10) = 0xDEADBC00 -> (
    count = (counter = 23),
    active = (counter = 0),
    parent = 0xDE862480,
    name = 0xDEAD96C0 -> "cpu",
(struct kernfs_node *)(0xde862470+0x10) = 0xDE862480 -> (
    count = (counter = 9),
    active = (counter = 0),
    parent = 0xDE862CC0,
    name = 0xDEAD7480 -> "system",
(struct kernfs_node *)(0xde862cb0+0x10) = 0xDE862CC0 -> (
    count = (counter = 36),
    active = (counter = 0),
    parent = 0xDE862000,
    name = 0xDEAF6600 -> "devices",
 
상위 디렉토리가 이렇게 확인 가능하군요.
/sys/devices/system/cpu/cpu3