forked from platformio/platformio-core
Fix issue with GDB/MI Stream Records for PIO Debugger
This commit is contained in:
@ -30,7 +30,7 @@ from platformio import app, exception, fs, proc, util
|
||||
from platformio.commands.debug import helpers, initcfgs
|
||||
from platformio.commands.debug.process import BaseProcess
|
||||
from platformio.commands.debug.server import DebugServer
|
||||
from platformio.compat import hashlib_encode_data
|
||||
from platformio.compat import hashlib_encode_data, is_bytes
|
||||
from platformio.project.helpers import get_project_cache_dir
|
||||
from platformio.telemetry import MeasurementProtocol
|
||||
|
||||
@ -223,10 +223,9 @@ class GDBClient(BaseProcess): # pylint: disable=too-many-instance-attributes
|
||||
self._handle_error(data)
|
||||
|
||||
def console_log(self, msg):
|
||||
if helpers.is_mi_mode(self.args):
|
||||
self.outReceived(('~"%s\\n"\n' % msg).encode())
|
||||
else:
|
||||
self.outReceived(("%s\n" % msg).encode())
|
||||
if helpers.is_gdbmi_mode():
|
||||
msg = helpers.escape_gdbmi_stream("~", msg)
|
||||
self.outReceived(msg if is_bytes(msg) else msg.encode())
|
||||
|
||||
def _auto_exec_continue(self):
|
||||
auto_exec_delay = 0.5 # in seconds
|
||||
@ -239,14 +238,14 @@ class GDBClient(BaseProcess): # pylint: disable=too-many-instance-attributes
|
||||
if not self.debug_options["init_break"] or self._target_is_run:
|
||||
return
|
||||
self.console_log(
|
||||
"PlatformIO: Resume the execution to `debug_init_break = %s`"
|
||||
"PlatformIO: Resume the execution to `debug_init_break = %s`\n"
|
||||
% self.debug_options["init_break"]
|
||||
)
|
||||
self.console_log(
|
||||
"PlatformIO: More configuration options -> http://bit.ly/pio-debug"
|
||||
"PlatformIO: More configuration options -> http://bit.ly/pio-debug\n"
|
||||
)
|
||||
self.transport.write(
|
||||
b"0-exec-continue\n" if helpers.is_mi_mode(self.args) else b"continue\n"
|
||||
b"0-exec-continue\n" if helpers.is_gdbmi_mode() else b"continue\n"
|
||||
)
|
||||
self._target_is_run = True
|
||||
|
||||
|
@ -90,10 +90,12 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface, __unpro
|
||||
try:
|
||||
fs.ensure_udev_rules()
|
||||
except exception.InvalidUdevRules as e:
|
||||
for line in str(e).split("\n") + [""]:
|
||||
click.echo(
|
||||
('~"%s\\n"' if helpers.is_mi_mode(__unprocessed) else "%s") % line
|
||||
)
|
||||
click.echo(
|
||||
helpers.escape_gdbmi_stream("~", str(e) + "\n")
|
||||
if helpers.is_gdbmi_mode()
|
||||
else str(e) + "\n",
|
||||
nl=False,
|
||||
)
|
||||
|
||||
debug_options["load_cmds"] = helpers.configure_esp32_load_cmds(
|
||||
debug_options, configuration
|
||||
@ -118,12 +120,17 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface, __unpro
|
||||
debug_options["load_cmds"] = []
|
||||
|
||||
if rebuild_prog:
|
||||
if helpers.is_mi_mode(__unprocessed):
|
||||
click.echo('~"Preparing firmware for debugging...\\n"')
|
||||
output = helpers.GDBBytesIO()
|
||||
with util.capture_std_streams(output):
|
||||
if helpers.is_gdbmi_mode():
|
||||
click.echo(
|
||||
helpers.escape_gdbmi_stream(
|
||||
"~", "Preparing firmware for debugging...\n"
|
||||
),
|
||||
nl=False,
|
||||
)
|
||||
stream = helpers.GDBMIConsoleStream()
|
||||
with util.capture_std_streams(stream):
|
||||
helpers.predebug_project(ctx, project_dir, env_name, preload, verbose)
|
||||
output.close()
|
||||
stream.close()
|
||||
else:
|
||||
click.echo("Preparing firmware for debugging...")
|
||||
helpers.predebug_project(ctx, project_dir, env_name, preload, verbose)
|
||||
|
@ -21,32 +21,46 @@ from io import BytesIO
|
||||
from os.path import isfile
|
||||
|
||||
from platformio import exception, fs, util
|
||||
from platformio.commands import PlatformioCLI
|
||||
from platformio.commands.platform import platform_install as cmd_platform_install
|
||||
from platformio.commands.run.command import cli as cmd_run
|
||||
from platformio.compat import is_bytes
|
||||
from platformio.managers.platform import PlatformFactory
|
||||
from platformio.project.config import ProjectConfig
|
||||
from platformio.project.options import ProjectOptions
|
||||
|
||||
|
||||
class GDBBytesIO(BytesIO): # pylint: disable=too-few-public-methods
|
||||
class GDBMIConsoleStream(BytesIO): # pylint: disable=too-few-public-methods
|
||||
|
||||
STDOUT = sys.stdout
|
||||
|
||||
@staticmethod
|
||||
def escape(text):
|
||||
return re.sub(r"\\+", "\\\\\\\\", text)
|
||||
|
||||
def write(self, text):
|
||||
if "\n" in text:
|
||||
for line in text.strip().split("\n"):
|
||||
self.STDOUT.write('~"%s\\n"\n' % self.escape(line))
|
||||
else:
|
||||
self.STDOUT.write('~"%s"' % self.escape(text))
|
||||
self.STDOUT.write(escape_gdbmi_stream("~", text))
|
||||
self.STDOUT.flush()
|
||||
|
||||
|
||||
def is_mi_mode(args):
|
||||
return "--interpreter" in " ".join(args)
|
||||
def is_gdbmi_mode():
|
||||
return "--interpreter" in " ".join(PlatformioCLI.leftover_args)
|
||||
|
||||
|
||||
def escape_gdbmi_stream(prefix, stream):
|
||||
bytes_stream = False
|
||||
if is_bytes(stream):
|
||||
bytes_stream = True
|
||||
stream = stream.decode()
|
||||
|
||||
if not stream:
|
||||
return b"" if bytes_stream else ""
|
||||
|
||||
ends_nl = stream.endswith("\n")
|
||||
stream = re.sub(r"\\+", "\\\\\\\\", stream)
|
||||
stream = stream.replace('"', '\\"')
|
||||
stream = stream.replace("\n", "\\n")
|
||||
stream = '%s"%s"' % (prefix, stream)
|
||||
if ends_nl:
|
||||
stream += "\n"
|
||||
|
||||
return stream.encode() if bytes_stream else stream
|
||||
|
||||
|
||||
def get_default_debug_env(config):
|
||||
|
@ -19,6 +19,7 @@ from twisted.internet import error # pylint: disable=import-error
|
||||
from twisted.internet import reactor # pylint: disable=import-error
|
||||
|
||||
from platformio import exception, fs, util
|
||||
from platformio.commands.debug.helpers import escape_gdbmi_stream, is_gdbmi_mode
|
||||
from platformio.commands.debug.process import BaseProcess
|
||||
from platformio.proc import where_is_program
|
||||
|
||||
@ -119,6 +120,11 @@ class DebugServer(BaseProcess):
|
||||
def get_debug_port(self):
|
||||
return self._debug_port
|
||||
|
||||
def outReceived(self, data):
|
||||
super(DebugServer, self).outReceived(
|
||||
escape_gdbmi_stream("@", data) if is_gdbmi_mode() else data
|
||||
)
|
||||
|
||||
def processEnded(self, reason):
|
||||
self._process_ended = True
|
||||
super(DebugServer, self).processEnded(reason)
|
||||
|
Reference in New Issue
Block a user