122 lines
3.1 KiB
Python
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)
|