1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-22 11:43:51 +01:00
This commit is contained in:
J. Nick Koston
2025-10-17 15:04:19 -10:00
parent e1e047c53f
commit 84316d62f9

View File

@@ -29,59 +29,6 @@ if TYPE_CHECKING:
_LOGGER = logging.getLogger(__name__)
def get_toolchain_for_platform(platform: str) -> tuple[str | None, str | None]:
"""Get objdump and readelf paths for a given platform.
This function auto-detects the correct toolchain based on the platform name,
using the same detection logic as PlatformIO's IDEData class.
Args:
platform: Platform name (e.g., "esp8266-ard", "esp32-idf", "esp32-c3-idf")
Returns:
Tuple of (objdump_path, readelf_path) or (None, None) if not found/supported
"""
home = Path.home()
platformio_packages = home / ".platformio" / "packages"
# Map platform to toolchain and prefix (same logic as PlatformIO uses)
toolchain = None
prefix = None
if "esp8266" in platform:
toolchain = "toolchain-xtensa"
prefix = "xtensa-lx106-elf"
elif "esp32-c" in platform or "esp32-h" in platform or "esp32-p4" in platform:
# RISC-V variants (C2, C3, C5, C6, H2, P4)
toolchain = "toolchain-riscv32-esp"
prefix = "riscv32-esp-elf"
elif "esp32" in platform:
# Xtensa variants (original, S2, S3)
toolchain = "toolchain-xtensa-esp-elf"
if "s2" in platform:
prefix = "xtensa-esp32s2-elf"
elif "s3" in platform:
prefix = "xtensa-esp32s3-elf"
else:
prefix = "xtensa-esp32-elf"
else:
# Other platforms (RP2040, LibreTiny, etc.) - not supported for ELF analysis
_LOGGER.debug("Platform %s not supported for ELF analysis", platform)
return None, None
# Construct paths (same pattern as IDEData.objdump_path/readelf_path)
toolchain_path = platformio_packages / toolchain / "bin"
objdump_path = toolchain_path / f"{prefix}-objdump"
readelf_path = toolchain_path / f"{prefix}-readelf"
if objdump_path.exists() and readelf_path.exists():
_LOGGER.debug("Found %s toolchain: %s", platform, prefix)
return str(objdump_path), str(readelf_path)
_LOGGER.warning("Toolchain not found at %s", toolchain_path)
return None, None
@dataclass
class MemorySection:
"""Represents a memory section with its symbols."""
@@ -171,7 +118,6 @@ class MemoryAnalyzer:
def _parse_sections(self) -> None:
"""Parse section headers from ELF file."""
try:
result = subprocess.run(
[self.readelf_path, "-S", str(self.elf_path)],
capture_output=True,
@@ -203,13 +149,8 @@ class MemoryAnalyzer:
self.sections[mapped_section] = MemorySection(mapped_section)
self.sections[mapped_section].total_size += size
except subprocess.CalledProcessError as e:
_LOGGER.error("Failed to parse sections: %s", e)
raise
def _parse_symbols(self) -> None:
"""Parse symbols from ELF file."""
try:
result = subprocess.run(
[self.objdump_path, "-t", str(self.elf_path)],
capture_output=True,
@@ -233,10 +174,6 @@ class MemoryAnalyzer:
self.sections[section].symbols.append((name, size, ""))
seen_addresses.add(address)
except subprocess.CalledProcessError as e:
_LOGGER.error("Failed to parse symbols: %s", e)
raise
def _categorize_symbols(self) -> None:
"""Categorize symbols by component."""
# First, collect all unique symbol names for batch demangling
@@ -373,13 +310,12 @@ class MemoryAnalyzer:
# Map original to demangled names
for original, demangled in zip(symbols, demangled_lines):
self._demangle_cache[original] = demangled
else:
# If batch fails, cache originals
for symbol in symbols:
self._demangle_cache[symbol] = symbol
return
except (subprocess.SubprocessError, OSError, UnicodeDecodeError) as e:
# On error, cache originals
_LOGGER.debug("Failed to batch demangle symbols: %s", e)
# If demangling failed, cache originals
for symbol in symbols:
self._demangle_cache[symbol] = symbol