mirror of
https://github.com/esphome/esphome.git
synced 2025-10-22 11:43:51 +01:00
merge
This commit is contained in:
@@ -13,28 +13,13 @@ from .const import (
|
||||
CORE_SUBCATEGORY_PATTERNS,
|
||||
DEMANGLED_PATTERNS,
|
||||
ESPHOME_COMPONENT_PATTERN,
|
||||
SECTION_MAPPING,
|
||||
SYMBOL_PATTERNS,
|
||||
)
|
||||
from .helpers import map_section_name, parse_symbol_line
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _map_section_name(raw_section: str) -> str | None:
|
||||
"""Map raw section name to standard section.
|
||||
|
||||
Args:
|
||||
raw_section: Raw section name from ELF file (e.g., ".iram0.text", ".rodata.str1.1")
|
||||
|
||||
Returns:
|
||||
Standard section name (".text", ".rodata", ".data", ".bss") or None
|
||||
"""
|
||||
for standard_section, patterns in SECTION_MAPPING.items():
|
||||
if any(pattern in raw_section for pattern in patterns):
|
||||
return standard_section
|
||||
return None
|
||||
|
||||
|
||||
# Get the list of actual ESPHome components by scanning the components directory
|
||||
@cache
|
||||
def get_esphome_components():
|
||||
@@ -170,7 +155,7 @@ class MemoryAnalyzer:
|
||||
size = int(size_hex, 16)
|
||||
|
||||
# Map to standard section name
|
||||
mapped_section = _map_section_name(section_name)
|
||||
mapped_section = map_section_name(section_name)
|
||||
if mapped_section:
|
||||
if mapped_section not in self.sections:
|
||||
self.sections[mapped_section] = MemorySection(
|
||||
@@ -184,44 +169,6 @@ class MemoryAnalyzer:
|
||||
|
||||
def _parse_symbols(self) -> None:
|
||||
"""Parse symbols from ELF file."""
|
||||
|
||||
def parse_symbol_line(line: str) -> tuple[str, str, int, str] | None:
|
||||
"""Parse a single symbol line from objdump output.
|
||||
|
||||
Returns (section, name, size, address) or None if not a valid symbol.
|
||||
Format: address l/g w/d F/O section size name
|
||||
Example: 40084870 l F .iram0.text 00000000 _xt_user_exc
|
||||
"""
|
||||
parts = line.split()
|
||||
if len(parts) < 5:
|
||||
return None
|
||||
|
||||
try:
|
||||
# Validate and extract address
|
||||
address = parts[0]
|
||||
int(address, 16)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
# Look for F (function) or O (object) flag
|
||||
if "F" not in parts and "O" not in parts:
|
||||
return None
|
||||
|
||||
# Find section, size, and name
|
||||
for i, part in enumerate(parts):
|
||||
if part.startswith("."):
|
||||
section = _map_section_name(part)
|
||||
if section and i + 1 < len(parts):
|
||||
try:
|
||||
size = int(parts[i + 1], 16)
|
||||
if i + 2 < len(parts) and size > 0:
|
||||
name = " ".join(parts[i + 2 :])
|
||||
return (section, name, size, address)
|
||||
except ValueError:
|
||||
pass
|
||||
break
|
||||
return None
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.objdump_path, "-t", str(self.elf_path)],
|
||||
@@ -234,13 +181,17 @@ class MemoryAnalyzer:
|
||||
seen_addresses: set[str] = set()
|
||||
|
||||
for line in result.stdout.splitlines():
|
||||
symbol_info = parse_symbol_line(line)
|
||||
if symbol_info:
|
||||
section, name, size, address = symbol_info
|
||||
# Skip duplicate symbols at the same address (e.g., C1/C2 constructors)
|
||||
if address not in seen_addresses and section in self.sections:
|
||||
self.sections[section].symbols.append((name, size, ""))
|
||||
seen_addresses.add(address)
|
||||
if not (symbol_info := parse_symbol_line(line)):
|
||||
continue
|
||||
|
||||
section, name, size, address = symbol_info
|
||||
|
||||
# Skip duplicate symbols at the same address (e.g., C1/C2 constructors)
|
||||
if address in seen_addresses or section not in self.sections:
|
||||
continue
|
||||
|
||||
self.sections[section].symbols.append((name, size, ""))
|
||||
seen_addresses.add(address)
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
_LOGGER.error("Failed to parse symbols: %s", e)
|
||||
|
Reference in New Issue
Block a user