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 test_voidp_test(self): var = gdb.lookup_symbol('voidp_test', None)[0] self.assertTrue(var is not None) for cpu, val in list(percpu.get_percpu_vars(var).items()): self.assertTrue(val is not None) self.assertTrue(val.type == self.voidp) self.assertTrue(int(val) == 0xdeadbeef)
def test_runqueues(self): rqs = gdb.lookup_symbol('runqueues', None)[0] rq_type = gdb.lookup_type('struct rq') self.assertTrue(rqs.type == rq_type) pcpu = get_percpu_vars(rqs) for (cpu, rq) in pcpu.items(): self.assertTrue(type(cpu) is int) self.assertTrue(type(rq) is gdb.Value) self.assertTrue(rq.type == rq_type)
def test_percpu_ptr_val(self): var = gdb.lookup_symbol('percpu_test', None)[0].value() self.assertTrue(var is not None) for cpu, val in list(percpu.get_percpu_vars(var).items()): self.assertTrue(val.type == self.test_struct)
def test_struct_test_ptr(self): var = gdb.lookup_symbol('ptr_to_struct_test', None)[0] self.assertTrue(var is not None) for cpu, val in list(percpu.get_percpu_vars(var).items()): self.assertTrue(val['x'] == cpu) self.assertTrue(val.type == self.test_struct.pointer())
def test_ulong_ptr_test(self): var = gdb.lookup_symbol('ptr_to_ulong_test', None)[0] self.assertTrue(var is not None) for cpu, val in list(percpu.get_percpu_vars(var).items()): self.assertTrue(val.type == self.ulong_type.pointer()) self.assertTrue(val.dereference() == cpu)
def test_ulong_test(self): var = gdb.lookup_symbol('ulong_test', None)[0] self.assertTrue(var is not None) for cpu, val in list(percpu.get_percpu_vars(var).items()): self.assertTrue(val == cpu) self.assertTrue(val.type == self.ulong_type)