1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
# SPDX-License-Identifier: GPL-2.0-or-later
#
# A simple interface module built around pygdbmi for handling GDB commands.
#
# Copyright (c) 2025 Linaro Limited
#
# Author:
# Gustavo Romero <gustavo.romero@linaro.org>
#
import re
class GDB:
"""Provides methods to run and capture GDB command output."""
def __init__(self, gdb_path, echo=True, suffix='# ', prompt="$ "):
from pygdbmi.gdbcontroller import GdbController
from pygdbmi.constants import GdbTimeoutError
type(self).TimeoutError = GdbTimeoutError
gdb_cmd = [gdb_path, "-q", "--interpreter=mi2"]
self.gdbmi = GdbController(gdb_cmd)
self.echo = echo
self.suffix = suffix
self.prompt = prompt
self.response = None
self.cmd_output = None
def get_payload(self, response, kind):
output = []
for o in response:
# Unpack payloads of the same type.
_type, _, payload, *_ = o.values()
if _type == kind:
output += [payload]
# Some output lines do not end with \n but begin with it,
# so remove the leading \n and merge them with the next line
# that ends with \n.
lines = [line.lstrip('\n') for line in output]
lines = "".join(lines)
lines = lines.splitlines(keepends=True)
return lines
def cli(self, cmd, timeout=32.0):
self.response = self.gdbmi.write(cmd, timeout_sec=timeout)
self.cmd_output = self.get_payload(self.response, kind="console")
if self.echo:
print(self.suffix + self.prompt + cmd)
if len(self.cmd_output) > 0:
cmd_output = self.suffix.join(self.cmd_output)
print(self.suffix + cmd_output, end="")
return self
def get_addr(self):
address_pattern = r"0x[0-9A-Fa-f]+"
cmd_output = "".join(self.cmd_output) # Concat output lines.
match = re.search(address_pattern, cmd_output)
return int(match[0], 16) if match else None
def get_log(self):
r = self.get_payload(self.response, kind="log")
r = "".join(r)
return r
def get_console(self):
r = "".join(self.cmd_output)
return r
def exit(self):
self.gdbmi.exit()
|