# 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 # 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()