def run_gdb(self): # type: () -> None with self: # disable console control normal_print('') try: cmd = [ '%sgdb' % self.toolchain_prefix, '-ex', 'set serial baud %d' % self.serial.baudrate, '-ex', 'target remote %s' % self.serial.port, '-ex', 'interrupt', # monitor has already parsed the first 'reason' command, need a second self.elf_file ] process = subprocess.Popen(cmd, cwd='.') process.wait() except OSError as e: red_print('%s: %s' % (' '.join(cmd), e)) except KeyboardInterrupt: pass # happens on Windows, maybe other OSes finally: try: # on Linux, maybe other OSes, gdb sometimes seems to be alive even after wait() returns... process.terminate() except Exception: pass try: # also on Linux, maybe other OSes, gdb sometimes exits uncleanly and breaks the tty mode subprocess.call(['stty', 'sane']) except Exception: pass # don't care if there's no stty, we tried... self.prompt_next_action('gdb exited')
def check_gdbstub_trigger(self, line): # type: (bytes) -> None line = self._gdb_buffer + line self._gdb_buffer = b'' m = re.search(b'\\$(T..)#(..)', line) # look for a gdb "reason" for a break if m is not None: try: chsum = sum(ord(bytes([p])) for p in m.group(1)) & 0xFF calc_chsum = int(m.group(2), 16) except ValueError: return # payload wasn't valid hex digits if chsum == calc_chsum: if self.websocket_client: yellow_print('Communicating through WebSocket') self.websocket_client.send({ 'event': 'gdb_stub', 'port': self.serial.port, 'prog': self.elf_file }) yellow_print('Waiting for debug finished event') self.websocket_client.wait([('event', 'debug_finished')]) yellow_print( 'Communications through WebSocket is finished') else: self.run_gdb() else: red_print( 'Malformed gdb message... calculated checksum %02x received %02x' % (chsum, calc_chsum))
def start_logging(self): # type: () -> None if not self._log_file: name = 'log.{}.{}.txt'.format( os.path.splitext(os.path.basename(self.elf_file))[0], datetime.datetime.now().strftime('%Y%m%d%H%M%S')) try: self._log_file = open(name, 'wb+') yellow_print('\nLogging is enabled into file {}'.format(name)) except Exception as e: red_print('\nLog file {} cannot be created: {}'.format( name, e))
def lookup_pc_address(self, pc_addr): # type: (str) -> None cmd = [ '%saddr2line' % self.toolchain_prefix, '-pfiaC', '-e', self.elf_file, pc_addr ] try: translation = subprocess.check_output(cmd, cwd='.') if b'?? ??:0' not in translation: self._print(translation.decode(), console_printer=yellow_print) except OSError as e: red_print('%s: %s' % (' '.join(cmd), e))
def stop_logging(self): # type: () -> None if self._log_file: try: name = self._log_file.name self._log_file.close() yellow_print( '\nLogging is disabled and file {} has been closed'.format( name)) except Exception as e: red_print('\nLog file cannot be closed: {}'.format(e)) finally: self._log_file = None
def _print(self, string, console_printer=None ): # type: (Union[str, bytes], Optional[Callable]) -> None if console_printer is None: console_printer = self.console.write_bytes if self._output_enabled: console_printer(string) if self._log_file: try: if isinstance(string, type(u'')): string = string.encode() self._log_file.write(string) # type: ignore except Exception as e: red_print('\nCannot write to file: {}'.format(e)) # don't fill-up the screen with the previous errors (probably consequent prints would fail also) self.stop_logging()
def prompt_next_action(self, reason): # type: (str) -> None self.console.setup() # set up console to trap input characters try: red_print('--- {}'.format(reason)) red_print(self.console_parser.get_next_action_text()) k = CTRL_T # ignore CTRL-T here, so people can muscle-memory Ctrl-T Ctrl-F, etc. while k == CTRL_T: k = self.console.getkey() finally: self.console.cleanup() ret = self.console_parser.parse_next_action_key(k) if ret is not None: cmd = ret[1] if cmd == CMD_STOP: # the stop command should be handled last self.event_queue.put(ret) else: self.cmd_queue.put(ret)
def run_gdb(self): # type: () -> None with self: # disable console control normal_print('') try: cmd = [ '%sgdb' % self.toolchain_prefix, '-ex', 'set serial baud %d' % self.serial.baudrate, '-ex', 'target remote %s' % self.serial.port, self.elf_file ] # Here we handling GDB as a process # Open GDB process try: process = subprocess.Popen(cmd, cwd='.') except KeyboardInterrupt: pass # We ignore Ctrl+C interrupt form external process abd wait responce util GDB will be finished. while True: try: process.wait() break except KeyboardInterrupt: pass # We ignore the Ctrl+C self.gdb_exit = True except OSError as e: red_print('%s: %s' % (' '.join(cmd), e)) except KeyboardInterrupt: pass # happens on Windows, maybe other OSes finally: try: # on Linux, maybe other OSes, gdb sometimes seems to be alive even after wait() returns... process.terminate() except Exception: pass try: # also on Linux, maybe other OSes, gdb sometimes exits uncleanly and breaks the tty mode subprocess.call(['stty', 'sane']) except Exception: pass # don't care if there's no stty, we tried...