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모델로 적용되고 있거든요. 그래서 디바이스 노드의 상하 관계를 커널 오브젝트를 써서 표현을 많이 하거든요. 그래서 커널 오브젝트 디버깅을 잘하면 좀 더 유용한 정보를 볼 수 있어요.
'[Debugging] Tips' 카테고리의 다른 글
Trace32 - Memory Class 메모리 클래스 (0) | 2023.05.04 |
---|---|
Trace32 유용한 명령어 - y.b (0) | 2023.05.04 |
커널 오브젝트 Kernel Object - rbtree debugging(parent directory) - (2) (0) | 2023.05.04 |
IPI (Inter Processor Interrupts) 소개 및 디버깅 패치 (1) (0) | 2023.05.04 |
[crash-utility]wakelock - rbtree debugging(디버깅) (0) | 2023.05.04 |