zephyr/scripts/coredump/gdbstubs/arch/risc_v.py

122 lines
3.1 KiB
Python

#!/usr/bin/env python3
#
# Copyright (c) 2021 Facebook, Inc. and its affiliates
#
# SPDX-License-Identifier: Apache-2.0
import binascii
import logging
import struct
from gdbstubs.gdbstub import GdbStub
logger = logging.getLogger("gdbstub")
class RegNum():
ZERO = 0
RA = 1
SP = 2
GP = 3
TP = 4
T0 = 5
T1 = 6
T2 = 7
FP = 8
S1 = 9
A0 = 10
A1 = 11
A2 = 12
A3 = 13
A4 = 14
A5 = 15
A6 = 16
A7 = 17
S2 = 18
S3 = 19
S4 = 20
S5 = 21
S6 = 22
S7 = 23
S8 = 24
S9 = 25
S10 = 26
S11 = 27
T3 = 28
T4 = 29
T5 = 30
T6 = 31
PC = 32
class GdbStub_RISC_V(GdbStub):
ARCH_DATA_BLK_STRUCT = "<IIIIIIIIIIIIIIIIII"
ARCH_DATA_BLK_STRUCT_2 = "<QQQQQQQQQQQQQQQQQQ"
GDB_SIGNAL_DEFAULT = 7
GDB_G_PKT_NUM_REGS = 33
def __init__(self, logfile, elffile):
super().__init__(logfile=logfile, elffile=elffile)
self.registers = None
self.gdb_signal = self.GDB_SIGNAL_DEFAULT
self.parse_arch_data_block()
def parse_arch_data_block(self):
arch_data_blk = self.logfile.get_arch_data()['data']
self.arch_data_ver = self.logfile.get_arch_data()['hdr_ver']
if self.arch_data_ver == 1:
tu = struct.unpack(self.ARCH_DATA_BLK_STRUCT, arch_data_blk)
elif self.arch_data_ver == 2:
tu = struct.unpack(self.ARCH_DATA_BLK_STRUCT_2, arch_data_blk)
self.registers = dict()
self.registers[RegNum.RA] = tu[0]
self.registers[RegNum.TP] = tu[1]
self.registers[RegNum.T0] = tu[2]
self.registers[RegNum.T1] = tu[3]
self.registers[RegNum.T2] = tu[4]
self.registers[RegNum.A0] = tu[5]
self.registers[RegNum.A1] = tu[6]
self.registers[RegNum.A2] = tu[7]
self.registers[RegNum.A3] = tu[8]
self.registers[RegNum.A4] = tu[9]
self.registers[RegNum.A5] = tu[10]
self.registers[RegNum.A6] = tu[11]
self.registers[RegNum.A7] = tu[12]
self.registers[RegNum.T3] = tu[13]
self.registers[RegNum.T4] = tu[14]
self.registers[RegNum.T5] = tu[15]
self.registers[RegNum.T6] = tu[16]
self.registers[RegNum.PC] = tu[17]
def handle_register_group_read_packet(self):
reg_fmt = "<I" if self.arch_data_ver == 1 else "<Q"
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])
pkt += binascii.hexlify(bval)
else:
# Register not in coredump -> unknown value
# Send in "xxxxxxxx"
length = 8 if self.arch_data_ver == 1 else 16
pkt += b'x' * length
idx += 1
self.put_gdb_packet(pkt)
def handle_register_single_read_packet(self, pkt):
# Mark registers as "<unavailable>". 'p' packets are not sent for the registers
# currently handled in this file so we can safely reply "xxxxxxxx" here.
length = 8 if self.arch_data_ver == 1 else 16
self.put_gdb_packet(b'x' * length)