Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement debug command #94

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions tockloader/board_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,3 +594,9 @@ def _align_and_stretch_to_page(self, address, binary):
binary = binary + after_binary

return (address, binary)

def debug_binary(self, binary):
"""
Debug the binary on the board.
"""
return
3 changes: 3 additions & 0 deletions tockloader/jlinkexe.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,6 @@ def run_terminal(self):
l = stdout_line.decode("utf-8")
if not l.startswith("###RTT Client: *"):
print(l, end="")

def debug(self, binary):
raise TockLoaderException("This functionality is not implemented for JLink")
24 changes: 24 additions & 0 deletions tockloader/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,20 @@ def command_flash(args):
logging.status("Flashing binar{} to board...".format(plural))
tock_loader.flash_binary(binary, args.address, pad=pad)

def command_debug(args):
# Check if binary exists
if not os.path.exists(args.binary):
raise TockLoaderException("{} does not exist".format(args.binary))

# For now, we do not compile or flash binary on the board

# Debug the binary to the chip
tock_loader = TockLoader(args)
tock_loader.open()

logging.status("Debug binary {} to board...".format(args.binary))
tock_loader.debug_binary(args.binary)


def command_read(args):
"""
Expand Down Expand Up @@ -1056,6 +1070,16 @@ def main():
)
list_known_boards.set_defaults(func=command_list_known_boards)

debug_binary = subparser.add_parser(
"debug-binary",
parents=[parent, parent_channel],
help="Debug the binary installed on the board",
)
debug_binary.set_defaults(func=command_debug)
debug_binary.add_argument(
"--binary", help="The binary file to debug on the board"
)

argcomplete.autocomplete(parser)
args, unknown_args = parser.parse_known_args()

Expand Down
107 changes: 107 additions & 0 deletions tockloader/openocd.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import subprocess
import tempfile
import time
import os
import signal
import shutil

from .board_interface import BoardInterface
from .exceptions import TockLoaderException
Expand Down Expand Up @@ -450,3 +453,107 @@ def run_terminal(self):
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)

def _run_gdb_server(self):
self.open_link_to_board()
logging.status("Starting OpenOCD debug server.")
openocd_command, _ = self._gather_openocd_cmdline(
[],
None,
exit=False,
)

logging.debug('Running "{}".'.format(openocd_command.replace("$", "\$")))

cflags = 0
preexec = None
system = platform.system()

# Create new process preventing to catch Ctrl+C
if system == 'Windows':
cflags |= subprocess.CREATE_NEW_PROCESS_GROUP
elif system in {'Linux', 'Darwin'}:
preexec = os.setsid

# This won't print messages from OpenOCD,
# to avoid interfering with the console.
ocd_p = subprocess.Popen(
shlex.split(openocd_command),
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
preexec_fn=preexec,
creationflags=cflags,
)

return ocd_p

def _find_gdb_binary(self):
gdb_multi_arch = shutil.wihch('gdb-multiarch')

if gdb_multi_arch is not None:
return gdb_multi_arch
elif self.arch.startswith('cortex'):
return shutil.wich('arm-none-eabi-gdb')

return None

def _run_gdb_client(self, binary):
gdb_binary = self._find_gdb_binary()
if gdb_binary is None:
raise TockLoaderException("No binary found to debug target")

gdb_command = f'{gdb_binary} --exec {binary} --symbols {binary} -eval-command="target remote localhost:3333"'

logging.debug('Running "{}".'.format(gdb_command))

# Ignore SIGINT. gdb must be exited properly by user
previous = signal.signal(signal.SIGINT, signal.SIG_IGN)

gdb_p = subprocess.Popen(
shlex.split(gdb_command),
)

gdb_p.wait()

signal.signal(signal.SIGINT, previous)

return gdb_p

def _reset_board(self):
openocd_command, _ = self._gather_openocd_cmdline(
[
"reset halt",
],
None,
)
subprocess.run(
shlex.split(openocd_command),
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)

def debug(self, binary):
cleanup = []
try:
ocd_p = self._run_gdb_server()

cleanup.append(ocd_p.wait)
cleanup.append(ocd_p.kill)

time.sleep(1)
if ocd_p.poll():
logging.error('Openocd server not running')
raise

gdb_p = self._run_gdb_client(binary)

cleanup.append(gdb_p.wait)
cleanup.append(gdb_p.kill)
except:
logging.error("Can't start debug session")
finally:
logging.status("Stopping debug session")
for f in reversed(cleanup):
f()

self._reset_board()
8 changes: 8 additions & 0 deletions tockloader/tockloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,14 @@ def print_known_boards(self):
"""
BoardInterface(self.args).print_known_boards()

def debug_binary(self, binary):
"""
Debug binary on board.
"""
# Enter bootloader mode to get things started
with self._start_communication_with_board():
self.channel.debug(binary)

############################################################################
## Internal Helper Functions for Communicating with Boards
############################################################################
Expand Down