mirror of
https://github.com/esphome/esphome.git
synced 2025-08-07 19:07:45 +00:00
wip
This commit is contained in:
parent
f3523a96c9
commit
6f05ee7427
@ -593,7 +593,7 @@ class MemoryAnalyzer:
|
|||||||
self._categorize_symbols()
|
self._categorize_symbols()
|
||||||
return dict(self.components)
|
return dict(self.components)
|
||||||
|
|
||||||
def _parse_sections(self):
|
def _parse_sections(self) -> None:
|
||||||
"""Parse section headers from ELF file."""
|
"""Parse section headers from ELF file."""
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
@ -637,8 +637,59 @@ class MemoryAnalyzer:
|
|||||||
_LOGGER.error(f"Failed to parse sections: {e}")
|
_LOGGER.error(f"Failed to parse sections: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _parse_symbols(self):
|
def _parse_symbols(self) -> None:
|
||||||
"""Parse symbols from ELF file."""
|
"""Parse symbols from ELF file."""
|
||||||
|
# Section mapping - centralizes the logic
|
||||||
|
SECTION_MAPPING = {
|
||||||
|
".text": [".text", ".iram"],
|
||||||
|
".rodata": [".rodata"],
|
||||||
|
".data": [".data", ".dram"],
|
||||||
|
".bss": [".bss"],
|
||||||
|
}
|
||||||
|
|
||||||
|
def map_section_name(raw_section: str) -> str | None:
|
||||||
|
"""Map raw section name to standard section."""
|
||||||
|
for standard_section, patterns in SECTION_MAPPING.items():
|
||||||
|
if any(pattern in raw_section for pattern in patterns):
|
||||||
|
return standard_section
|
||||||
|
return None
|
||||||
|
|
||||||
|
def parse_symbol_line(line: str) -> tuple[str, str, int] | None:
|
||||||
|
"""Parse a single symbol line from objdump output.
|
||||||
|
|
||||||
|
Returns (section, name, size) 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 address
|
||||||
|
int(parts[0], 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)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
break
|
||||||
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
[self.objdump_path, "-t", str(self.elf_path)],
|
[self.objdump_path, "-t", str(self.elf_path)],
|
||||||
@ -648,60 +699,17 @@ class MemoryAnalyzer:
|
|||||||
)
|
)
|
||||||
|
|
||||||
for line in result.stdout.splitlines():
|
for line in result.stdout.splitlines():
|
||||||
# Parse symbol table entries
|
symbol_info = parse_symbol_line(line)
|
||||||
# Format: address l/g w/d F/O section size name
|
if symbol_info:
|
||||||
# Example: 40084870 l F .iram0.text 00000000 _xt_user_exc
|
section, name, size = symbol_info
|
||||||
parts = line.split()
|
if section in self.sections:
|
||||||
if len(parts) >= 5:
|
self.sections[section].symbols.append((name, size, ""))
|
||||||
try:
|
|
||||||
# Check if this looks like a symbol entry
|
|
||||||
int(parts[0], 16)
|
|
||||||
|
|
||||||
# Look for F (function) or O (object) flag
|
|
||||||
if "F" in parts or "O" in parts:
|
|
||||||
# Find the section name
|
|
||||||
section = None
|
|
||||||
size = 0
|
|
||||||
name = None
|
|
||||||
|
|
||||||
for i, part in enumerate(parts):
|
|
||||||
if part.startswith("."):
|
|
||||||
# Map section names
|
|
||||||
if ".text" in part or ".iram" in part:
|
|
||||||
section = ".text"
|
|
||||||
elif ".rodata" in part:
|
|
||||||
section = ".rodata"
|
|
||||||
elif ".data" in part or ".dram" in part:
|
|
||||||
section = ".data"
|
|
||||||
elif ".bss" in part:
|
|
||||||
section = ".bss"
|
|
||||||
|
|
||||||
if section and i + 1 < len(parts):
|
|
||||||
try:
|
|
||||||
# Next field should be size
|
|
||||||
size = int(parts[i + 1], 16)
|
|
||||||
# Rest is the symbol name
|
|
||||||
if i + 2 < len(parts):
|
|
||||||
name = " ".join(parts[i + 2 :])
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
break
|
|
||||||
|
|
||||||
if section and name and size > 0:
|
|
||||||
if section in self.sections:
|
|
||||||
self.sections[section].symbols.append(
|
|
||||||
(name, size, "")
|
|
||||||
)
|
|
||||||
|
|
||||||
except ValueError:
|
|
||||||
# Not a valid address, skip
|
|
||||||
continue
|
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
_LOGGER.error(f"Failed to parse symbols: {e}")
|
_LOGGER.error(f"Failed to parse symbols: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _categorize_symbols(self):
|
def _categorize_symbols(self) -> None:
|
||||||
"""Categorize symbols by component."""
|
"""Categorize symbols by component."""
|
||||||
# First, collect all unique symbol names for batch demangling
|
# First, collect all unique symbol names for batch demangling
|
||||||
all_symbols = set()
|
all_symbols = set()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user