Skip to content

Commit

Permalink
Merge branch 'feature/move-gdb-options-to_project_description_json_v5…
Browse files Browse the repository at this point in the history
….2' into 'release/v5.2'

feat(debugging): move gdbinit generation to CMake (v5.2)

See merge request espressif/esp-idf!35177
  • Loading branch information
dobairoland committed Dec 7, 2024
2 parents c19ac46 + b7b6fff commit 3f920b5
Show file tree
Hide file tree
Showing 19 changed files with 510 additions and 428 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
list(APPEND compile_options "-fdump-rtl-expand")
endif()

idf_build_set_property(GDBINIT_FILES_PREFIX_MAP "${BUILD_DIR}/gdbinit/prefix_map")
file(MAKE_DIRECTORY "${BUILD_DIR}/gdbinit")
file(WRITE "${BUILD_DIR}/gdbinit/prefix_map" "")

if(NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS 8.0.0)
if(CONFIG_COMPILER_HIDE_PATHS_MACROS)
list(APPEND compile_options "-fmacro-prefix-map=${CMAKE_SOURCE_DIR}=.")
Expand Down
73 changes: 73 additions & 0 deletions components/esp_rom/gen_gdbinit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env python
#
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import json
import os
import sys
from textwrap import indent

IDF_PATH = os.getenv('IDF_PATH', '')
ROMS_JSON = os.path.join(IDF_PATH, 'tools', 'idf_py_actions', 'roms.json') # type: ignore


# Direct string extraction and comparison is not feasible due to:
# 1. ROM ELF binaries for esp32XX chips are little-endian. The byte order in
# the binary may differ from the system's endianness. We must ensure the
# bytes are read correctly for the system where the script runs.
# 2. GDB lacks built-in string comparison functionality. To work around this,
# strings are converted to numeric values for comparison.
def get_rom_if_condition_str(date_addr: int, date_str: str) -> str:
r = []
for i in range(0, len(date_str), 4):
value = hex(int.from_bytes(bytes(date_str[i:i + 4], 'utf-8'), 'little'))
r.append(f'(*(int*) {hex(date_addr + i)}) == {value}')
return 'if ' + ' && '.join(r)


def generate_gdbinit_rom_add_symbols(target: str) -> str:
base_ident = ' '
rom_elfs_dir = os.getenv('ESP_ROM_ELF_DIR')
if not rom_elfs_dir:
raise EnvironmentError(
'ESP_ROM_ELF_DIR environment variable is not defined. Please try to run IDF "install" and "export" scripts.')
if os.name == 'nt':
# convert to posix-path for windows
rom_elfs_dir = rom_elfs_dir.replace('\\', '/')
with open(ROMS_JSON, 'r') as f:
roms = json.load(f)
if target not in roms:
msg_body = f'Warning: ROM ELF is not supported yet for "{target}".' # noqa: E713
return f'echo {msg_body}\\n\n'
r = ['', f'# Load {target} ROM ELF symbols']
r.append('define target hookpost-remote')
r.append('set confirm off')
# Since GDB does not have 'else if' statement than we use nested 'if..else' instead.
for i, k in enumerate(roms[target], 1):
indent_str = base_ident * i
rom_file = f'{target}_rev{k["rev"]}_rom.elf'
build_date_addr = int(k['build_date_str_addr'], base=16)
r.append(indent(f'# if $_streq((char *) {hex(build_date_addr)}, "{k["build_date_str"]}")', indent_str))
r.append(indent(get_rom_if_condition_str(build_date_addr, k['build_date_str']), indent_str))
r.append(indent(f'add-symbol-file {rom_elfs_dir}{rom_file}', indent_str + base_ident))
r.append(indent('else', indent_str))
if i == len(roms[target]):
# In case no one known ROM ELF fits - print warning
indent_str += base_ident
msg_body = f'Warning: Unknown {target} ROM revision.'
r.append(indent(f'echo {msg_body}\\n', indent_str))
# Close 'else' operators
for i in range(len(roms[target]), 0, -1):
r.append(indent('end', base_ident * i))
r.append('set confirm on')
r.append('end')
return '\n'.join(r)[1:]


if __name__ == '__main__':
if len(sys.argv) != 2:
raise ValueError('Please pass only one argument (target).')

target = sys.argv[1]
gdbinit_lines = generate_gdbinit_rom_add_symbols(target)
print(gdbinit_lines)
54 changes: 54 additions & 0 deletions components/esp_rom/test_esp_rom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import json
import os

import elftools.common.utils as ecu
import jsonschema
from elftools.elf.elffile import ELFFile
from idf_build_apps.constants import SUPPORTED_TARGETS

