mirror of
https://github.com/google/pebble.git
synced 2025-03-15 08:41:21 +00:00
113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
# Copyright 2024 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import logging
|
|
import subprocess
|
|
import time
|
|
|
|
|
|
def find_gdb_path():
|
|
""" Find the first arm gdb on our path"""
|
|
prioritized_names = ['pebble-gdb', 'arm-none-eabi-gdb-py', 'arm-none-eabi-gdb']
|
|
for name in prioritized_names:
|
|
try:
|
|
which_all_cmd = 'which %s' % name
|
|
out = subprocess.check_output(which_all_cmd, shell=True)
|
|
except subprocess.CalledProcessError, e:
|
|
if e.returncode == 1:
|
|
continue # `which` returns with 1 when nothing is found
|
|
raise e
|
|
path = out.splitlines()[0]
|
|
logging.info("Found %s at %s" % (name, path))
|
|
return path
|
|
return None
|
|
|
|
|
|
class GDBDriver(object):
|
|
def __init__(self, elf_path, gdb_path=None, server_port=1234):
|
|
self.gdb_path = gdb_path or find_gdb_path()
|
|
if not self.gdb_path:
|
|
raise Exception("pebble-gdb not found on your path, nor"
|
|
" was it specified using the `gdb_path` argument")
|
|
self.elf_path = elf_path
|
|
self.server_port = server_port
|
|
self.pipe = None
|
|
self.interface = GDBInterface(self)
|
|
|
|
def _gdb_command(self):
|
|
cmd = self.gdb_path
|
|
cmd += " %s" % self.elf_path
|
|
cmd += " -ex=\"target remote :%u\"" % self.server_port
|
|
return cmd
|
|
|
|
def start(self):
|
|
if self.pipe:
|
|
raise Exception("GDB Already running.")
|
|
|
|
# Run GDB:
|
|
cmd = self._gdb_command()
|
|
try:
|
|
self.pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE,
|
|
shell=True)
|
|
except:
|
|
logging.error("Failed to start GDB.\nCommand: `%s`" % cmd)
|
|
return
|
|
time.sleep(0.1) # FIXME
|
|
logging.info("GDB started.")
|
|
|
|
def stop(self):
|
|
if self.pipe:
|
|
self.pipe.kill()
|
|
logging.info("GDB stopped.")
|
|
self.pipe = None
|
|
|
|
def write_stdin(self, cmd):
|
|
if not self.pipe:
|
|
logging.error("GDB not running")
|
|
return
|
|
self.pipe.stdin.write(cmd)
|
|
|
|
def send_signal(self, signal):
|
|
self.pipe.send_signal(signal)
|
|
|
|
|
|
class GDBInterface(object):
|
|
def __init__(self, gdb_driver):
|
|
assert gdb_driver
|
|
self.gdb_driver = gdb_driver
|
|
|
|
def _send(self, cmd):
|
|
self.gdb_driver.write_stdin(cmd)
|
|
|
|
def _send_signal(self, signal):
|
|
self.gdb_driver.send_signal(signal)
|
|
|
|
def interrupt(self):
|
|
self._send_signal(signal.SIGINT)
|
|
|
|
def cont(self):
|
|
self._send("c\n")
|
|
|
|
def source(self, script_file_name):
|
|
self._send("source %s\n" % script_file_name)
|
|
|
|
def set(self, var_name, expr):
|
|
self._send("set %s=%s\n" % (var_name, expr))
|
|
|
|
def disable_breakpoints(self):
|
|
self._send("dis\n")
|
|
|
|
def set_pagination(self, enabled):
|
|
enabled_str = "on" if enabled else "off"
|
|
self._send("set pagination %s\n" % enabled_str)
|