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