IDF_PATH = os.getenv('IDF_PATH', '')
ROMS_JSON = os.path.join(IDF_PATH, 'tools', 'idf_py_actions', 'roms.json') # type: ignore


def test_roms_validate_json() -> None:
with open(ROMS_JSON, 'r') as f:
roms_json = json.load(f)

json_schema_path = os.path.join(os.path.dirname(ROMS_JSON), 'roms_schema.json')
with open(json_schema_path, 'r') as f:
schema_json = json.load(f)
jsonschema.validate(roms_json, schema_json)


def test_roms_check_supported_chips() -> None:
with open(ROMS_JSON, 'r') as f:
roms_json = json.load(f)
for chip in SUPPORTED_TARGETS:
assert chip in roms_json, f'Have no ROM data for chip {chip}'


def test_roms_validate_build_date() -> None:
def get_string_from_elf_by_addr(filename: str, address: int) -> str:
result = ''
with open(filename, 'rb') as stream:
elf_file = ELFFile(stream)
ro = elf_file.get_section_by_name('.rodata')
ro_addr_delta = ro['sh_addr'] - ro['sh_offset']
cstring = ecu.parse_cstring_from_stream(ro.stream, address - ro_addr_delta)
if cstring:
result = str(cstring.decode('utf-8'))
return result

rom_elfs_dir = os.getenv('ESP_ROM_ELF_DIR', '')
with open(ROMS_JSON, 'r') as f:
roms_json = json.load(f)

for chip in roms_json:
for k in roms_json[chip]:
rom_file = os.path.join(rom_elfs_dir, f'{chip}_rev{k["rev"]}_rom.elf')
build_date_str = get_string_from_elf_by_addr(rom_file, int(k['build_date_str_addr'], base=16))
assert len(build_date_str) == 11
assert build_date_str == k['build_date_str']
16 changes: 10 additions & 6 deletions docs/en/api-guides/jtag-debugging/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,17 @@ Setup of OpenOCD

.. highlight:: bash

If you have already set up ESP-IDF with CMake build system according to the :doc:`Getting Started Guide <../../get-started/index>`, then OpenOCD is already installed. After :ref:`setting up the environment <get-started-set-up-env>` in your terminal, you should be able to run OpenOCD. Check this by executing the following command::
If you have already set up ESP-IDF with CMake build system according to the :doc:`Getting Started Guide <../../get-started/index>`, then OpenOCD is already installed. After :ref:`setting up the environment <get-started-set-up-env>` in your terminal, you should be able to run OpenOCD. Check this by executing the following command:

.. code-block:: none
openocd --version
.. highlight:: none

The output should be as follows (although the version may be more recent than listed here)::
The output should be as follows (although the version may be more recent than listed here):

.. code-block:: none
Open On-Chip Debugger v0.12.0-esp32-20240318 (2024-03-18-18:25)
Licensed under GNU GPL v2
Expand Down Expand Up @@ -174,7 +178,7 @@ Once target is configured and connected to computer, you are ready to launch Ope

.. highlight:: bash

Open a terminal and set it up for using the ESP-IDF as described in the :ref:`setting up the environment <get-started-set-up-env>` section of the Getting Started Guide. Then run OpenOCD (this command works on Windows, Linux, and macOS):
Open a terminal and set it up for using the ESP-IDF as described in the :ref:`setting up the environment <get-started-set-up-env>` section of the Getting Started Guide. To run OpenOCD for a specific board, you must pass the board-specific configuration. The default configuration for the built project can be found in the ``debug_arguments_openocd`` field of the ``build/project_description.json`` file. There is an example to run OpenOCD (this command works on Windows, Linux, and macOS):

.. include:: {IDF_TARGET_PATH_NAME}.inc
:start-after: run-openocd
Expand Down Expand Up @@ -276,7 +280,7 @@ Before proceeding to examples, set up your {IDF_TARGET_NAME} target and load it
.. _jtag-debugging-building-openocd:

Building OpenOCD from Sources
---------------------------------
-----------------------------

Please refer to separate documents listed below, that describe build process.

Expand Down Expand Up @@ -318,7 +322,7 @@ and Windows:
.. _jtag-debugging-tips-and-quirks:

Tips and Quirks
------------------
---------------

This section provides collection of links to all tips and quirks referred to from various parts of this guide.

Expand All @@ -329,7 +333,7 @@ This section provides collection of links to all tips and quirks referred to fro


Related Documents
---------------------
-----------------

.. toctree::
:hidden:
Expand Down
Loading

0 comments on commit 3f920b5

Please sign in to comment.