mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-29 22:24:26 +00:00 
			
		
		
		
	esp32 only platforms
This commit is contained in:
		| @@ -27,6 +27,12 @@ if TYPE_CHECKING: | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| # GCC global constructor/destructor prefix annotations | ||||
| _GCC_PREFIX_ANNOTATIONS = { | ||||
|     "_GLOBAL__sub_I_": "global constructor for", | ||||
|     "_GLOBAL__sub_D_": "global destructor for", | ||||
| } | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class MemorySection: | ||||
| @@ -340,66 +346,116 @@ class MemoryAnalyzer: | ||||
|                 text=True, | ||||
|                 check=False, | ||||
|             ) | ||||
|             if result.returncode == 0: | ||||
|                 demangled_lines = result.stdout.strip().split("\n") | ||||
|                 # Map original to demangled names | ||||
|                 failed_count = 0 | ||||
|                 for original, stripped, prefix, demangled in zip( | ||||
|                     symbols, symbols_stripped, symbols_prefixes, demangled_lines | ||||
|                 ): | ||||
|                     # Add back any prefix that was removed | ||||
|                     if prefix: | ||||
|                         if demangled != stripped: | ||||
|                             # Successfully demangled - add descriptive prefix | ||||
|                             if prefix == "_GLOBAL__sub_I_": | ||||
|                                 demangled = f"[global constructor for: {demangled}]" | ||||
|                             elif prefix == "_GLOBAL__sub_D_": | ||||
|                                 demangled = f"[global destructor for: {demangled}]" | ||||
|                         else: | ||||
|                             # Failed to demangle - restore original prefix | ||||
|                             demangled = prefix + demangled | ||||
|         except (subprocess.SubprocessError, OSError, UnicodeDecodeError) as e: | ||||
|             # On error, cache originals | ||||
|             _LOGGER.warning("Failed to batch demangle symbols: %s", e) | ||||
|             for symbol in symbols: | ||||
|                 self._demangle_cache[symbol] = symbol | ||||
|             return | ||||
|  | ||||
|                     # If we stripped a suffix, add it back to the demangled name for clarity | ||||
|                     if original != stripped and not prefix: | ||||
|                         # Find what was stripped | ||||
|                         suffix_match = re.search( | ||||
|                             r"(\$(?:isra|part|constprop)\$\d+)", original | ||||
|                         ) | ||||
|                         if suffix_match: | ||||
|                             demangled = f"{demangled} [{suffix_match.group(1)}]" | ||||
|  | ||||
|                     self._demangle_cache[original] = demangled | ||||
|  | ||||
|                     # Log symbols that failed to demangle (stayed the same as stripped version) | ||||
|                     if stripped == demangled and stripped.startswith("_Z"): | ||||
|                         failed_count += 1 | ||||
|                         if failed_count <= 5:  # Only log first 5 failures | ||||
|                             _LOGGER.warning("Failed to demangle: %s", original[:100]) | ||||
|  | ||||
|                 if failed_count > 0: | ||||
|                     _LOGGER.warning( | ||||
|                         "Failed to demangle %d/%d symbols using %s", | ||||
|                         failed_count, | ||||
|                         len(symbols), | ||||
|                         cppfilt_cmd, | ||||
|                     ) | ||||
|                 else: | ||||
|                     _LOGGER.warning( | ||||
|                         "Successfully demangled all %d symbols", len(symbols) | ||||
|                     ) | ||||
|                 return | ||||
|         if result.returncode != 0: | ||||
|             _LOGGER.warning( | ||||
|                 "c++filt exited with code %d: %s", | ||||
|                 result.returncode, | ||||
|                 result.stderr[:200] if result.stderr else "(no error output)", | ||||
|             ) | ||||
|         except (subprocess.SubprocessError, OSError, UnicodeDecodeError) as e: | ||||
|             # On error, cache originals | ||||
|             _LOGGER.warning("Failed to batch demangle symbols: %s", e) | ||||
|             # Cache originals on failure | ||||
|             for symbol in symbols: | ||||
|                 self._demangle_cache[symbol] = symbol | ||||
|             return | ||||
|  | ||||
|         # If demangling failed, cache originals | ||||
|         for symbol in symbols: | ||||
|             self._demangle_cache[symbol] = symbol | ||||
|         # Process demangled output | ||||
|         self._process_demangled_output( | ||||
|             symbols, symbols_stripped, symbols_prefixes, result.stdout, cppfilt_cmd | ||||
|         ) | ||||
|  | ||||
|     def _process_demangled_output( | ||||
|         self, | ||||
|         symbols: list[str], | ||||
|         symbols_stripped: list[str], | ||||
|         symbols_prefixes: list[str], | ||||
|         demangled_output: str, | ||||
|         cppfilt_cmd: str, | ||||
|     ) -> None: | ||||
|         """Process demangled symbol output and populate cache. | ||||
|  | ||||
|         Args: | ||||
|             symbols: Original symbol names | ||||
|             symbols_stripped: Stripped symbol names sent to c++filt | ||||
|             symbols_prefixes: Removed prefixes to restore | ||||
|             demangled_output: Output from c++filt | ||||
|             cppfilt_cmd: Path to c++filt command (for logging) | ||||
|         """ | ||||
|         demangled_lines = demangled_output.strip().split("\n") | ||||
|         failed_count = 0 | ||||
|  | ||||
|         for original, stripped, prefix, demangled in zip( | ||||
|             symbols, symbols_stripped, symbols_prefixes, demangled_lines | ||||
|         ): | ||||
|             # Add back any prefix that was removed | ||||
|             demangled = self._restore_symbol_prefix(prefix, stripped, demangled) | ||||
|  | ||||
|             # If we stripped a suffix, add it back to the demangled name for clarity | ||||
|             if original != stripped and not prefix: | ||||
|                 demangled = self._restore_symbol_suffix(original, demangled) | ||||
|  | ||||
|             self._demangle_cache[original] = demangled | ||||
|  | ||||
|             # Log symbols that failed to demangle (stayed the same as stripped version) | ||||
|             if stripped == demangled and stripped.startswith("_Z"): | ||||
|                 failed_count += 1 | ||||
|                 if failed_count <= 5:  # Only log first 5 failures | ||||
|                     _LOGGER.warning("Failed to demangle: %s", original[:100]) | ||||
|  | ||||
|         if failed_count > 0: | ||||
|             _LOGGER.warning( | ||||
|                 "Failed to demangle %d/%d symbols using %s", | ||||
|                 failed_count, | ||||
|                 len(symbols), | ||||
|                 cppfilt_cmd, | ||||
|             ) | ||||
|         else: | ||||
|             _LOGGER.warning("Successfully demangled all %d symbols", len(symbols)) | ||||
|  | ||||
|     @staticmethod | ||||
|     def _restore_symbol_prefix(prefix: str, stripped: str, demangled: str) -> str: | ||||
|         """Restore prefix that was removed before demangling. | ||||
|  | ||||
|         Args: | ||||
|             prefix: Prefix that was removed (e.g., "_GLOBAL__sub_I_") | ||||
|             stripped: Stripped symbol name | ||||
|             demangled: Demangled symbol name | ||||
|  | ||||
|         Returns: | ||||
|             Demangled name with prefix restored/annotated | ||||
|         """ | ||||
|         if not prefix: | ||||
|             return demangled | ||||
|  | ||||
|         # Successfully demangled - add descriptive prefix | ||||
|         if demangled != stripped and ( | ||||
|             annotation := _GCC_PREFIX_ANNOTATIONS.get(prefix) | ||||
|         ): | ||||
|             return f"[{annotation}: {demangled}]" | ||||
|  | ||||
|         # Failed to demangle - restore original prefix | ||||
|         return prefix + demangled | ||||
|  | ||||
|     @staticmethod | ||||
|     def _restore_symbol_suffix(original: str, demangled: str) -> str: | ||||
|         """Restore GCC optimization suffix that was removed before demangling. | ||||
|  | ||||
|         Args: | ||||
|             original: Original symbol name with suffix | ||||
|             demangled: Demangled symbol name without suffix | ||||
|  | ||||
|         Returns: | ||||
|             Demangled name with suffix annotation | ||||
|         """ | ||||
|         suffix_match = re.search(r"(\$(?:isra|part|constprop)\$\d+)", original) | ||||
|         if suffix_match: | ||||
|             return f"{demangled} [{suffix_match.group(1)}]" | ||||
|         return demangled | ||||
|  | ||||
|     def _demangle_symbol(self, symbol: str) -> str: | ||||
|         """Get demangled C++ symbol name from cache.""" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user