def _format_last_run(self, task: LinuxTask, state: str) -> str: pid = task.task_pid() addr = task.task_address() cpu = task.get_last_cpu() name = task.task_name() if task.active: cpu = task.cpu line = f"[{task.last_run():d}] [{state}] PID: {pid:-5d} " line += f"TASK: {addr:x} CPU: {cpu:>2d} COMMAND: \"{name}\"" return line
def setup_tasks(self): init_task = gdb.lookup_global_symbol('init_task') task_list = init_task.value()['tasks'] runqueues = gdb.lookup_global_symbol('runqueues') rqs = get_percpu_var(runqueues) rqscurrs = {long(x["curr"]) : k for (k, x) in rqs.items()} self.pid_to_task_struct = {} print("Loading tasks...", end='') sys.stdout.flush() task_count = 0 tasks = [] for taskg in list_for_each_entry(task_list, init_task.type, 'tasks'): tasks.append(taskg) for task in list_for_each_entry(taskg['thread_group'], init_task.type, 'thread_group'): tasks.append(task) for task in tasks: cpu = None regs = None active = long(task.address) in rqscurrs if active: cpu = rqscurrs[long(task.address)] regs = self.kdump.attr.cpu[cpu].reg ltask = LinuxTask(task, active, cpu, regs) ptid = (LINUX_KERNEL_PID, task['pid'], 0) try: thread = gdb.selected_inferior().new_thread(ptid, ltask) except gdb.error as e: print("Failed to setup task @{:#x}".format(long(task.address))) continue thread.name = task['comm'].string() self.arch.setup_thread_info(thread) ltask.attach_thread(thread) ltask.set_get_stack_pointer(self.arch.get_stack_pointer) crash.cache.tasks.cache_task(ltask) task_count += 1 if task_count % 100 == 0: print(".", end='') sys.stdout.flush() print(" done. ({} tasks total)".format(task_count)) gdb.selected_inferior().executing = False
def setup_tasks(self) -> None: """ Populate GDB's thread list using the kernel's task lists This method will iterate over the kernel's task lists, create a LinuxTask object, and create a gdb thread for each one. The threads will be built so that the registers are ready to be populated, which allows symbolic stack traces to be made available. """ from crash.types.percpu import get_percpu_vars from crash.types.task import LinuxTask, for_each_all_tasks import crash.cache.tasks # pylint: disable=redefined-outer-name gdb.execute('set print thread-events 0') rqs = get_percpu_vars(self.symbols.runqueues) rqscurrs = {int(x["curr"]): k for (k, x) in rqs.items()} print("Loading tasks...", end='') sys.stdout.flush() task_count = 0 try: crashing_cpu = int(get_symbol_value('crashing_cpu')) except MissingSymbolError: crashing_cpu = -1 for task in for_each_all_tasks(): ltask = LinuxTask(task) active = int(task.address) in rqscurrs if active: cpu = rqscurrs[int(task.address)] regs = self.vmcore.attr.cpu[cpu].reg ltask.set_active(cpu, regs) ptid = (LINUX_KERNEL_PID, task['pid'], 0) try: thread = gdb.selected_inferior().new_thread(ptid) thread.info = ltask except gdb.error: print("Failed to setup task @{:#x}".format(int(task.address))) continue thread.name = task['comm'].string() if active and cpu == crashing_cpu: self.crashing_thread = thread self.arch.setup_thread_info(thread) ltask.attach_thread(thread) ltask.set_get_stack_pointer(self.arch.get_stack_pointer) crash.cache.tasks.cache_task(ltask) task_count += 1 if task_count % 100 == 0: print(".", end='') sys.stdout.flush() print(" done. ({} tasks total)".format(task_count)) gdb.selected_inferior().executing = False
def task_state_string(self, task: LinuxTask) -> str: state = task.task_state() buf = "" for bits in sorted(self.task_states.keys(), reverse=True): if (state & bits) == bits: buf = self.task_states[bits] break if state & TF.TASK_DEAD and task.maybe_dead(): buf = self.task_states[TF.TASK_DEAD] if not buf: print(f"Unknown state {state} found") return buf
def _format_common_line(self, task: LinuxTask, state: str) -> str: pid = task.task_pid() parent_pid = task.parent_pid() last_cpu = task.get_last_cpu() name = task.task_name() # This needs adaptation for page size != 4k total_vm = task.total_vm * 4096 // 1024 rss = task.rss * 4096 // 1024 if task.active: active = ">" else: active = " " line = f"{active} {pid:>5} {parent_pid:>5} {last_cpu:>3} " line += self._format_column4(task) line += f" {state:3} {0:.1f} {total_vm:7d} {rss:6d} {name}" return line
def setup_tasks(self): gdb.execute('set print thread-events 0') init_task = gdb.lookup_global_symbol('init_task') task_list = init_task.value()['tasks'] runqueues = gdb.lookup_global_symbol('runqueues') rqs = get_percpu_var(runqueues) rqscurrs = {long(x["curr"]): k for (k, x) in rqs.items()} self.pid_to_task_struct = {} print("Loading tasks...", end='') sys.stdout.flush() task_count = 0 tasks = [] for taskg in list_for_each_entry(task_list, init_task.type, 'tasks', include_head=True): tasks.append(taskg) for task in list_for_each_entry(taskg['thread_group'], init_task.type, 'thread_group'): tasks.append(task) for task in tasks: cpu = None regs = None active = long(task.address) in rqscurrs if active: cpu = rqscurrs[long(task.address)] regs = self.vmcore.attr.cpu[cpu].reg ltask = LinuxTask(task, active, cpu, regs) ptid = (LINUX_KERNEL_PID, task['pid'], 0) try: thread = gdb.selected_inferior().new_thread(ptid, ltask) except gdb.error as e: print("Failed to setup task @{:#x}".format(long(task.address))) continue thread.name = task['comm'].string() self.target.arch.setup_thread_info(thread) ltask.attach_thread(thread) ltask.set_get_stack_pointer(self.target.arch.get_stack_pointer) crash.cache.tasks.cache_task(ltask) task_count += 1 if task_count % 100 == 0: print(".", end='') sys.stdout.flush() print(" done. ({} tasks total)".format(task_count)) gdb.selected_inferior().executing = False
def should_print_task(self, task: LinuxTask) -> bool: """ Given optional filters and regex as part of the parent object, return whether a task passes the criteria to be printed. Args: task (LinuxTask): The task under consideration Returns: bool: Whether this task should be printed """ if self._filter(task) is False: return False if self._regex and not self._regex.match(task.task_name()): return False return True
def _is_thread_group_leader(self, task: LinuxTask) -> bool: return task.is_thread_group_leader()
def _is_kernel_thread(self, task: LinuxTask) -> bool: return task.is_kernel_task()
def _format_stack_address(self, task: LinuxTask) -> str: addr = int(task.get_stack_pointer()) return f"{addr:16x}"