+ """A single gdb class which can interact with one or more gdb instances."""
+
+ # pylint: disable=too-many-public-methods
+ # pylint: disable=too-many-instance-attributes
+
+ def __init__(self, ports,
+ cmd=os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gdb"),
+ timeout=60, binary=None):
+ assert ports
+
+ self.ports = ports
+ self.cmd = cmd
+ self.timeout = timeout
+ self.binary = binary
+
+ self.stack = []
+ self.harts = {}
+
+ self.logfiles = []
+ self.children = []
+ for port in ports:
+ logfile = tempfile.NamedTemporaryFile(prefix="gdb@%d-" % port,
+ suffix=".log")
+ self.logfiles.append(logfile)
+ if print_log_names:
+ real_stdout.write("Temporary gdb log: %s\n" % logfile.name)
+ child = pexpect.spawn(cmd)
+ child.logfile = logfile
+ child.logfile.write("+ %s\n" % cmd)
+ self.children.append(child)
+ self.active_child = self.children[0]
+
+ def connect(self):
+ for port, child in zip(self.ports, self.children):
+ self.select_child(child)
+ self.wait()
+ self.command("set confirm off")
+ self.command("set width 0")
+ self.command("set height 0")
+ # Force consistency.
+ self.command("set print entry-values no")
+ self.command("set remotetimeout %d" % self.timeout)
+ self.command("target extended-remote localhost:%d" % port)
+ if self.binary:
+ self.command("file %s" % self.binary)
+ threads = self.threads()
+ for t in threads:
+ hartid = None
+ if t.name:
+ m = re.search(r"Hart (\d+)", t.name)
+ if m:
+ hartid = int(m.group(1))
+ if hartid is None:
+ if self.harts:
+ hartid = max(self.harts) + 1
+ else:
+ hartid = 0
+ # solo: True iff this is the only thread on this child
+ self.harts[hartid] = {'child': child,
+ 'thread': t,
+ 'solo': len(threads) == 1}