17704d58aSJan Kiszka# 27704d58aSJan Kiszka# gdb helper commands and functions for Linux kernel debugging 37704d58aSJan Kiszka# 47704d58aSJan Kiszka# task & thread tools 57704d58aSJan Kiszka# 67704d58aSJan Kiszka# Copyright (c) Siemens AG, 2011-2013 77704d58aSJan Kiszka# 87704d58aSJan Kiszka# Authors: 97704d58aSJan Kiszka# Jan Kiszka <jan.kiszka@siemens.com> 107704d58aSJan Kiszka# 117704d58aSJan Kiszka# This work is licensed under the terms of the GNU GPL version 2. 127704d58aSJan Kiszka# 137704d58aSJan Kiszka 147704d58aSJan Kiszkaimport gdb 157704d58aSJan Kiszka 16*854f2764SKuan-Ying Leefrom linux import utils, lists 177704d58aSJan Kiszka 187704d58aSJan Kiszka 197704d58aSJan Kiszkatask_type = utils.CachedType("struct task_struct") 207704d58aSJan Kiszka 216ad18b73SThiébaud Weksteen 2254e2289aSDaniel Wagnerdef task_lists(): 2354e2289aSDaniel Wagner task_ptr_type = task_type.get_type().pointer() 2454e2289aSDaniel Wagner init_task = gdb.parse_and_eval("init_task").address 25*854f2764SKuan-Ying Lee t = init_task 267704d58aSJan Kiszka 2754e2289aSDaniel Wagner while True: 28*854f2764SKuan-Ying Lee thread_head = t['signal']['thread_head'] 29*854f2764SKuan-Ying Lee for thread in lists.list_for_each_entry(thread_head, task_ptr_type, 'thread_node'): 30*854f2764SKuan-Ying Lee yield thread 317704d58aSJan Kiszka 32*854f2764SKuan-Ying Lee t = utils.container_of(t['tasks']['next'], 3354e2289aSDaniel Wagner task_ptr_type, "tasks") 3454e2289aSDaniel Wagner if t == init_task: 3554e2289aSDaniel Wagner return 3647528710SJan Kiszka 376ad18b73SThiébaud Weksteen 3847528710SJan Kiszkadef get_task_by_pid(pid): 3954e2289aSDaniel Wagner for task in task_lists(): 4047528710SJan Kiszka if int(task['pid']) == pid: 4147528710SJan Kiszka return task 4247528710SJan Kiszka return None 4347528710SJan Kiszka 4447528710SJan Kiszka 4547528710SJan Kiszkaclass LxTaskByPidFunc(gdb.Function): 4647528710SJan Kiszka """Find Linux task by PID and return the task_struct variable. 4747528710SJan Kiszka 4847528710SJan Kiszka$lx_task_by_pid(PID): Given PID, iterate over all tasks of the target and 4947528710SJan Kiszkareturn that task_struct variable which PID matches.""" 5047528710SJan Kiszka 5147528710SJan Kiszka def __init__(self): 5247528710SJan Kiszka super(LxTaskByPidFunc, self).__init__("lx_task_by_pid") 5347528710SJan Kiszka 5447528710SJan Kiszka def invoke(self, pid): 5547528710SJan Kiszka task = get_task_by_pid(pid) 5647528710SJan Kiszka if task: 5747528710SJan Kiszka return task.dereference() 5847528710SJan Kiszka else: 5947528710SJan Kiszka raise gdb.GdbError("No task of PID " + str(pid)) 6047528710SJan Kiszka 6147528710SJan Kiszka 6247528710SJan KiszkaLxTaskByPidFunc() 63cf7492e9SJan Kiszka 64cf7492e9SJan Kiszka 65a930850bSThiébaud Weksteenclass LxPs(gdb.Command): 66a930850bSThiébaud Weksteen """Dump Linux tasks.""" 67a930850bSThiébaud Weksteen 68a930850bSThiébaud Weksteen def __init__(self): 69a930850bSThiébaud Weksteen super(LxPs, self).__init__("lx-ps", gdb.COMMAND_DATA) 70a930850bSThiébaud Weksteen 71a930850bSThiébaud Weksteen def invoke(self, arg, from_tty): 724fbe310eSRitesh Harjani gdb.write("{:>10} {:>12} {:>7}\n".format("TASK", "PID", "COMM")) 73a930850bSThiébaud Weksteen for task in task_lists(): 744fbe310eSRitesh Harjani gdb.write("{} {:^5} {}\n".format( 754fbe310eSRitesh Harjani task.format_string().split()[0], 764fbe310eSRitesh Harjani task["pid"].format_string(), 774fbe310eSRitesh Harjani task["comm"].string())) 78a930850bSThiébaud Weksteen 79494dbe02SStephen Boyd 80a930850bSThiébaud WeksteenLxPs() 81a930850bSThiébaud Weksteen 82a930850bSThiébaud Weksteen 83cf7492e9SJan Kiszkathread_info_type = utils.CachedType("struct thread_info") 84cf7492e9SJan Kiszka 85cf7492e9SJan Kiszka 86cf7492e9SJan Kiszkadef get_thread_info(task): 87cf7492e9SJan Kiszka thread_info_ptr_type = thread_info_type.get_type().pointer() 88883d50f5SXi Kangjie if task.type.fields()[0].type == thread_info_type.get_type(): 89883d50f5SXi Kangjie return task['thread_info'] 90cf7492e9SJan Kiszka thread_info = task['stack'].cast(thread_info_ptr_type) 91cf7492e9SJan Kiszka return thread_info.dereference() 92cf7492e9SJan Kiszka 93cf7492e9SJan Kiszka 94cf7492e9SJan Kiszkaclass LxThreadInfoFunc (gdb.Function): 95cf7492e9SJan Kiszka """Calculate Linux thread_info from task variable. 96cf7492e9SJan Kiszka 97cf7492e9SJan Kiszka$lx_thread_info(TASK): Given TASK, return the corresponding thread_info 98cf7492e9SJan Kiszkavariable.""" 99cf7492e9SJan Kiszka 100cf7492e9SJan Kiszka def __init__(self): 101cf7492e9SJan Kiszka super(LxThreadInfoFunc, self).__init__("lx_thread_info") 102cf7492e9SJan Kiszka 103cf7492e9SJan Kiszka def invoke(self, task): 104cf7492e9SJan Kiszka return get_thread_info(task) 105cf7492e9SJan Kiszka 106cf7492e9SJan Kiszka 107cf7492e9SJan KiszkaLxThreadInfoFunc() 1089f66dee7SKieran Bingham 1099f66dee7SKieran Bingham 1109f66dee7SKieran Binghamclass LxThreadInfoByPidFunc (gdb.Function): 1119f66dee7SKieran Bingham """Calculate Linux thread_info from task variable found by pid 1129f66dee7SKieran Bingham 1139f66dee7SKieran Bingham$lx_thread_info_by_pid(PID): Given PID, return the corresponding thread_info 1149f66dee7SKieran Binghamvariable.""" 1159f66dee7SKieran Bingham 1169f66dee7SKieran Bingham def __init__(self): 1179f66dee7SKieran Bingham super(LxThreadInfoByPidFunc, self).__init__("lx_thread_info_by_pid") 1189f66dee7SKieran Bingham 1199f66dee7SKieran Bingham def invoke(self, pid): 1209f66dee7SKieran Bingham task = get_task_by_pid(pid) 1219f66dee7SKieran Bingham if task: 1229f66dee7SKieran Bingham return get_thread_info(task.dereference()) 1239f66dee7SKieran Bingham else: 1249f66dee7SKieran Bingham raise gdb.GdbError("No task of PID " + str(pid)) 1259f66dee7SKieran Bingham 126494dbe02SStephen Boyd 1279f66dee7SKieran BinghamLxThreadInfoByPidFunc() 128