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

Add rtt control block into YAML config #1418

Open
wants to merge 3 commits into
base: main
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
5 changes: 5 additions & 0 deletions pyocd/core/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ class OptionInfo(NamedTuple):
OptionInfo('xpsr_control_fields', bool, False,
"When set to True, XPSR and CONTROL registers will have their respective bitfields defined "
"for presentation in gdb."),

# RTT options
OptionInfo('rtt.start', int, None, "Start address of RTT control block search range."),
OptionInfo('rtt.size', int, None, "Length of RTT control block search range."),
OptionInfo('rtt.elf', str, None, "ELF file to use for obtaining RTT control block address."),
]

## @brief The runtime dictionary of options.
Expand Down
71 changes: 48 additions & 23 deletions pyocd/subcommands/rtt_cmd.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# pyOCD debugger
# Copyright (c) 2022 crides
# Copyright (c) 2021 mikisama
# Copyright (C) 2021 Ciro Cattuto <ciro.cattuto@gmail.com>
# Copyright (C) 2021 Simon D. Levy <simon.d.levy@gmail.com>
Expand Down Expand Up @@ -27,6 +28,7 @@
from pyocd.utility.cmdline import convert_session_options, int_base_0
from pyocd.utility.kbhit import KBHit
from ctypes import Structure, c_char, c_int32, c_uint32, sizeof
from elftools.elf.elffile import ELFFile


LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -82,11 +84,13 @@ def get_args(cls) -> List[argparse.ArgumentParser]:

rtt_parser = argparse.ArgumentParser(cls.HELP, add_help=False)

rtt_options = rtt_parser.add_argument_group("rtt options")
rtt_options.add_argument("-a", "--address", type=int_base_0, default=None,
rtt_search_opts = rtt_parser.add_argument_group("rtt options")
rtt_search_opts.add_argument("-a", "--address", type=int_base_0, default=None,
help="Start address of RTT control block search range.")
rtt_options.add_argument("-s", "--size", type=int_base_0, default=None,
rtt_search_opts.add_argument("-s", "--size", type=int_base_0, default=None,
help="Size of RTT control block search range.")
rtt_parser.add_argument("-e", "--elf", type=str, default=None,
help="ELF file for finding the control block address directly")

return [cls.CommonOptions.COMMON, cls.CommonOptions.CONNECT, rtt_parser]

Expand Down Expand Up @@ -120,27 +124,48 @@ def invoke(self) -> int:
memory_map: MemoryMap = target.get_memory_map()
ram_region: MemoryRegion = memory_map.get_default_region_of_type(MemoryType.RAM)

if self._args.address is None or self._args.size is None:
rtt_range_start = ram_region.start
rtt_range_size = ram_region.length
elif ram_region.start <= self._args.address and self._args.size <= ram_region.length:
rtt_range_start = self._args.address
rtt_range_size = self._args.size

LOG.info(f"RTT control block search range [{rtt_range_start:#08x}, {rtt_range_size:#08x}]")

rtt_cb_addr = -1
data = bytearray(b'0000000000')
chunk_size = 1024
while rtt_range_size > 0:
read_size = min(chunk_size, rtt_range_size)
data += bytearray(target.read_memory_block8(rtt_range_start, read_size))
pos = data[-(read_size + 10):].find(b"SEGGER RTT")
if pos != -1:
rtt_cb_addr = rtt_range_start + pos - 10
break
rtt_range_start += read_size
rtt_range_size -= read_size

elf_file_arg, elf_file_option = self._args.elf, session.options.get("rtt.elf")
if elf_file_arg != None:
elf_file = elf_file_arg
elif elf_file_option != None:
elf_file = elf_file_option
else:
elf_file = None

if elf_file != None:
elf = ELFFile(open(self._args.elf, "rb"))
symtab = elf.get_section_by_name(".symtab")
if symtab:
rtt_entry = symtab.get_symbol_by_name("_SEGGER_RTT")
if len(rtt_entry) > 0:
rtt_cb_addr = rtt_entry[0].entry["st_value"]
Comment on lines +138 to +143
Copy link
Member

@flit flit Jun 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fyi, pyocd has some built-in support for ELF symbol extraction (and other things) in the pyocd.debug.elf sub-package. It's based on pyelftools, so for cases like this, where there is not much advantage, it's fine to directly use pyelftools. So no need to rewrite this.

For reference, this is what this code would look like using pyocd's ELF tools:

sym_info = ELFBinaryFile(self._args.elf).symbol_decoder.get_symbol_by_name('_SEGGER_RTT')
if sym_info:
    rtt_cb_addr = sym_info.value

else:
def valid_range(start, size):
return start != None and size != None \
and ram_region.start <= start and size + start <= ram_region.start + ram_region.length
config_start, config_size = session.options.get('rtt.start'), session.options.get('rtt.size')
if valid_range(self._args.address, self._args.size):
rtt_range_start, rtt_range_size = self._args.address, self._args.size
elif valid_range(config_start, config_size):
rtt_range_start, rtt_range_size = config_start, config_size
else:
rtt_range_start, rtt_range_size = ram_region.start, ram_region.length

LOG.info(f"RTT control block search range [{rtt_range_start:#08x}, {rtt_range_size:#08x}]")

data = bytearray(b'0000000000')
chunk_size = 1024
while rtt_range_size > 0:
read_size = min(chunk_size, rtt_range_size)
data += bytearray(target.read_memory_block8(rtt_range_start, read_size))
pos = data[-(read_size + 10):].find(b"SEGGER RTT")
if pos != -1:
rtt_cb_addr = rtt_range_start + pos - 10
break
rtt_range_start += read_size
rtt_range_size -= read_size

if rtt_cb_addr == -1:
LOG.error("No RTT control block available")
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ install_requires =
pyyaml>=6.0,<7.0
six>=1.15.0,<2.0
typing-extensions>=4.0,<5.0
elftools>=0.28
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This package doesn't exist. The package on PyPI is actually called pyelftools, and is already a pyocd dependency. 😄


[options.extras_require]
pemicro =
Expand Down