From a56e2f86cc975f48f99586aef6cea8987eb596fa Mon Sep 17 00:00:00 2001 From: Mark Holden Date: Mon, 24 Jun 2024 13:24:07 -0700 Subject: [PATCH] coredump: Enable thread understanding for arm cortex m Add support in arm_cortex_m python script to read thread registers off of a thread's stack when switching context. When CONFIG_ARM_STORE_EXC_RETURN is enabled, check the exc_return value in thread's arch struct to determine accurately where the stack pointer is. Also, set r7 (the frame pointer register) in case the frame pointer is not omitted. Only 8 registers are read from the top of the stack for other threads present in the dump. So update the script to reflect that. Signed-off-by: Mark Holden --- .../coredump/gdbstubs/arch/arm_cortex_m.py | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/scripts/coredump/gdbstubs/arch/arm_cortex_m.py b/scripts/coredump/gdbstubs/arch/arm_cortex_m.py index 5aa47825435..02cdac598ff 100644 --- a/scripts/coredump/gdbstubs/arch/arm_cortex_m.py +++ b/scripts/coredump/gdbstubs/arch/arm_cortex_m.py @@ -8,6 +8,7 @@ import binascii import logging import struct +from coredump_parser.elf_parser import ThreadInfoOffset from gdbstubs.gdbstub import GdbStub @@ -80,15 +81,15 @@ class GdbStub_ARM_CortexM(GdbStub): self.registers[RegNum.R10] = tu[15] self.registers[RegNum.R11] = tu[16] - def handle_register_group_read_packet(self): + def send_registers_packet(self, registers): reg_fmt = " unknown value @@ -99,6 +100,12 @@ class GdbStub_ARM_CortexM(GdbStub): self.put_gdb_packet(pkt) + def handle_register_group_read_packet(self): + if not self.elffile.has_kernel_thread_info(): + self.send_registers_packet(self.registers) + else: + self.handle_thread_register_group_read_packet() + def handle_register_single_read_packet(self, pkt): # Mark registers as "". # 'p' packets are usually used for registers @@ -111,3 +118,57 @@ class GdbStub_ARM_CortexM(GdbStub): reg = int(pkt_str[1:pkt_str.index('=')], 16) self.registers[reg] = int.from_bytes(binascii.unhexlify(pkt[3:]), byteorder = 'little') self.put_gdb_packet(b'+') + + def arch_supports_thread_operations(self): + return True + + def handle_thread_register_group_read_packet(self): + # For selected_thread 0, use the register data retrieved from the dump's arch section + if self.selected_thread == 0: + self.send_registers_packet(self.registers) + else: + thread_ptr = self.thread_ptrs[self.selected_thread] + + # Get stack pointer out of thread struct + t_stack_ptr_offset = self.elffile.get_kernel_thread_info_offset(ThreadInfoOffset.THREAD_INFO_OFFSET_T_STACK_PTR) + size_t_size = self.elffile.get_kernel_thread_info_size_t_size() + stack_ptr_bytes = self.get_memory(thread_ptr + t_stack_ptr_offset, size_t_size) + + thread_registers = dict() + + if stack_ptr_bytes is not None: + # Read registers stored at top of stack + stack_ptr = int.from_bytes(stack_ptr_bytes, "little") + barray = self.get_memory(stack_ptr, (size_t_size * 8)) + + if barray is not None: + tu = struct.unpack("