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