Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

8200
629
98815


커널 오브젝트 Kernel Object - rbtree debugging(child directory) - (1) [Debugging] Tips

Crash Tool로 커널 오브젝트의 rbtree를 디버깅하는 방법에 대해 간단히 소개하고자 해요.

아래와 같은 커널 오브젝트가 있다고 가정해보아요. Sys node의 위치는 /sys/devices/system/cpu/cpu3 이겠죠?
현재 struct kobject->cpu는 "cpu3"을 가르키고 있는데요, 그럼 이 커널 오브젝트의 하위 child 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,
    (struct kref) kref = ((atomic_t) refcount = ((int) counter = 3 = 0x3)),
    (unsigned int:1) state_initialized = 1 = 0x1,
    (unsigned int:1) state_in_sysfs = 1 = 0x1,
    (unsigned int:1) state_add_uevent_sent = 1 = 0x1,
    (unsigned int:1) state_remove_uevent_sent = 0 = 0x0,
    (unsigned int:1) uevent_suppress = 0 = 0x0)
 
커널 오브젝트에서 struct kobject->sd.dir로 child directory에 대한 속성을 확인할 수 있어요. 
struct kobject.sd.dir.children.rb_node 멤버에 rb_node 주소가 있는데요. 이 rb_node에 따라 child 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
      (void *) ns = 0x0,
      (unsigned int) hash = 25910027 = 0x018B5B0B,
      (struct kernfs_elem_dir) dir = (
        (long unsigned int) subdirs = 2 = 0x2,
        (struct rb_root) children = (
          (struct rb_node *) rb_node = 0xDE213310),
        (struct kernfs_root *) root = 0xDE85EF00),
      (struct kernfs_elem_symlink) symlink = ((struct kernfs_node *) target_kn = 0x2),
      (struct kernfs_elem_attr) attr = ((struct kernfs_ops *) ops = 0x2, (struct kernfs_open_node *) o
      (void *) priv = 0xDEF78018,

Crash tool는 rbtree을 아주 쉽게 파싱할 수 있는 명령어를 제공해요. 
아래 명령어를 입력해볼까요?
crash> tree -t rbtree -o kernfs_node.rb -N 0xDE213310
de213300
de213b40
dc9c20c0
de2133c0
de213cc0
 
output 파일은 child directory의 (struct kernfs_node *) 구조체 인스턴스이거든요.
확인해볼까요?

0xde213300: "online"
  (struct kernfs_node *) (struct kernfs_node *)0xde213300 = 0xDE213300 -> (
    (atomic_t) count = ((int) counter = 0x3),
    (atomic_t) active = ((int) counter = 0x0),
    (struct kernfs_node *) parent = 0xDE213240,
    (char *) name = 0xC0F82A60 -> "online",
    (struct rb_node) rb = ((long unsigned int) __rb_parent_color = 0x1, (struct rb_node *) rb_right
    (void *) ns = 0x0,
    (unsigned int) hash = 0x4EC7CDD8,
    (struct kernfs_elem_dir) dir = ((long unsigned int) subdirs = 0xC0BDD680, (struct rb_root) child
    (struct kernfs_elem_symlink) symlink = ((struct kernfs_node *) target_kn = 0xC0BDD680),
    (struct kernfs_elem_attr) attr = ((struct kernfs_ops *) ops = 0xC0BDD680, (struct kernfs_open_no
    (void *) priv = 0xC12E9E04,
    (short unsigned int) flags = 0x0252,
    (umode_t) mode = 0x81A4,
    (unsigned int) ino = 0x14C6,
    (struct kernfs_iattrs *) iattr = 0xD9DEDB00)
 
0xde213b40: "power"
  (struct kernfs_node *) (struct kernfs_node *)0xde213b40 = 0xDE213B40 -> (
    (atomic_t) count = ((int) counter = 0x3),
    (atomic_t) active = ((int) counter = 0x0),
    (struct kernfs_node *) parent = 0xDE213240,
    (char *) name = 0xDE214000 -> "power",
    (struct rb_node) rb = ((long unsigned int) __rb_parent_color = 0xDE213310, (struct rb_node *) rb
    (void *) ns = 0x0,
    (unsigned int) hash = 0x12FD28DB,
    (struct kernfs_elem_dir) dir = ((long unsigned int) subdirs = 0x0, (struct rb_root) children = (
    (struct kernfs_elem_symlink) symlink = ((struct kernfs_node *) target_kn = 0x0),
    (struct kernfs_elem_attr) attr = ((struct kernfs_ops *) ops = 0x0, (struct kernfs_open_node *) o
    (void *) priv = 0xDEF78018,
    (short unsigned int) flags = 0x11,
 
0xdc9c20c0: "cpuidle"
  (struct kernfs_node *) (struct kernfs_node *)0xdc9c20c0 = 0xDC9C20C0 -> (
    (atomic_t) count = ((int) counter = 0x0A),
    (atomic_t) active = ((int) counter = 0x0),
    (struct kernfs_node *) parent = 0xDE213240,
    (char *) name = 0xDC993C00 -> "cpuidle",
    (struct rb_node) rb = ((long unsigned int) __rb_parent_color = 0xDE213B51, (struct rb_node *) rb
    (void *) ns = 0x0,
    (unsigned int) hash = 0x0870225E,
    (struct kernfs_elem_dir) dir = ((long unsigned int) subdirs = 0x6, (struct rb_root) children = (
    (struct kernfs_elem_symlink) symlink = ((struct kernfs_node *) target_kn = 0x6),
    (struct kernfs_elem_attr) attr = ((struct kernfs_ops *) ops = 0x6, (struct kernfs_open_node *) o
    (void *) priv = 0xDC992220,
    (short unsigned int) flags = 0x11,
    (umode_t) mode = 0x41ED,
    (unsigned int) ino = 0x4136,
    (struct kernfs_iattrs *) iattr = 0xD9DE4000)
 
0xde2133c0: "subsystem"
  (struct kernfs_node *) (struct kernfs_node *)0xde2133c0 = 0xDE2133C0 -> (
    (atomic_t) count = ((int) counter = 0x3),
    (atomic_t) active = ((int) counter = 0x0),
    (struct kernfs_node *) parent = 0xDE213240,
    (char *) name = 0xDE211900 -> "subsystem",
    (struct rb_node) rb = ((long unsigned int) __rb_parent_color = 0xDE213B51, (struct rb_node *) rb
    (void *) ns = 0x0,
    (unsigned int) hash = 0x45372B66,
    (struct kernfs_elem_dir) dir = ((long unsigned int) subdirs = 0xDEADBE40, (struct rb_root) child
    (struct kernfs_elem_symlink) symlink = ((struct kernfs_node *) target_kn = 0xDEADBE40),
    (struct kernfs_elem_attr) attr = ((struct kernfs_ops *) ops = 0xDEADBE40, (struct kernfs_open_no
    (void *) priv = 0x0,
    (short unsigned int) flags = 0x14,
    (umode_t) mode = 0xA1FF,
    (unsigned int) ino = 0x14C8,
    (struct kernfs_iattrs *) iattr = 0xD9DED400)
 
0xde213cc0: "uevent"
  (struct kernfs_node *) (struct kernfs_node *)0xde213cc0 = 0xDE213CC0 -> (
    (atomic_t) count = ((int) counter = 0x3),
    (atomic_t) active = ((int) counter = 0x0),
    (struct kernfs_node *) parent = 0xDE213240,
    (char *) name = 0xC0F7485C -> "uevent",
    (struct rb_node) rb = ((long unsigned int) __rb_parent_color = 0xDE213311, (struct rb_node *) rb
    (void *) ns = 0x0,
    (unsigned int) hash = 0x57C6BB9D,
    (struct kernfs_elem_dir) dir = ((long unsigned int) subdirs = 0xC0BDD680, (struct rb_root) child
    (struct kernfs_elem_symlink) symlink = ((struct kernfs_node *) target_kn = 0xC0BDD680),
    (struct kernfs_elem_attr) attr = ((struct kernfs_ops *) ops = 0xC0BDD680, (struct kernfs_open_no
    (void *) priv = 0xC12E9E4C,
    (short unsigned int) flags = 0x0252,
    (umode_t) mode = 0x81A4,
    (unsigned int) ino = 0x14C5,
    (struct kernfs_iattrs *) iattr = 0xD9DED500)

정리하면,
cpu3(/sys/devices/system/cpu/cpu3)의 하위 디렉토리가 "online", "power", "cpuidle", "subsystem", "uevent" 임을 알 수 있네요.

최근 디바이스 드라이버는 Platform Device모델로 적용되고 있거든요. 그래서 디바이스 노드의 상하 관계를 커널 오브젝트를 써서 표현을 많이 하거든요. 그래서 커널 오브젝트 디버깅을 잘하면 좀 더 유용한 정보를 볼 수 있어요.

덧글

댓글 입력 영역