xref: /OK3568_Linux_fs/kernel/scripts/gdb/linux/tasks.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#
2*4882a593Smuzhiyun# gdb helper commands and functions for Linux kernel debugging
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun#  task & thread tools
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun# Copyright (c) Siemens AG, 2011-2013
7*4882a593Smuzhiyun#
8*4882a593Smuzhiyun# Authors:
9*4882a593Smuzhiyun#  Jan Kiszka <jan.kiszka@siemens.com>
10*4882a593Smuzhiyun#
11*4882a593Smuzhiyun# This work is licensed under the terms of the GNU GPL version 2.
12*4882a593Smuzhiyun#
13*4882a593Smuzhiyun
14*4882a593Smuzhiyunimport gdb
15*4882a593Smuzhiyun
16*4882a593Smuzhiyunfrom linux import utils
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun
19*4882a593Smuzhiyuntask_type = utils.CachedType("struct task_struct")
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun
22*4882a593Smuzhiyundef task_lists():
23*4882a593Smuzhiyun    task_ptr_type = task_type.get_type().pointer()
24*4882a593Smuzhiyun    init_task = gdb.parse_and_eval("init_task").address
25*4882a593Smuzhiyun    t = g = init_task
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun    while True:
28*4882a593Smuzhiyun        while True:
29*4882a593Smuzhiyun            yield t
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun            t = utils.container_of(t['thread_group']['next'],
32*4882a593Smuzhiyun                                   task_ptr_type, "thread_group")
33*4882a593Smuzhiyun            if t == g:
34*4882a593Smuzhiyun                break
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun        t = g = utils.container_of(g['tasks']['next'],
37*4882a593Smuzhiyun                                   task_ptr_type, "tasks")
38*4882a593Smuzhiyun        if t == init_task:
39*4882a593Smuzhiyun            return
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun
42*4882a593Smuzhiyundef get_task_by_pid(pid):
43*4882a593Smuzhiyun    for task in task_lists():
44*4882a593Smuzhiyun        if int(task['pid']) == pid:
45*4882a593Smuzhiyun            return task
46*4882a593Smuzhiyun    return None
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun
49*4882a593Smuzhiyunclass LxTaskByPidFunc(gdb.Function):
50*4882a593Smuzhiyun    """Find Linux task by PID and return the task_struct variable.
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun$lx_task_by_pid(PID): Given PID, iterate over all tasks of the target and
53*4882a593Smuzhiyunreturn that task_struct variable which PID matches."""
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun    def __init__(self):
56*4882a593Smuzhiyun        super(LxTaskByPidFunc, self).__init__("lx_task_by_pid")
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun    def invoke(self, pid):
59*4882a593Smuzhiyun        task = get_task_by_pid(pid)
60*4882a593Smuzhiyun        if task:
61*4882a593Smuzhiyun            return task.dereference()
62*4882a593Smuzhiyun        else:
63*4882a593Smuzhiyun            raise gdb.GdbError("No task of PID " + str(pid))
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun
66*4882a593SmuzhiyunLxTaskByPidFunc()
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun
69*4882a593Smuzhiyunclass LxPs(gdb.Command):
70*4882a593Smuzhiyun    """Dump Linux tasks."""
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun    def __init__(self):
73*4882a593Smuzhiyun        super(LxPs, self).__init__("lx-ps", gdb.COMMAND_DATA)
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun    def invoke(self, arg, from_tty):
76*4882a593Smuzhiyun        gdb.write("{:>10} {:>12} {:>7}\n".format("TASK", "PID", "COMM"))
77*4882a593Smuzhiyun        for task in task_lists():
78*4882a593Smuzhiyun            gdb.write("{} {:^5} {}\n".format(
79*4882a593Smuzhiyun                task.format_string().split()[0],
80*4882a593Smuzhiyun                task["pid"].format_string(),
81*4882a593Smuzhiyun                task["comm"].string()))
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun
84*4882a593SmuzhiyunLxPs()
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun
87*4882a593Smuzhiyunthread_info_type = utils.CachedType("struct thread_info")
88*4882a593Smuzhiyun
89*4882a593Smuzhiyunia64_task_size = None
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun
92*4882a593Smuzhiyundef get_thread_info(task):
93*4882a593Smuzhiyun    thread_info_ptr_type = thread_info_type.get_type().pointer()
94*4882a593Smuzhiyun    if utils.is_target_arch("ia64"):
95*4882a593Smuzhiyun        global ia64_task_size
96*4882a593Smuzhiyun        if ia64_task_size is None:
97*4882a593Smuzhiyun            ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)")
98*4882a593Smuzhiyun        thread_info_addr = task.address + ia64_task_size
99*4882a593Smuzhiyun        thread_info = thread_info_addr.cast(thread_info_ptr_type)
100*4882a593Smuzhiyun    else:
101*4882a593Smuzhiyun        if task.type.fields()[0].type == thread_info_type.get_type():
102*4882a593Smuzhiyun            return task['thread_info']
103*4882a593Smuzhiyun        thread_info = task['stack'].cast(thread_info_ptr_type)
104*4882a593Smuzhiyun    return thread_info.dereference()
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun
107*4882a593Smuzhiyunclass LxThreadInfoFunc (gdb.Function):
108*4882a593Smuzhiyun    """Calculate Linux thread_info from task variable.
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun$lx_thread_info(TASK): Given TASK, return the corresponding thread_info
111*4882a593Smuzhiyunvariable."""
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun    def __init__(self):
114*4882a593Smuzhiyun        super(LxThreadInfoFunc, self).__init__("lx_thread_info")
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun    def invoke(self, task):
117*4882a593Smuzhiyun        return get_thread_info(task)
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun
120*4882a593SmuzhiyunLxThreadInfoFunc()
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun
123*4882a593Smuzhiyunclass LxThreadInfoByPidFunc (gdb.Function):
124*4882a593Smuzhiyun    """Calculate Linux thread_info from task variable found by pid
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun$lx_thread_info_by_pid(PID): Given PID, return the corresponding thread_info
127*4882a593Smuzhiyunvariable."""
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun    def __init__(self):
130*4882a593Smuzhiyun        super(LxThreadInfoByPidFunc, self).__init__("lx_thread_info_by_pid")
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun    def invoke(self, pid):
133*4882a593Smuzhiyun        task = get_task_by_pid(pid)
134*4882a593Smuzhiyun        if task:
135*4882a593Smuzhiyun            return get_thread_info(task.dereference())
136*4882a593Smuzhiyun        else:
137*4882a593Smuzhiyun            raise gdb.GdbError("No task of PID " + str(pid))
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun
140*4882a593SmuzhiyunLxThreadInfoByPidFunc()
141