Commit | Line | Data |
---|---|---|
7704d58a JK |
1 | # |
2 | # gdb helper commands and functions for Linux kernel debugging | |
3 | # | |
4 | # task & thread tools | |
5 | # | |
6 | # Copyright (c) Siemens AG, 2011-2013 | |
7 | # | |
8 | # Authors: | |
9 | # Jan Kiszka <jan.kiszka@siemens.com> | |
10 | # | |
11 | # This work is licensed under the terms of the GNU GPL version 2. | |
12 | # | |
13 | ||
14 | import gdb | |
15 | ||
16 | from linux import utils | |
17 | ||
18 | ||
19 | task_type = utils.CachedType("struct task_struct") | |
20 | ||
6ad18b73 | 21 | |
54e2289a DW |
22 | def task_lists(): |
23 | global task_type | |
24 | task_ptr_type = task_type.get_type().pointer() | |
25 | init_task = gdb.parse_and_eval("init_task").address | |
26 | t = g = init_task | |
27 | ||
28 | while True: | |
29 | while True: | |
30 | yield t | |
31 | ||
32 | t = utils.container_of(t['thread_group']['next'], | |
33 | task_ptr_type, "thread_group") | |
34 | if t == g: | |
35 | break | |
36 | ||
37 | t = g = utils.container_of(g['tasks']['next'], | |
38 | task_ptr_type, "tasks") | |
39 | if t == init_task: | |
40 | return | |
47528710 | 41 | |
6ad18b73 | 42 | |
47528710 | 43 | def get_task_by_pid(pid): |
54e2289a | 44 | for task in task_lists(): |
47528710 JK |
45 | if int(task['pid']) == pid: |
46 | return task | |
47 | return None | |
48 | ||
49 | ||
50 | class LxTaskByPidFunc(gdb.Function): | |
51 | """Find Linux task by PID and return the task_struct variable. | |
52 | ||
53 | $lx_task_by_pid(PID): Given PID, iterate over all tasks of the target and | |
54 | return that task_struct variable which PID matches.""" | |
55 | ||
56 | def __init__(self): | |
57 | super(LxTaskByPidFunc, self).__init__("lx_task_by_pid") | |
58 | ||
59 | def invoke(self, pid): | |
60 | task = get_task_by_pid(pid) | |
61 | if task: | |
62 | return task.dereference() | |
63 | else: | |
64 | raise gdb.GdbError("No task of PID " + str(pid)) | |
65 | ||
66 | ||
67 | LxTaskByPidFunc() | |
cf7492e9 JK |
68 | |
69 | ||
70 | thread_info_type = utils.CachedType("struct thread_info") | |
71 | ||
72 | ia64_task_size = None | |
73 | ||
74 | ||
75 | def get_thread_info(task): | |
76 | global thread_info_type | |
77 | thread_info_ptr_type = thread_info_type.get_type().pointer() | |
78 | if utils.is_target_arch("ia64"): | |
79 | global ia64_task_size | |
80 | if ia64_task_size is None: | |
81 | ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)") | |
82 | thread_info_addr = task.address + ia64_task_size | |
83 | thread_info = thread_info_addr.cast(thread_info_ptr_type) | |
84 | else: | |
85 | thread_info = task['stack'].cast(thread_info_ptr_type) | |
86 | return thread_info.dereference() | |
87 | ||
88 | ||
89 | class LxThreadInfoFunc (gdb.Function): | |
90 | """Calculate Linux thread_info from task variable. | |
91 | ||
92 | $lx_thread_info(TASK): Given TASK, return the corresponding thread_info | |
93 | variable.""" | |
94 | ||
95 | def __init__(self): | |
96 | super(LxThreadInfoFunc, self).__init__("lx_thread_info") | |
97 | ||
98 | def invoke(self, task): | |
99 | return get_thread_info(task) | |
100 | ||
101 | ||
102 | LxThreadInfoFunc() |