gdbserver.py: add arm64 support

Use struct.unpack_from to eliminate the need to specify data size.

Signed-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
xuxingliang 2024-09-19 17:51:50 +08:00 committed by Xiang Xiao
parent 3bfeddcbdd
commit c5276f4244

View file

@ -117,6 +117,41 @@ reg_table = {
"PC": 15,
"CPSR": 41,
},
"arm64": {
"X0": 0,
"X1": 1,
"X2": 2,
"X3": 3,
"X4": 4,
"X5": 5,
"X6": 6,
"X7": 7,
"X8": 8,
"X9": 9,
"X10": 10,
"X11": 11,
"X12": 12,
"X13": 13,
"X14": 14,
"X15": 15,
"X16": 16,
"X17": 17,
"X18": 18,
"X19": 19,
"X20": 20,
"X21": 21,
"X22": 22,
"X23": 23,
"X24": 24,
"X25": 25,
"X26": 26,
"X27": 27,
"X28": 28,
"X29": 29,
"X30": 30,
"SP_ELX": 31,
"ELR": 32,
},
# rv64 works with gdb-multiarch on Ubuntu
"riscv": {
"ZERO": 0,
@ -375,9 +410,10 @@ class DumpLogFile:
line = line.strip()
# find register value
find_res = re.findall(r"(?P<REG>\w+): (?P<REGV>[0-9a-fA-F]+)", line)
find_res = re.findall(r"(?P<REG>\w+):\s*(?P<REGV>[0-9a-fxA-FX]+)", line)
for reg_name, reg_val in find_res:
reg_name = reg_name.upper()
if reg_name in self.reg_table:
reg_index = self.reg_table[reg_name]
self.registers[reg_index] = int(reg_val, 16)
@ -526,6 +562,7 @@ class GDBStub:
self.gdb_signal = GDB_SIGNAL_DEFAULT
self.arch = arch
self.reg_fmt = "<I" if elffile.xlen() <= 32 else "<Q"
self.int_size = elffile.xlen() // 8
self.reg_digits = elffile.xlen() // 4
# new list oreder is coredump, rawfile, logfile, elffile
@ -556,11 +593,11 @@ class GDBStub:
self.regfix = True
logger.info(f"Current arch is {arch}, need reg index fix.")
except TypeError:
except TypeError as e:
if not self.registers:
logger.critical(
"Logfile, coredump, or rawfile do not contain register,"
"Please check if the files are correct."
f"Please check if the files are correct. {e}"
)
stack_trace = traceback.format_exc()
@ -784,11 +821,11 @@ class GDBStub:
self.put_gdb_packet(b"OK")
def parse_thread(self):
def unpack_data(addr, size, fmt):
def unpack_data(addr, fmt):
r = self.get_mem_region(addr)
offset = addr - r["start"]
data = r["data"][offset : offset + size]
return struct.unpack(fmt, data)
data = r["data"]
return struct.unpack_from(fmt, data, offset)
TCBINFO_FMT = "<8HQ"
@ -808,7 +845,6 @@ class GDBStub:
unpacked_data = unpack_data(
self.elffile.symbol["g_tcbinfo"]["st_value"],
self.elffile.symbol["g_tcbinfo"]["st_size"],
TCBINFO_FMT,
)
tcbinfo = {
@ -825,7 +861,6 @@ class GDBStub:
unpacked_data = unpack_data(
self.elffile.symbol["g_npidhash"]["st_value"],
self.elffile.symbol["g_npidhash"]["st_size"],
"<I",
)
npidhash = int(unpacked_data[0])
@ -833,32 +868,35 @@ class GDBStub:
unpacked_data = unpack_data(
self.elffile.symbol["g_pidhash"]["st_value"],
self.elffile.symbol["g_pidhash"]["st_size"],
"<I",
self.reg_fmt,
)
pidhash = int(unpacked_data[0])
logger.debug(f"g_pidhash is {hex(pidhash)}")
tcbptr_list = []
for i in range(0, npidhash):
unpacked_data = unpack_data(pidhash + i * 4, 4, "<I")
unpacked_data = unpack_data(pidhash + i * self.int_size, self.reg_fmt)
tcbptr_list.append(int(unpacked_data[0]))
def parse_tcb(tcbptr):
tcb = {}
tcb["pid"] = int(unpack_data(tcbptr + tcbinfo["pid_off"], 4, "<I")[0])
tcb["state"] = int(unpack_data(tcbptr + tcbinfo["state_off"], 1, "<B")[0])
tcb["pri"] = int(unpack_data(tcbptr + tcbinfo["pri_off"], 1, "<B")[0])
tcb["stack"] = int(unpack_data(tcbptr + tcbinfo["stack_off"], 4, "<I")[0])
tcb["stack_size"] = int(
unpack_data(tcbptr + tcbinfo["stack_size_off"], 4, "<I")[0]
tcb["pid"] = int(unpack_data(tcbptr + tcbinfo["pid_off"], "<I")[0])
tcb["state"] = int(unpack_data(tcbptr + tcbinfo["state_off"], "<B")[0])
tcb["pri"] = int(unpack_data(tcbptr + tcbinfo["pri_off"], "<B")[0])
tcb["stack"] = int(
unpack_data(tcbptr + tcbinfo["stack_off"], self.reg_fmt)[0]
)
tcb["stack_size"] = int(
unpack_data(tcbptr + tcbinfo["stack_size_off"], self.reg_fmt)[0]
)
tcb["regs"] = int(
unpack_data(tcbptr + tcbinfo["regs_off"], self.reg_fmt)[0]
)
tcb["regs"] = int(unpack_data(tcbptr + tcbinfo["regs_off"], 4, "<I")[0])
tcb["tcbptr"] = tcbptr
i = 0
tcb["name"] = ""
while True:
c = int(unpack_data(tcbptr + tcbinfo["name_off"] + i, 1, "<B")[0])
c = int(unpack_data(tcbptr + tcbinfo["name_off"] + i, "<B")[0])
if c == 0:
break
i += 1
@ -869,18 +907,17 @@ class GDBStub:
def parse_regs_to_gdb(regs):
gdb_regs = []
for i in range(0, tcbinfo["regs_num"]):
reg_off = int(unpack_data(tcbinfo["reg_off"] + i * 2, 2, "<H")[0])
reg_off = int(unpack_data(tcbinfo["reg_off"] + i * 2, "<H")[0])
if reg_off == UINT16_MAX:
gdb_regs.append(b"x")
else:
gdb_regs.append(int(unpack_data(regs + reg_off, 4, "<I")[0]))
gdb_regs.append(int(unpack_data(regs + reg_off, self.reg_fmt)[0]))
return gdb_regs
self.cpunum = self.elffile.symbol["g_running_tasks"]["st_size"] // 4
logger.debug(f"Have {self.cpunum} cpu")
unpacked_data = unpack_data(
self.elffile.symbol["g_running_tasks"]["st_value"],
self.elffile.symbol["g_running_tasks"]["st_size"],
f"<{self.cpunum}I",
)