From dd471c680f596c269f742e71281b764d9bbe516a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 27 Sep 2025 23:29:37 +0200 Subject: [PATCH 01/14] Implement coredump analysis targets in builder Add custom targets for coredump analysis with CLI support. --- builder/main.py | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/builder/main.py b/builder/main.py index d218e02f9..81524943e 100644 --- a/builder/main.py +++ b/builder/main.py @@ -650,6 +650,70 @@ def firmware_metrics(target, source, env): print(f'Make sure esp-idf-size is installed: uv pip install --python "{PYTHON_EXE}" esp-idf-size') +def coredump_analysis(target, source, env): + """ + Custom target to run esp-coredump with support for command line parameters. + Usage: pio run -t coredump -- [esp-coredump arguments] + + Args: + target: SCons target + source: SCons source + env: SCons environment object + """ + if terminal_cp != "utf-8": + print("Coredump analysis can not be shown. Set the terminal codepage to \"utf-8\"") + return + + elf_file = str(Path(env.subst("$BUILD_DIR")) / (env.subst("$PROGNAME") + ".elf")) + if not Path(elf_file).is_file(): + # elf file can be in project dir + elf_file = str(Path(get_project_dir()) / (env.subst("$PROGNAME") + ".elf")) + + if not Path(elf_file).is_file(): + print(f"Error: ELF file not found: {elf_file}") + print("Make sure the project is built first with 'pio run'") + return + + try: + cmd = [PYTHON_EXE, "-m", "esp_coredump"] + + # Parameters from platformio.ini + extra_args = env.GetProjectOption("custom_esp_coredump_args", "") + if extra_args: + cmd.extend(shlex.split(extra_args)) + + # Command Line Parameter, after -- + cli_args = [] + if "--" in sys.argv: + dash_index = sys.argv.index("--") + if dash_index + 1 < len(sys.argv): + cli_args = sys.argv[dash_index + 1:] + + # Add CLI arguments + if cli_args: + cmd.extend(cli_args) + else: + # Default arguments if none provided + cmd.extend(["info_corefile", "--chip", mcu, "--elf", elf_file]) + + # Debug-Info if wanted + if env.GetProjectOption("custom_esp_coredump_verbose", False): + print(f"Running command: {' '.join(cmd)}") + + # Execute esp-coredump with current environment + result = subprocess.run(cmd, check=False, capture_output=False, env=os.environ) + + if result.returncode != 0: + print(f"Warning: esp-coredump exited with code {result.returncode}") + + except FileNotFoundError: + print("Error: Python executable not found.") + print("Check your Python installation.") + except Exception as e: + print(f"Error: Failed to run coredump analysis: {e}") + print(f'Make sure esp-coredump is installed: uv pip install --python "{PYTHON_EXE}" esp-coredump') + + # # Target: Build executable and linkable firmware or FS image # @@ -931,6 +995,27 @@ def firmware_metrics(target, source, env): always_build=True, ) +# Register Custom Target for coredump analysis +env.AddCustomTarget( + name="coredump", + dependencies="$BUILD_DIR/${PROGNAME}.elf", + actions=coredump_analysis, + title="Coredump Analysis", + description="Analyze coredumps using esp-coredump " + "(supports CLI args after --)", + always_build=True, +) + +# Additional Target without Build-Dependency when already compiled +env.AddCustomTarget( + name="coredump-only", + dependencies=None, + actions=coredump_analysis, + title="Coredump Analysis (No Build)", + description="Analyze coredumps without building first", + always_build=True, +) + # Override memory inspection behavior env.SConscript("sizedata.py", exports="env") From fcfa8c673bac44aa563e32bc78a8772d8cb44c23 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 27 Sep 2025 23:49:21 +0200 Subject: [PATCH 02/14] Add esp-coredump dependency to penv_setup.py --- builder/penv_setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 448aa40d6..312054595 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -55,7 +55,8 @@ "ecdsa": ">=0.19.1", "bitstring": ">=4.3.1", "reedsolo": ">=1.5.3,<1.8", - "esp-idf-size": ">=1.6.1" + "esp-idf-size": ">=1.6.1", + "esp-coredump": ">=1.14.0" } From aaae112e2b450807c9f156d0acbc01ffa417a97c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 27 Sep 2025 23:57:08 +0200 Subject: [PATCH 03/14] fix syntax for coredump Refactor command construction to include default parameters and handle extra arguments from platformio.ini. --- builder/main.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/builder/main.py b/builder/main.py index 81524943e..f920eb758 100644 --- a/builder/main.py +++ b/builder/main.py @@ -677,11 +677,6 @@ def coredump_analysis(target, source, env): try: cmd = [PYTHON_EXE, "-m", "esp_coredump"] - # Parameters from platformio.ini - extra_args = env.GetProjectOption("custom_esp_coredump_args", "") - if extra_args: - cmd.extend(shlex.split(extra_args)) - # Command Line Parameter, after -- cli_args = [] if "--" in sys.argv: @@ -689,12 +684,24 @@ def coredump_analysis(target, source, env): if dash_index + 1 < len(sys.argv): cli_args = sys.argv[dash_index + 1:] - # Add CLI arguments + # Add CLI arguments or use defaults if cli_args: cmd.extend(cli_args) + # ELF file should be at the end as positional argument + if not any(arg.endswith('.elf') for arg in cli_args): + cmd.append(elf_file) else: # Default arguments if none provided - cmd.extend(["info_corefile", "--chip", mcu, "--elf", elf_file]) + # Parameters from platformio.ini + extra_args = env.GetProjectOption("custom_esp_coredump_args", "") + if extra_args: + cmd.extend(shlex.split(extra_args)) + else: + # Use defaults: info_corefile --chip + cmd.extend(["info_corefile", "--chip", mcu]) + + # ELF file as positional argument at the end + cmd.append(elf_file) # Debug-Info if wanted if env.GetProjectOption("custom_esp_coredump_verbose", False): From c202672503e49092754e42da13e5df3e31f6f25c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Sep 2025 00:05:15 +0200 Subject: [PATCH 04/14] Refactor command construction for core dump args --- builder/main.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/builder/main.py b/builder/main.py index f920eb758..b7972edb4 100644 --- a/builder/main.py +++ b/builder/main.py @@ -695,13 +695,12 @@ def coredump_analysis(target, source, env): # Parameters from platformio.ini extra_args = env.GetProjectOption("custom_esp_coredump_args", "") if extra_args: + # Parse extra args and add ELF file at the end cmd.extend(shlex.split(extra_args)) + cmd.append(elf_file) else: - # Use defaults: info_corefile --chip - cmd.extend(["info_corefile", "--chip", mcu]) - - # ELF file as positional argument at the end - cmd.append(elf_file) + # Use defaults: info_corefile --chip + cmd.extend(["info_corefile", "--chip", mcu, elf_file]) # Debug-Info if wanted if env.GetProjectOption("custom_esp_coredump_verbose", False): From 874b240bfd961b94835db1b25030430833830b12 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Sep 2025 00:10:39 +0200 Subject: [PATCH 05/14] Reorder command arguments for info_corefile usage --- builder/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index b7972edb4..65f6635de 100644 --- a/builder/main.py +++ b/builder/main.py @@ -699,8 +699,8 @@ def coredump_analysis(target, source, env): cmd.extend(shlex.split(extra_args)) cmd.append(elf_file) else: - # Use defaults: info_corefile --chip - cmd.extend(["info_corefile", "--chip", mcu, elf_file]) + # Use defaults: --chip info_corefile + cmd.extend(["--chip", mcu, "info_corefile", elf_file]) # Debug-Info if wanted if env.GetProjectOption("custom_esp_coredump_verbose", False): From 84b20fb5dfb236a92e5ceecc6feed1e577e9168f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Sep 2025 00:16:52 +0200 Subject: [PATCH 06/14] Add ROM_ELFS_DIR_PATH and set environment variables --- builder/frameworks/espidf.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 8ccda07d0..0c132ff7c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -88,11 +88,16 @@ IDF_ENV_VERSION = "1.0.0" _framework_pkg_dir = platform.get_package_dir("framework-espidf") +_rom_elfs_dir = platform.get_package_dir("tool-esp-rom-elfs") if not _framework_pkg_dir or not os.path.isdir(_framework_pkg_dir): sys.stderr.write(f"Error: Missing framework directory '{_framework_pkg_dir}'\n") env.Exit(1) FRAMEWORK_DIR_PATH = Path(_framework_pkg_dir).resolve() +ROM_ELFS_DIR_PATH = Path(_rom_elfs_dir).resolve() FRAMEWORK_DIR = str(FRAMEWORK_DIR_PATH) +ROM_ELFS_DIR = str(ROM_ELFS_DIR_PATH) +os.environ['IDF_PATH'] = FRAMEWORK_DIR +os.environ['ESP_ROM_ELF_DIR'] = ROM_ELFS_DIR TOOLCHAIN_DIR = platform.get_package_dir( "toolchain-xtensa-esp-elf" if mcu in ("esp32", "esp32s2", "esp32s3") From 0e398804f2de02b847fa1ff988c573fc66b5727b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Sep 2025 00:31:26 +0200 Subject: [PATCH 07/14] Configure ESP-IDF environment for esp-coredump Set up ESP-IDF environment variables for coredump execution. --- builder/main.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index 65f6635de..7838ba14f 100644 --- a/builder/main.py +++ b/builder/main.py @@ -702,12 +702,25 @@ def coredump_analysis(target, source, env): # Use defaults: --chip info_corefile cmd.extend(["--chip", mcu, "info_corefile", elf_file]) + # Set up ESP-IDF environment variables when ESP-IDF framework is used + coredump_env = os.environ.copy() + if env.get("PIOFRAMEWORK") and "espidf" in env.get("PIOFRAMEWORK", []): + _framework_pkg_dir = platform.get_package_dir("framework-espidf") + _rom_elfs_dir = platform.get_package_dir("tool-esp-rom-elfs") + if _framework_pkg_dir and os.path.isdir(_framework_pkg_dir): + coredump_env['IDF_PATH'] = str(Path(_framework_pkg_dir).resolve()) + if _rom_elfs_dir and os.path.isdir(_rom_elfs_dir): + coredump_env['ESP_ROM_ELF_DIR'] = str(Path(_rom_elfs_dir).resolve()) + # Debug-Info if wanted if env.GetProjectOption("custom_esp_coredump_verbose", False): print(f"Running command: {' '.join(cmd)}") + if 'IDF_PATH' in coredump_env: + print(f"IDF_PATH: {coredump_env['IDF_PATH']}") + print(f"ESP_ROM_ELF_DIR: {coredump_env.get('ESP_ROM_ELF_DIR', 'Not set')}") - # Execute esp-coredump with current environment - result = subprocess.run(cmd, check=False, capture_output=False, env=os.environ) + # Execute esp-coredump with ESP-IDF environment + result = subprocess.run(cmd, check=False, capture_output=False, env=coredump_env) if result.returncode != 0: print(f"Warning: esp-coredump exited with code {result.returncode}") From f5c17f87c8442028fd7c63b742e7062baf4647f7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Sep 2025 12:24:28 +0200 Subject: [PATCH 08/14] Remove unused ROM_ELFS_DIR variable Removed unused ROM_ELFS_DIR and related environment variables. --- builder/frameworks/espidf.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 0c132ff7c..e0cc75924 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -88,16 +88,11 @@ IDF_ENV_VERSION = "1.0.0" _framework_pkg_dir = platform.get_package_dir("framework-espidf") -_rom_elfs_dir = platform.get_package_dir("tool-esp-rom-elfs") if not _framework_pkg_dir or not os.path.isdir(_framework_pkg_dir): sys.stderr.write(f"Error: Missing framework directory '{_framework_pkg_dir}'\n") env.Exit(1) FRAMEWORK_DIR_PATH = Path(_framework_pkg_dir).resolve() -ROM_ELFS_DIR_PATH = Path(_rom_elfs_dir).resolve() FRAMEWORK_DIR = str(FRAMEWORK_DIR_PATH) -ROM_ELFS_DIR = str(ROM_ELFS_DIR_PATH) -os.environ['IDF_PATH'] = FRAMEWORK_DIR -os.environ['ESP_ROM_ELF_DIR'] = ROM_ELFS_DIR TOOLCHAIN_DIR = platform.get_package_dir( "toolchain-xtensa-esp-elf" if mcu in ("esp32", "esp32s2", "esp32s3") @@ -109,13 +104,13 @@ sys.stderr.write(f"Error: Missing toolchain directory '{TOOLCHAIN_DIR}'\n") env.Exit(1) - def create_silent_action(action_func): """Create a silent SCons action that suppresses output""" silent_action = env.Action(action_func) silent_action.strfunction = lambda target, source, env: '' return silent_action + if "arduino" in env.subst("$PIOFRAMEWORK"): _arduino_pkg_dir = platform.get_package_dir("framework-arduinoespressif32") if not _arduino_pkg_dir or not os.path.isdir(_arduino_pkg_dir): From 5d72bcb28a54f6f84bf1404946146a3f3fbe151a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Sep 2025 12:25:18 +0200 Subject: [PATCH 09/14] Add silent action creation function in espidf.py --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index e0cc75924..8ccda07d0 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -104,13 +104,13 @@ sys.stderr.write(f"Error: Missing toolchain directory '{TOOLCHAIN_DIR}'\n") env.Exit(1) + def create_silent_action(action_func): """Create a silent SCons action that suppresses output""" silent_action = env.Action(action_func) silent_action.strfunction = lambda target, source, env: '' return silent_action - if "arduino" in env.subst("$PIOFRAMEWORK"): _arduino_pkg_dir = platform.get_package_dir("framework-arduinoespressif32") if not _arduino_pkg_dir or not os.path.isdir(_arduino_pkg_dir): From 1b258f7b082e6b7dd2e02ec06261cd7636af618a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Sep 2025 16:21:27 +0200 Subject: [PATCH 10/14] Install espidf and rom-elf for core-dump --- builder/main.py | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/builder/main.py b/builder/main.py index 7838ba14f..17a199211 100644 --- a/builder/main.py +++ b/builder/main.py @@ -702,15 +702,36 @@ def coredump_analysis(target, source, env): # Use defaults: --chip info_corefile cmd.extend(["--chip", mcu, "info_corefile", elf_file]) - # Set up ESP-IDF environment variables when ESP-IDF framework is used + # Set up ESP-IDF environment variables and ensure required packages are installed coredump_env = os.environ.copy() - if env.get("PIOFRAMEWORK") and "espidf" in env.get("PIOFRAMEWORK", []): - _framework_pkg_dir = platform.get_package_dir("framework-espidf") - _rom_elfs_dir = platform.get_package_dir("tool-esp-rom-elfs") - if _framework_pkg_dir and os.path.isdir(_framework_pkg_dir): - coredump_env['IDF_PATH'] = str(Path(_framework_pkg_dir).resolve()) - if _rom_elfs_dir and os.path.isdir(_rom_elfs_dir): - coredump_env['ESP_ROM_ELF_DIR'] = str(Path(_rom_elfs_dir).resolve()) + + # Check if ESP-IDF packages are available, install if missing + _framework_pkg_dir = platform.get_package_dir("framework-espidf") + _rom_elfs_dir = platform.get_package_dir("tool-esp-rom-elfs") + + # Install framework-espidf if not available + if not _framework_pkg_dir or not os.path.isdir(_framework_pkg_dir): + print("ESP-IDF framework not found, installing...") + try: + platform.install_package("framework-espidf") + _framework_pkg_dir = platform.get_package_dir("framework-espidf") + except Exception as e: + print(f"Warning: Failed to install framework-espidf: {e}") + + # Install tool-esp-rom-elfs if not available + if not _rom_elfs_dir or not os.path.isdir(_rom_elfs_dir): + print("ESP ROM ELFs tool not found, installing...") + try: + platform.install_package("tool-esp-rom-elfs") + _rom_elfs_dir = platform.get_package_dir("tool-esp-rom-elfs") + except Exception as e: + print(f"Warning: Failed to install tool-esp-rom-elfs: {e}") + + # Set environment variables if packages are available + if _framework_pkg_dir and os.path.isdir(_framework_pkg_dir): + coredump_env['IDF_PATH'] = str(Path(_framework_pkg_dir).resolve()) + if _rom_elfs_dir and os.path.isdir(_rom_elfs_dir): + coredump_env['ESP_ROM_ELF_DIR'] = str(Path(_rom_elfs_dir).resolve()) # Debug-Info if wanted if env.GetProjectOption("custom_esp_coredump_verbose", False): From 72b28481372e7fcd573175e30dde4e94f2b69871 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Sep 2025 17:00:10 +0200 Subject: [PATCH 11/14] Enhance coredump command handling in main.py Refactor coredump command construction to handle extra arguments and core file detection more robustly. --- builder/main.py | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/builder/main.py b/builder/main.py index 17a199211..e95a7f779 100644 --- a/builder/main.py +++ b/builder/main.py @@ -695,12 +695,35 @@ def coredump_analysis(target, source, env): # Parameters from platformio.ini extra_args = env.GetProjectOption("custom_esp_coredump_args", "") if extra_args: - # Parse extra args and add ELF file at the end - cmd.extend(shlex.split(extra_args)) - cmd.append(elf_file) + args = shlex.split(extra_args) + cmd.extend(args) + # Ensure ELF is last positional if not present + if not any(a.endswith(".elf") for a in args): + cmd.append(elf_file) else: - # Use defaults: --chip info_corefile - cmd.extend(["--chip", mcu, "info_corefile", elf_file]) + # Prefer an explicit core file if configured or present; else read from flash + core_file = env.GetProjectOption("custom_esp_coredump_corefile", "") + if not core_file: + for name in ("coredump.bin", "coredump.b64"): + cand = Path(get_project_dir()) / name + if cand.is_file(): + core_file = str(cand) + break + + # Global options + cmd.extend(["--chip", mcu]) + upload_port = env.subst("$UPLOAD_PORT") + if upload_port: + cmd.extend(["--port", upload_port]) + + # Subcommand and arguments + cmd.append("info_corefile") + if core_file: + cmd.extend(["--core", core_file]) + if core_file.lower().endswith(".b64"): + cmd.extend(["--core-format", "b64"]) + # ELF is the required positional + cmd.append(elf_file) # Set up ESP-IDF environment variables and ensure required packages are installed coredump_env = os.environ.copy() @@ -753,7 +776,6 @@ def coredump_analysis(target, source, env): print(f"Error: Failed to run coredump analysis: {e}") print(f'Make sure esp-coredump is installed: uv pip install --python "{PYTHON_EXE}" esp-coredump') - # # Target: Build executable and linkable firmware or FS image # From bd4921f92cd7b2b0415fcd88739559c3c02a7a3d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:07:00 +0200 Subject: [PATCH 12/14] Update esp_idf_size command in main.py Removed '--ng' argument from esp_idf_size command. --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index e95a7f779..f9f8a3694 100644 --- a/builder/main.py +++ b/builder/main.py @@ -611,7 +611,7 @@ def firmware_metrics(target, source, env): return try: - cmd = [PYTHON_EXE, "-m", "esp_idf_size", "--ng"] + cmd = [PYTHON_EXE, "-m", "esp_idf_size"] # Parameters from platformio.ini extra_args = env.GetProjectOption("custom_esp_idf_size_args", "") From 4f4305df359fc493c39027c9830a1b1db0151987 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:07:50 +0200 Subject: [PATCH 13/14] Update esp-idf-size version requirement --- builder/penv_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 312054595..7196f1217 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -55,7 +55,7 @@ "ecdsa": ">=0.19.1", "bitstring": ">=4.3.1", "reedsolo": ">=1.5.3,<1.8", - "esp-idf-size": ">=1.6.1", + "esp-idf-size": ">=2.0.0", "esp-coredump": ">=1.14.0" } From 49710cc4d35a10afeb0213c5e1506e077dd76bcd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:31:46 +0200 Subject: [PATCH 14/14] Add pydantic dependency version specification --- builder/frameworks/espidf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 1cc9adef4..74fb88074 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1679,6 +1679,7 @@ def _get_installed_uv_packages(python_exe_path): # https://github.com/platformio/platform-espressif32/issues/635 "cryptography": "~=44.0.0", "pyparsing": ">=3.1.0,<4", + "pydantic": "~=2.11.10", "idf-component-manager": "~=2.2", "esp-idf-kconfig": "~=2.5.0" }