mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-31 10:37:13 +02:00
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 import helpers, initcfgs
|
||||||
from platformio.commands.debug.process import BaseProcess
|
from platformio.commands.debug.process import BaseProcess
|
||||||
from platformio.commands.debug.server import DebugServer
|
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.project.helpers import get_project_cache_dir
|
||||||
from platformio.telemetry import MeasurementProtocol
|
from platformio.telemetry import MeasurementProtocol
|
||||||
|
|
||||||
@ -223,10 +223,9 @@ class GDBClient(BaseProcess): # pylint: disable=too-many-instance-attributes
|
|||||||
self._handle_error(data)
|
self._handle_error(data)
|
||||||
|
|
||||||
def console_log(self, msg):
|
def console_log(self, msg):
|
||||||
if helpers.is_mi_mode(self.args):
|
if helpers.is_gdbmi_mode():
|
||||||
self.outReceived(('~"%s\\n"\n' % msg).encode())
|
msg = helpers.escape_gdbmi_stream("~", msg)
|
||||||
else:
|
self.outReceived(msg if is_bytes(msg) else msg.encode())
|
||||||
self.outReceived(("%s\n" % msg).encode())
|
|
||||||
|
|
||||||
def _auto_exec_continue(self):
|
def _auto_exec_continue(self):
|
||||||
auto_exec_delay = 0.5 # in seconds
|
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:
|
if not self.debug_options["init_break"] or self._target_is_run:
|
||||||
return
|
return
|
||||||
self.console_log(
|
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.debug_options["init_break"]
|
||||||
)
|
)
|
||||||
self.console_log(
|
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(
|
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
|
self._target_is_run = True
|
||||||
|
|
||||||
|
@ -90,10 +90,12 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface, __unpro
|
|||||||
try:
|
try:
|
||||||
fs.ensure_udev_rules()
|
fs.ensure_udev_rules()
|
||||||
except exception.InvalidUdevRules as e:
|
except exception.InvalidUdevRules as e:
|
||||||
for line in str(e).split("\n") + [""]:
|
click.echo(
|
||||||
click.echo(
|
helpers.escape_gdbmi_stream("~", str(e) + "\n")
|
||||||
('~"%s\\n"' if helpers.is_mi_mode(__unprocessed) else "%s") % line
|
if helpers.is_gdbmi_mode()
|
||||||
)
|
else str(e) + "\n",
|
||||||
|
nl=False,
|
||||||
|
)
|
||||||
|
|
||||||
debug_options["load_cmds"] = helpers.configure_esp32_load_cmds(
|
debug_options["load_cmds"] = helpers.configure_esp32_load_cmds(
|
||||||
debug_options, configuration
|
debug_options, configuration
|
||||||
@ -118,12 +120,17 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface, __unpro
|
|||||||
debug_options["load_cmds"] = []
|
debug_options["load_cmds"] = []
|
||||||
|
|
||||||
if rebuild_prog:
|
if rebuild_prog:
|
||||||
if helpers.is_mi_mode(__unprocessed):
|
if helpers.is_gdbmi_mode():
|
||||||
click.echo('~"Preparing firmware for debugging...\\n"')
|
click.echo(
|
||||||
output = helpers.GDBBytesIO()
|
helpers.escape_gdbmi_stream(
|
||||||
with util.capture_std_streams(output):
|
"~", "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)
|
helpers.predebug_project(ctx, project_dir, env_name, preload, verbose)
|
||||||
output.close()
|
stream.close()
|
||||||
else:
|
else:
|
||||||
click.echo("Preparing firmware for debugging...")
|
click.echo("Preparing firmware for debugging...")
|
||||||
helpers.predebug_project(ctx, project_dir, env_name, preload, verbose)
|
helpers.predebug_project(ctx, project_dir, env_name, preload, verbose)
|
||||||
|
@ -21,32 +21,46 @@ from io import BytesIO
|
|||||||
from os.path import isfile
|
from os.path import isfile
|
||||||
|
|
||||||
from platformio import exception, fs, util
|
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.platform import platform_install as cmd_platform_install
|
||||||
from platformio.commands.run.command import cli as cmd_run
|
from platformio.commands.run.command import cli as cmd_run
|
||||||
|
from platformio.compat import is_bytes
|
||||||
from platformio.managers.platform import PlatformFactory
|
from platformio.managers.platform import PlatformFactory
|
||||||
from platformio.project.config import ProjectConfig
|
from platformio.project.config import ProjectConfig
|
||||||
from platformio.project.options import ProjectOptions
|
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
|
STDOUT = sys.stdout
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def escape(text):
|
|
||||||
return re.sub(r"\\+", "\\\\\\\\", text)
|
|
||||||
|
|
||||||
def write(self, text):
|
def write(self, text):
|
||||||
if "\n" in text:
|
self.STDOUT.write(escape_gdbmi_stream("~", 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.flush()
|
self.STDOUT.flush()
|
||||||
|
|
||||||
|
|
||||||
def is_mi_mode(args):
|
def is_gdbmi_mode():
|
||||||
return "--interpreter" in " ".join(args)
|
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):
|
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 twisted.internet import reactor # pylint: disable=import-error
|
||||||
|
|
||||||
from platformio import exception, fs, util
|
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.commands.debug.process import BaseProcess
|
||||||
from platformio.proc import where_is_program
|
from platformio.proc import where_is_program
|
||||||
|
|
||||||
@ -119,6 +120,11 @@ class DebugServer(BaseProcess):
|
|||||||
def get_debug_port(self):
|
def get_debug_port(self):
|
||||||
return self._debug_port
|
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):
|
def processEnded(self, reason):
|
||||||
self._process_ended = True
|
self._process_ended = True
|
||||||
super(DebugServer, self).processEnded(reason)
|
super(DebugServer, self).processEnded(reason)
|
||||||
|
Reference in New Issue
Block a user