@ -8,6 +8,7 @@ import binascii
@@ -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):
@@ -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 = " <I "
idx = 0
pkt = b ' '
while idx < self . GDB_G_PKT_NUM_REGS :
if idx in self . registers :
bval = struct . pack ( reg_fmt , self . registers [ idx ] )
if idx in registers :
bval = struct . pack ( reg_fmt , registers [ idx ] )
pkt + = binascii . hexlify ( bval )
else :
# Register not in coredump -> unknown value
@ -99,6 +100,12 @@ class GdbStub_ARM_CortexM(GdbStub):
@@ -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 "<unavailable>".
# 'p' packets are usually used for registers
@ -111,3 +118,57 @@ class GdbStub_ARM_CortexM(GdbStub):
@@ -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 ( " <IIIIIIII " , barray )
thread_registers [ RegNum . R0 ] = tu [ 0 ]
thread_registers [ RegNum . R1 ] = tu [ 1 ]
thread_registers [ RegNum . R2 ] = tu [ 2 ]
thread_registers [ RegNum . R3 ] = tu [ 3 ]
thread_registers [ RegNum . R12 ] = tu [ 4 ]
thread_registers [ RegNum . LR ] = tu [ 5 ]
thread_registers [ RegNum . PC ] = tu [ 6 ]
thread_registers [ RegNum . XPSR ] = tu [ 7 ]
# Set SP to point to stack just after these registers
thread_registers [ RegNum . SP ] = stack_ptr + 32
# Read the exc_return value from the thread's arch struct
t_arch_offset = self . elffile . get_kernel_thread_info_offset ( ThreadInfoOffset . THREAD_INFO_OFFSET_T_ARCH )
t_exc_return_offset = self . elffile . get_kernel_thread_info_offset ( ThreadInfoOffset . THREAD_INFO_OFFSET_T_ARM_EXC_RETURN )
# Value of 0xffffffff indicates THREAD_INFO_UNIMPLEMENTED
if t_exc_return_offset != 0xffffffff :
exc_return_bytes = self . get_memory ( thread_ptr + t_arch_offset + t_exc_return_offset , 1 )
exc_return = int . from_bytes ( exc_return_bytes , " little " )
# If the bit 4 is not set, the stack frame is extended for floating point data, adjust the SP accordingly
if ( exc_return & ( 1 << 4 ) ) == 0 :
thread_registers [ RegNum . SP ] = thread_registers [ RegNum . SP ] + 72
# Set R7 to match the stack pointer in case the frame pointer is not omitted
thread_registers [ RegNum . R7 ] = thread_registers [ RegNum . SP ]
self . send_registers_packet ( thread_registers )