mirror of
https://github.com/esphome/esphome.git
synced 2025-08-06 18:37:47 +00:00
wip
This commit is contained in:
parent
40d9c0a3db
commit
1f361b07d1
@ -12,6 +12,397 @@ _LOGGER = logging.getLogger(__name__)
|
||||
# Pattern to extract ESPHome component namespaces dynamically
|
||||
ESPHOME_COMPONENT_PATTERN = re.compile(r"esphome::([a-zA-Z0-9_]+)::")
|
||||
|
||||
# Component identification rules
|
||||
# Symbol patterns: patterns found in raw symbol names
|
||||
SYMBOL_PATTERNS = {
|
||||
"freertos": [
|
||||
"vTask",
|
||||
"xTask",
|
||||
"xQueue",
|
||||
"pvPort",
|
||||
"vPort",
|
||||
"uxTask",
|
||||
"pcTask",
|
||||
"prvTimerTask",
|
||||
"prvAddNewTaskToReadyList",
|
||||
"pxReadyTasksLists",
|
||||
],
|
||||
"xtensa": ["xt_", "_xt_"],
|
||||
"heap": ["heap_", "multi_heap"],
|
||||
"spi_flash": ["spi_flash"],
|
||||
"rtc": ["rtc_"],
|
||||
"gpio_driver": ["gpio_", "pins"],
|
||||
"uart_driver": ["uart", "_uart", "UART"],
|
||||
"timer": ["timer_", "esp_timer"],
|
||||
"peripherals": ["periph_", "periman"],
|
||||
"network_stack": [
|
||||
"vj_compress",
|
||||
"raw_sendto",
|
||||
"raw_input",
|
||||
"etharp_",
|
||||
"icmp_input",
|
||||
"socket_ipv6",
|
||||
"ip_napt",
|
||||
],
|
||||
"ipv6_stack": ["nd6_", "ip6_", "mld6_"],
|
||||
"wifi_stack": [
|
||||
"ieee80211",
|
||||
"hostap",
|
||||
"sta_",
|
||||
"ap_",
|
||||
"scan_",
|
||||
"wifi_",
|
||||
"wpa_",
|
||||
"wps_",
|
||||
"esp_wifi",
|
||||
"cnx_",
|
||||
"wpa3_",
|
||||
"sae_",
|
||||
"wDev_",
|
||||
"ic_",
|
||||
"mac_",
|
||||
"esf_buf",
|
||||
"gWpaSm",
|
||||
"sm_WPA",
|
||||
"eapol_",
|
||||
"owe_",
|
||||
],
|
||||
"bluetooth": ["bt_", "ble_", "l2c_", "gatt_", "gap_", "hci_", "BT_init"],
|
||||
"wifi_bt_coex": ["coex"],
|
||||
"bluetooth_rom": ["r_ble", "r_lld", "r_llc", "r_llm"],
|
||||
"bluedroid_bt": ["bluedroid", "btc_", "bta_", "btm_", "btu_"],
|
||||
"crypto_math": [
|
||||
"ecp_",
|
||||
"bignum_",
|
||||
"mpi_",
|
||||
"sswu",
|
||||
"modp",
|
||||
"dragonfly_",
|
||||
"gcm_mult",
|
||||
"__multiply",
|
||||
],
|
||||
"hw_crypto": ["esp_aes", "esp_sha", "esp_rsa", "esp_bignum", "esp_mpi"],
|
||||
"libc": [
|
||||
"printf",
|
||||
"scanf",
|
||||
"malloc",
|
||||
"free",
|
||||
"memcpy",
|
||||
"memset",
|
||||
"strcpy",
|
||||
"strlen",
|
||||
"_dtoa",
|
||||
"_fopen",
|
||||
"__sfvwrite_r",
|
||||
"qsort",
|
||||
],
|
||||
"string_ops": ["strcmp", "strncmp", "strchr", "strstr", "strtok", "strdup"],
|
||||
"memory_alloc": ["malloc", "calloc", "realloc", "free", "_sbrk"],
|
||||
"file_io": ["fread", "fwrite", "fopen", "fclose", "fseek", "ftell", "fflush"],
|
||||
"string_formatting": [
|
||||
"snprintf",
|
||||
"vsnprintf",
|
||||
"sprintf",
|
||||
"vsprintf",
|
||||
"sscanf",
|
||||
"vsscanf",
|
||||
],
|
||||
"cpp_anonymous": ["_GLOBAL__N_"],
|
||||
"cpp_runtime": ["__cxx", "_ZN", "_ZL", "_ZSt", "__gxx_personality"],
|
||||
"exception_handling": ["__cxa_", "_Unwind_", "__gcc_personality", "uw_frame_state"],
|
||||
"static_init": ["_GLOBAL__sub_I_"],
|
||||
"mdns_lib": ["mdns"],
|
||||
"phy_radio": [
|
||||
"phy_",
|
||||
"rf_",
|
||||
"chip_",
|
||||
"register_chipv7",
|
||||
"pbus_",
|
||||
"bb_",
|
||||
"fe_",
|
||||
"rfcal_",
|
||||
"ram_rfcal",
|
||||
"tx_pwctrl",
|
||||
"rx_chan",
|
||||
"set_rx_gain",
|
||||
"set_chan",
|
||||
"agc_reg",
|
||||
"ram_txiq",
|
||||
"ram_txdc",
|
||||
"ram_gen_rx_gain",
|
||||
],
|
||||
"wifi_phy_pp": ["pp_", "ppT", "ppR", "ppP", "ppInstall", "ppCalTxAMPDULength"],
|
||||
"wifi_lmac": ["lmac"],
|
||||
"wifi_device": ["wdev", "wDev_"],
|
||||
"power_mgmt": [
|
||||
"pm_",
|
||||
"sleep",
|
||||
"rtc_sleep",
|
||||
"light_sleep",
|
||||
"deep_sleep",
|
||||
"power_down",
|
||||
"g_pm",
|
||||
],
|
||||
"memory_mgmt": ["mem_", "memory_", "tlsf_", "memp_"],
|
||||
"hal_layer": ["hal_"],
|
||||
"clock_mgmt": [
|
||||
"clk_",
|
||||
"clock_",
|
||||
"rtc_clk",
|
||||
"apb_",
|
||||
"cpu_freq",
|
||||
"setCpuFrequencyMhz",
|
||||
],
|
||||
"cache_mgmt": ["cache"],
|
||||
"flash_ops": ["flash", "image_load"],
|
||||
"interrupt_handlers": [
|
||||
"isr",
|
||||
"interrupt",
|
||||
"intr_",
|
||||
"exc_",
|
||||
"exception",
|
||||
"port_IntStack",
|
||||
],
|
||||
"wrapper_functions": ["_wrapper"],
|
||||
"error_handling": ["panic", "abort", "assert", "error_", "fault"],
|
||||
"authentication": ["auth"],
|
||||
"ppp_protocol": ["ppp", "ipcp_", "lcp_", "chap_"],
|
||||
"dhcp": ["dhcp", "handle_dhcp"],
|
||||
"ethernet_phy": [
|
||||
"emac_",
|
||||
"eth_phy_",
|
||||
"phy_tlk110",
|
||||
"phy_lan87",
|
||||
"phy_ip101",
|
||||
"phy_rtl",
|
||||
"phy_dp83",
|
||||
"phy_ksz",
|
||||
],
|
||||
"threading": ["pthread_", "thread_", "_task_"],
|
||||
"pthread": ["pthread"],
|
||||
"synchronization": ["mutex", "semaphore", "spinlock", "portMUX"],
|
||||
"math_lib": [
|
||||
"sin",
|
||||
"cos",
|
||||
"tan",
|
||||
"sqrt",
|
||||
"pow",
|
||||
"exp",
|
||||
"log",
|
||||
"atan",
|
||||
"asin",
|
||||
"acos",
|
||||
"floor",
|
||||
"ceil",
|
||||
"fabs",
|
||||
"round",
|
||||
],
|
||||
"random": ["rand", "random", "rng_", "prng"],
|
||||
"time_lib": [
|
||||
"time",
|
||||
"clock",
|
||||
"gettimeofday",
|
||||
"settimeofday",
|
||||
"localtime",
|
||||
"gmtime",
|
||||
"mktime",
|
||||
"strftime",
|
||||
],
|
||||
"console_io": ["console_", "uart_tx", "uart_rx", "puts", "putchar", "getchar"],
|
||||
"rom_functions": ["r_", "rom_"],
|
||||
"compiler_runtime": [
|
||||
"__divdi3",
|
||||
"__udivdi3",
|
||||
"__moddi3",
|
||||
"__muldi3",
|
||||
"__ashldi3",
|
||||
"__ashrdi3",
|
||||
"__lshrdi3",
|
||||
"__cmpdi2",
|
||||
"__fixdfdi",
|
||||
"__floatdidf",
|
||||
],
|
||||
"libgcc": ["libgcc", "_divdi3", "_udivdi3"],
|
||||
"boot_startup": ["boot", "start_cpu", "call_start", "startup", "bootloader"],
|
||||
"bootloader": ["bootloader_", "esp_bootloader"],
|
||||
"app_framework": ["app_", "initArduino", "setup", "loop"],
|
||||
"weak_symbols": ["__weak_"],
|
||||
"compiler_builtins": ["__builtin_"],
|
||||
"vfs": ["vfs_", "VFS"],
|
||||
"esp32_sdk": ["esp32_", "esp32c", "esp32s"],
|
||||
"usb": ["usb_", "USB", "cdc_", "CDC"],
|
||||
"i2c_driver": ["i2c_", "I2C"],
|
||||
"i2s_driver": ["i2s_", "I2S"],
|
||||
"spi_driver": ["spi_", "SPI"],
|
||||
"adc_driver": ["adc_", "ADC"],
|
||||
"dac_driver": ["dac_", "DAC"],
|
||||
"touch_driver": ["touch_", "TOUCH"],
|
||||
"pwm_driver": ["pwm_", "PWM", "ledc_", "LEDC"],
|
||||
"rmt_driver": ["rmt_", "RMT"],
|
||||
"pcnt_driver": ["pcnt_", "PCNT"],
|
||||
"can_driver": ["can_", "CAN", "twai_", "TWAI"],
|
||||
"sdmmc_driver": ["sdmmc_", "SDMMC", "sdcard", "sd_card"],
|
||||
"temp_sensor": ["temp_sensor", "tsens_"],
|
||||
"watchdog": ["wdt_", "WDT", "watchdog"],
|
||||
"brownout": ["brownout", "bod_"],
|
||||
"ulp": ["ulp_", "ULP"],
|
||||
"psram": ["psram", "PSRAM", "spiram", "SPIRAM"],
|
||||
"efuse": ["efuse", "EFUSE"],
|
||||
"partition": ["partition", "esp_partition"],
|
||||
"esp_event": ["esp_event", "event_loop", "event_callback"],
|
||||
"esp_console": ["esp_console", "console_"],
|
||||
"chip_specific": ["chip_", "esp_chip"],
|
||||
"esp_system_utils": ["esp_system", "esp_hw", "esp_clk", "esp_sleep"],
|
||||
"ipc": ["esp_ipc", "ipc_"],
|
||||
"wifi_config": [
|
||||
"g_cnxMgr",
|
||||
"gChmCxt",
|
||||
"g_ic",
|
||||
"TxRxCxt",
|
||||
"s_dp",
|
||||
"s_ni",
|
||||
"s_reg_dump",
|
||||
"packet$",
|
||||
"d_mult_table",
|
||||
"K",
|
||||
"fcstab",
|
||||
],
|
||||
"smartconfig": ["sc_ack_send"],
|
||||
"rc_calibration": ["rc_cal", "rcUpdate"],
|
||||
"noise_floor": ["noise_check"],
|
||||
"rf_calibration": [
|
||||
"set_rx_sense",
|
||||
"set_rx_gain_cal",
|
||||
"set_chan_dig_gain",
|
||||
"tx_pwctrl_init_cal",
|
||||
"rfcal_txiq",
|
||||
"set_tx_gain_table",
|
||||
"correct_rfpll_offset",
|
||||
"pll_correct_dcap",
|
||||
"txiq_cal_init",
|
||||
"pwdet_sar",
|
||||
"rx_11b_opt",
|
||||
],
|
||||
"wifi_crypto": [
|
||||
"pk_use_ecparams",
|
||||
"process_segments",
|
||||
"ccmp_",
|
||||
"rc4_",
|
||||
"aria_",
|
||||
"mgf_mask",
|
||||
"dh_group",
|
||||
],
|
||||
"radio_control": ["fsm_input", "fsm_sconfreq"],
|
||||
"pbuf": [
|
||||
"pbuf_",
|
||||
"ppSearchTxframe",
|
||||
"ppMapWaitTxq",
|
||||
"ppFillAMPDUBar",
|
||||
"ppCheckTxConnTrafficIdle",
|
||||
],
|
||||
"ppTask": ["ppCalTkipMic"],
|
||||
"event_group": ["xEventGroup"],
|
||||
"ringbuffer": ["xRingbuffer", "prvSend", "prvReceive", "prvCopy"],
|
||||
"provisioning": ["prov_"],
|
||||
"scan": ["gScanStruct"],
|
||||
"port": ["xPort"],
|
||||
"elf_loader": ["elf_add", "process_image", "read_encoded"],
|
||||
"socket_api": [
|
||||
"sockets",
|
||||
"netconn_",
|
||||
"accept_function",
|
||||
"recv_raw",
|
||||
"socket_ipv4_multicast",
|
||||
"socket_ipv6_multicast",
|
||||
],
|
||||
"igmp": ["igmp_"],
|
||||
"icmp6": ["icmp6_"],
|
||||
"arp": ["arp_table"],
|
||||
"ampdu": ["ampdu_", "rcAmpdu", "trc_onAmpduOp"],
|
||||
"ieee802_11": ["ieee802_11_"],
|
||||
"rate_control": ["rssi_margin", "rcGetSched", "get_rate_fcc_index"],
|
||||
"nan": ["nan_dp_"],
|
||||
"channel_mgmt": ["chm_init", "chm_set_current_channel"],
|
||||
"trace": ["trc_init"],
|
||||
"country_code": ["country_info"],
|
||||
"multicore": ["do_multicore_settings"],
|
||||
"Update_lib": ["Update"],
|
||||
"stdio": [
|
||||
"__sf",
|
||||
"__sflush_r",
|
||||
"__srefill_r",
|
||||
"_impure_data",
|
||||
"_reclaim_reent",
|
||||
"_open_r",
|
||||
],
|
||||
"strncpy_ops": ["strncpy"],
|
||||
"math_internal": ["__mdiff", "__lshift", "__mprec_tens", "quorem"],
|
||||
"character_class": ["__chclass"],
|
||||
"camellia": ["camellia_"],
|
||||
"crypto_tables": ["FSb", "FSb2", "FSb3", "FSb4"],
|
||||
"event_buffer": ["g_eb_list_desc", "eb_space"],
|
||||
"base_node": ["base_node_"],
|
||||
"file_descriptor": ["s_fd_table"],
|
||||
"tx_delay": ["tx_delay_cfg"],
|
||||
"deinit": ["deinit_functions"],
|
||||
"lcp_echo": ["LcpEchoCheck"],
|
||||
"raw_api": ["raw_bind", "raw_connect"],
|
||||
}
|
||||
|
||||
# Demangled patterns: patterns found in demangled C++ names
|
||||
DEMANGLED_PATTERNS = {
|
||||
"gpio_driver": ["GPIO"],
|
||||
"uart_driver": ["UART"],
|
||||
"network_stack": [
|
||||
"lwip",
|
||||
"tcp",
|
||||
"udp",
|
||||
"ip4",
|
||||
"ip6",
|
||||
"dhcp",
|
||||
"dns",
|
||||
"netif",
|
||||
"ethernet",
|
||||
"ppp",
|
||||
"slip",
|
||||
],
|
||||
"wifi_stack": ["NetworkInterface"],
|
||||
"nimble_bt": [
|
||||
"nimble",
|
||||
"NimBLE",
|
||||
"ble_hs",
|
||||
"ble_gap",
|
||||
"ble_gatt",
|
||||
"ble_att",
|
||||
"ble_l2cap",
|
||||
"ble_sm",
|
||||
],
|
||||
"crypto": ["mbedtls", "crypto", "sha", "aes", "rsa", "ecc", "tls", "ssl"],
|
||||
"cpp_stdlib": ["std::", "__gnu_cxx::", "__cxxabiv"],
|
||||
"static_init": ["__static_initialization"],
|
||||
"rtti": ["__type_info", "__class_type_info"],
|
||||
"web_server_lib": ["AsyncWebServer", "AsyncWebHandler", "WebServer"],
|
||||
"async_tcp": ["AsyncClient", "AsyncServer"],
|
||||
"mdns_lib": ["mdns"],
|
||||
"json_lib": [
|
||||
"ArduinoJson",
|
||||
"JsonDocument",
|
||||
"JsonArray",
|
||||
"JsonObject",
|
||||
"deserialize",
|
||||
"serialize",
|
||||
],
|
||||
"http_lib": ["HTTP", "http_", "Request", "Response", "Uri", "WebSocket"],
|
||||
"logging": ["log", "Log", "print", "Print", "diag_"],
|
||||
"authentication": ["checkDigestAuthentication"],
|
||||
"libgcc": ["libgcc"],
|
||||
"esp_system": ["esp_", "ESP"],
|
||||
"arduino": ["arduino"],
|
||||
"nvs": ["nvs_"],
|
||||
"filesystem": ["spiffs", "vfs"],
|
||||
"libc": ["newlib"],
|
||||
}
|
||||
|
||||
|
||||
# Get the list of actual ESPHome components by scanning the components directory
|
||||
def get_esphome_components():
|
||||
@ -88,6 +479,7 @@ class MemoryAnalyzer:
|
||||
lambda: ComponentMemory("")
|
||||
)
|
||||
self._demangle_cache: dict[str, str] = {}
|
||||
self._uncategorized_symbols: list[tuple[str, str, int]] = []
|
||||
|
||||
def analyze(self) -> dict[str, ComponentMemory]:
|
||||
"""Analyze the ELF file and return component memory usage."""
|
||||
@ -235,13 +627,17 @@ class MemoryAnalyzer:
|
||||
elif section_name == ".bss":
|
||||
comp_mem.bss_size += size
|
||||
|
||||
# Track uncategorized symbols
|
||||
if component == "other" and size > 0:
|
||||
demangled = self._demangle_symbol(symbol_name)
|
||||
self._uncategorized_symbols.append((symbol_name, demangled, size))
|
||||
|
||||
def _identify_component(self, symbol_name: str) -> str:
|
||||
"""Identify which component a symbol belongs to."""
|
||||
# Demangle C++ names if needed
|
||||
demangled = self._demangle_symbol(symbol_name)
|
||||
|
||||
# Check for ESPHome component namespaces dynamically
|
||||
# Pattern: esphome::component_name:: (with trailing ::)
|
||||
# Check for ESPHome component namespaces first
|
||||
match = ESPHOME_COMPONENT_PATTERN.search(demangled)
|
||||
if match:
|
||||
component_name = match.group(1)
|
||||
@ -255,448 +651,64 @@ class MemoryAnalyzer:
|
||||
return "[esphome]core"
|
||||
|
||||
# Check for esphome core namespace (no component namespace)
|
||||
# This catches esphome::ClassName or esphome::function_name
|
||||
if "esphome::" in demangled:
|
||||
return "[esphome]core"
|
||||
|
||||
# Check for web server related code
|
||||
# Check against symbol patterns
|
||||
for component, patterns in SYMBOL_PATTERNS.items():
|
||||
if any(pattern in symbol_name for pattern in patterns):
|
||||
return component
|
||||
|
||||
# Check against demangled patterns
|
||||
for component, patterns in DEMANGLED_PATTERNS.items():
|
||||
if any(pattern in demangled for pattern in patterns):
|
||||
return component
|
||||
|
||||
# Special cases that need more complex logic
|
||||
|
||||
# ROM functions starting with r_ or rom_
|
||||
if symbol_name.startswith("r_") or symbol_name.startswith("rom_"):
|
||||
return "rom_functions"
|
||||
|
||||
# Math functions with short names
|
||||
if len(symbol_name) < 20 and symbol_name in [
|
||||
"sin",
|
||||
"cos",
|
||||
"tan",
|
||||
"sqrt",
|
||||
"pow",
|
||||
"exp",
|
||||
"log",
|
||||
"atan",
|
||||
"asin",
|
||||
"acos",
|
||||
"floor",
|
||||
"ceil",
|
||||
"fabs",
|
||||
"round",
|
||||
]:
|
||||
return "math_lib"
|
||||
|
||||
# Check if spi_flash vs spi_driver
|
||||
if "spi_" in symbol_name or "SPI" in symbol_name:
|
||||
if "spi_flash" in symbol_name:
|
||||
return "spi_flash"
|
||||
else:
|
||||
return "spi_driver"
|
||||
|
||||
# ESP OTA framework (exclude esphome OTA)
|
||||
if (
|
||||
"AsyncWebServer" in demangled
|
||||
or "AsyncWebHandler" in demangled
|
||||
or "WebServer" in demangled
|
||||
):
|
||||
return "web_server_lib"
|
||||
elif "AsyncClient" in demangled or "AsyncServer" in demangled:
|
||||
return "async_tcp"
|
||||
|
||||
# Check for FreeRTOS/ESP-IDF components
|
||||
if any(
|
||||
prefix in symbol_name
|
||||
for prefix in [
|
||||
"vTask",
|
||||
"xTask",
|
||||
"xQueue",
|
||||
"pvPort",
|
||||
"vPort",
|
||||
"uxTask",
|
||||
"pcTask",
|
||||
]
|
||||
):
|
||||
return "freertos"
|
||||
elif "xt_" in symbol_name or "_xt_" in symbol_name:
|
||||
return "xtensa"
|
||||
elif "heap_" in symbol_name or "multi_heap" in demangled:
|
||||
return "heap"
|
||||
elif "spi_flash" in symbol_name:
|
||||
return "spi_flash"
|
||||
elif "rtc_" in symbol_name:
|
||||
return "rtc"
|
||||
elif "gpio_" in symbol_name or "GPIO" in demangled:
|
||||
return "gpio_driver"
|
||||
elif "uart_" in symbol_name or "UART" in demangled:
|
||||
return "uart_driver"
|
||||
elif "timer_" in symbol_name or "esp_timer" in symbol_name:
|
||||
return "timer"
|
||||
elif "periph_" in symbol_name:
|
||||
return "peripherals"
|
||||
|
||||
# C++ standard library
|
||||
if any(ns in demangled for ns in ["std::", "__gnu_cxx::", "__cxxabiv"]):
|
||||
return "cpp_stdlib"
|
||||
elif "_GLOBAL__N_" in symbol_name:
|
||||
return "cpp_anonymous"
|
||||
|
||||
# Platform/system code
|
||||
if "esp_" in demangled or "ESP" in demangled:
|
||||
return "esp_system"
|
||||
elif "app_" in symbol_name:
|
||||
return "app_framework"
|
||||
elif "arduino" in demangled.lower():
|
||||
return "arduino"
|
||||
|
||||
# Network stack components
|
||||
if any(
|
||||
net in demangled
|
||||
for net in [
|
||||
"lwip",
|
||||
"tcp",
|
||||
"udp",
|
||||
"ip4",
|
||||
"ip6",
|
||||
"dhcp",
|
||||
"dns",
|
||||
"netif",
|
||||
"ethernet",
|
||||
"ppp",
|
||||
"slip",
|
||||
]
|
||||
):
|
||||
return "network_stack"
|
||||
elif "vj_compress" in symbol_name: # Van Jacobson TCP compression
|
||||
return "network_stack"
|
||||
|
||||
# WiFi/802.11 stack
|
||||
if any(
|
||||
wifi in symbol_name
|
||||
for wifi in [
|
||||
"ieee80211",
|
||||
"hostap",
|
||||
"sta_",
|
||||
"ap_",
|
||||
"scan_",
|
||||
"wifi_",
|
||||
"wpa_",
|
||||
"wps_",
|
||||
"esp_wifi",
|
||||
]
|
||||
):
|
||||
return "wifi_stack"
|
||||
elif "NetworkInterface" in demangled:
|
||||
return "wifi_stack"
|
||||
|
||||
# mDNS specific
|
||||
if (
|
||||
"mdns" in symbol_name or "mdns" in demangled
|
||||
"esp_ota" in symbol_name or "ota_" in symbol_name
|
||||
) and "esphome" not in demangled:
|
||||
return "mdns_lib"
|
||||
return "esp_ota"
|
||||
|
||||
# Cryptography
|
||||
if any(
|
||||
crypto in demangled
|
||||
for crypto in [
|
||||
"mbedtls",
|
||||
"crypto",
|
||||
"sha",
|
||||
"aes",
|
||||
"rsa",
|
||||
"ecc",
|
||||
"tls",
|
||||
"ssl",
|
||||
]
|
||||
):
|
||||
return "crypto"
|
||||
|
||||
# C library functions
|
||||
if any(
|
||||
libc in symbol_name
|
||||
for libc in [
|
||||
"printf",
|
||||
"scanf",
|
||||
"malloc",
|
||||
"free",
|
||||
"memcpy",
|
||||
"memset",
|
||||
"strcpy",
|
||||
"strlen",
|
||||
"_dtoa",
|
||||
"_fopen",
|
||||
]
|
||||
):
|
||||
return "libc"
|
||||
elif symbol_name.startswith("_") and symbol_name[1:].replace("_r", "").replace(
|
||||
# libc special printf variants
|
||||
if symbol_name.startswith("_") and symbol_name[1:].replace("_r", "").replace(
|
||||
"v", ""
|
||||
).replace("s", "") in ["printf", "fprintf", "sprintf", "scanf"]:
|
||||
return "libc"
|
||||
|
||||
# IPv6 specific
|
||||
if "nd6_" in symbol_name or "ip6_" in symbol_name:
|
||||
return "ipv6_stack"
|
||||
|
||||
# Other system libraries
|
||||
if "nvs_" in demangled:
|
||||
return "nvs"
|
||||
elif "spiffs" in demangled or "vfs" in demangled:
|
||||
return "filesystem"
|
||||
elif "newlib" in demangled:
|
||||
return "libc"
|
||||
elif (
|
||||
"libgcc" in demangled
|
||||
or "_divdi3" in symbol_name
|
||||
or "_udivdi3" in symbol_name
|
||||
):
|
||||
return "libgcc"
|
||||
|
||||
# Boot and startup
|
||||
if any(
|
||||
boot in symbol_name
|
||||
for boot in ["boot", "start_cpu", "call_start", "startup", "bootloader"]
|
||||
):
|
||||
return "boot_startup"
|
||||
|
||||
# PHY/Radio layer
|
||||
if any(
|
||||
phy in symbol_name
|
||||
for phy in [
|
||||
"phy_",
|
||||
"rf_",
|
||||
"chip_",
|
||||
"register_chipv7",
|
||||
"pbus_",
|
||||
"bb_",
|
||||
"fe_",
|
||||
]
|
||||
):
|
||||
return "phy_radio"
|
||||
elif any(pp in symbol_name for pp in ["pp_", "ppT", "ppR", "ppP", "ppInstall"]):
|
||||
return "wifi_phy_pp"
|
||||
elif "lmac" in symbol_name:
|
||||
return "wifi_lmac"
|
||||
elif "wdev" in symbol_name:
|
||||
return "wifi_device"
|
||||
|
||||
# Bluetooth/BLE
|
||||
if any(
|
||||
bt in symbol_name for bt in ["bt_", "ble_", "l2c_", "gatt_", "gap_", "hci_"]
|
||||
):
|
||||
return "bluetooth"
|
||||
elif "coex" in symbol_name:
|
||||
return "wifi_bt_coex"
|
||||
elif "r_" in symbol_name and any(
|
||||
bt in symbol_name for bt in ["ble", "lld", "llc", "llm"]
|
||||
):
|
||||
# ROM bluetooth functions
|
||||
return "bluetooth_rom"
|
||||
|
||||
# Power management
|
||||
if any(
|
||||
pm in symbol_name
|
||||
for pm in [
|
||||
"pm_",
|
||||
"sleep",
|
||||
"rtc_sleep",
|
||||
"light_sleep",
|
||||
"deep_sleep",
|
||||
"power_down",
|
||||
]
|
||||
):
|
||||
return "power_mgmt"
|
||||
|
||||
# Logging and diagnostics
|
||||
if any(log in demangled for log in ["log", "Log", "print", "Print", "diag_"]):
|
||||
return "logging"
|
||||
|
||||
# Memory management
|
||||
if any(mem in symbol_name for mem in ["mem_", "memory_", "tlsf_", "memp_"]):
|
||||
return "memory_mgmt"
|
||||
|
||||
# HAL (Hardware Abstraction Layer)
|
||||
if "hal_" in symbol_name:
|
||||
return "hal_layer"
|
||||
|
||||
# Clock management
|
||||
if any(
|
||||
clk in symbol_name
|
||||
for clk in ["clk_", "clock_", "rtc_clk", "apb_", "cpu_freq"]
|
||||
):
|
||||
return "clock_mgmt"
|
||||
|
||||
# Cache management
|
||||
if "cache" in symbol_name:
|
||||
return "cache_mgmt"
|
||||
|
||||
# Flash operations
|
||||
if "flash" in symbol_name and "spi" not in symbol_name:
|
||||
return "flash_ops"
|
||||
|
||||
# Interrupt/Exception handling
|
||||
if any(
|
||||
isr in symbol_name
|
||||
for isr in ["isr", "interrupt", "intr_", "exc_", "exception"]
|
||||
):
|
||||
return "interrupt_handlers"
|
||||
elif "_wrapper" in symbol_name:
|
||||
return "wrapper_functions"
|
||||
|
||||
# Error handling
|
||||
if any(
|
||||
err in symbol_name
|
||||
for err in ["panic", "abort", "assert", "error_", "fault"]
|
||||
):
|
||||
return "error_handling"
|
||||
|
||||
# ECC/Crypto math
|
||||
if any(
|
||||
ecc in symbol_name for ecc in ["ecp_", "bignum_", "mpi_", "sswu", "modp"]
|
||||
):
|
||||
return "crypto_math"
|
||||
|
||||
# Authentication
|
||||
if "checkDigestAuthentication" in demangled or "auth" in symbol_name.lower():
|
||||
return "authentication"
|
||||
|
||||
# PPP protocol
|
||||
if any(ppp in symbol_name for ppp in ["ppp", "ipcp_", "lcp_", "chap_"]):
|
||||
return "ppp_protocol"
|
||||
|
||||
# DHCP
|
||||
if "dhcp" in symbol_name or "handle_dhcp" in symbol_name:
|
||||
return "dhcp"
|
||||
|
||||
# JSON parsing
|
||||
if any(
|
||||
json in demangled
|
||||
for json in [
|
||||
"ArduinoJson",
|
||||
"JsonDocument",
|
||||
"JsonArray",
|
||||
"JsonObject",
|
||||
"deserialize",
|
||||
"serialize",
|
||||
]
|
||||
):
|
||||
return "json_lib"
|
||||
|
||||
# HTTP/Web related
|
||||
if any(
|
||||
http in demangled
|
||||
for http in ["HTTP", "http_", "Request", "Response", "Uri", "WebSocket"]
|
||||
):
|
||||
return "http_lib"
|
||||
|
||||
# Ethernet PHY drivers
|
||||
if any(
|
||||
eth in symbol_name
|
||||
for eth in [
|
||||
"emac_",
|
||||
"eth_phy_",
|
||||
"phy_tlk110",
|
||||
"phy_lan87",
|
||||
"phy_ip101",
|
||||
"phy_rtl",
|
||||
"phy_dp83",
|
||||
"phy_ksz",
|
||||
]
|
||||
):
|
||||
return "ethernet_phy"
|
||||
|
||||
# Task/Thread management
|
||||
if any(task in symbol_name for task in ["pthread_", "thread_", "_task_"]):
|
||||
return "threading"
|
||||
|
||||
# Mutex/Semaphore
|
||||
if any(
|
||||
sync in symbol_name
|
||||
for sync in ["mutex", "semaphore", "spinlock", "portMUX"]
|
||||
):
|
||||
return "synchronization"
|
||||
|
||||
# String formatting
|
||||
if any(
|
||||
fmt in symbol_name
|
||||
for fmt in [
|
||||
"snprintf",
|
||||
"vsnprintf",
|
||||
"sprintf",
|
||||
"vsprintf",
|
||||
"sscanf",
|
||||
"vsscanf",
|
||||
]
|
||||
):
|
||||
return "string_formatting"
|
||||
|
||||
# Math functions
|
||||
if (
|
||||
any(
|
||||
math in symbol_name
|
||||
for math in [
|
||||
"sin",
|
||||
"cos",
|
||||
"tan",
|
||||
"sqrt",
|
||||
"pow",
|
||||
"exp",
|
||||
"log",
|
||||
"atan",
|
||||
"asin",
|
||||
"acos",
|
||||
"floor",
|
||||
"ceil",
|
||||
"fabs",
|
||||
"round",
|
||||
]
|
||||
)
|
||||
and len(symbol_name) < 20
|
||||
):
|
||||
return "math_lib"
|
||||
|
||||
# Random number generation
|
||||
if any(rng in symbol_name for rng in ["rand", "random", "rng_", "prng"]):
|
||||
return "random"
|
||||
|
||||
# Time functions
|
||||
if any(
|
||||
time in symbol_name
|
||||
for time in [
|
||||
"time",
|
||||
"clock",
|
||||
"gettimeofday",
|
||||
"settimeofday",
|
||||
"localtime",
|
||||
"gmtime",
|
||||
"mktime",
|
||||
"strftime",
|
||||
]
|
||||
):
|
||||
return "time_lib"
|
||||
|
||||
# Console/UART output
|
||||
if any(
|
||||
console in symbol_name
|
||||
for console in [
|
||||
"console_",
|
||||
"uart_tx",
|
||||
"uart_rx",
|
||||
"puts",
|
||||
"putchar",
|
||||
"getchar",
|
||||
]
|
||||
):
|
||||
return "console_io"
|
||||
|
||||
# ROM functions
|
||||
if symbol_name.startswith("r_") or symbol_name.startswith("rom_"):
|
||||
return "rom_functions"
|
||||
|
||||
# Compiler generated code
|
||||
if any(
|
||||
gen in symbol_name
|
||||
for gen in [
|
||||
"__divdi3",
|
||||
"__udivdi3",
|
||||
"__moddi3",
|
||||
"__muldi3",
|
||||
"__ashldi3",
|
||||
"__ashrdi3",
|
||||
"__lshrdi3",
|
||||
"__cmpdi2",
|
||||
"__fixdfdi",
|
||||
"__floatdidf",
|
||||
]
|
||||
):
|
||||
return "compiler_runtime"
|
||||
|
||||
# Exception handling
|
||||
if any(
|
||||
exc in symbol_name for exc in ["__cxa_", "_Unwind_", "__gcc_personality"]
|
||||
):
|
||||
return "exception_handling"
|
||||
|
||||
# RTTI (Run-Time Type Information)
|
||||
if "__type_info" in demangled or "__class_type_info" in demangled:
|
||||
return "rtti"
|
||||
|
||||
# Static initializers
|
||||
if "_GLOBAL__sub_I_" in symbol_name or "__static_initialization" in demangled:
|
||||
return "static_init"
|
||||
|
||||
# Weak symbols
|
||||
if "__weak_" in symbol_name:
|
||||
return "weak_symbols"
|
||||
|
||||
# Compiler builtins
|
||||
if "__builtin_" in symbol_name:
|
||||
return "compiler_builtins"
|
||||
|
||||
# Track uncategorized symbols for analysis
|
||||
return "other"
|
||||
|
||||
def _batch_demangle_symbols(self, symbols: list[str]) -> None:
|
||||
@ -760,7 +772,7 @@ class MemoryAnalyzer:
|
||||
|
||||
# Main table
|
||||
lines.append(
|
||||
f"{'Component':<28} | {'Flash (text)':<12} | {'Flash (data)':<12} | {'RAM (data)':<10} | {'RAM (bss)':<10} | {'Total Flash':<12} | {'Total RAM':<10}"
|
||||
f"{'Component':<28} | {'Flash (text)':>12} | {'Flash (data)':>12} | {'RAM (data)':>10} | {'RAM (bss)':>10} | {'Total Flash':>12} | {'Total RAM':>10}"
|
||||
)
|
||||
lines.append(
|
||||
"-" * 28
|
||||
@ -860,6 +872,39 @@ class MemoryAnalyzer:
|
||||
}
|
||||
return json.dumps(data, indent=2)
|
||||
|
||||
def dump_uncategorized_symbols(self, output_file: str | None = None) -> None:
|
||||
"""Dump uncategorized symbols for analysis."""
|
||||
# Sort by size descending
|
||||
sorted_symbols = sorted(
|
||||
self._uncategorized_symbols, key=lambda x: x[2], reverse=True
|
||||
)
|
||||
|
||||
lines = ["Uncategorized Symbols Analysis", "=" * 80]
|
||||
lines.append(f"Total uncategorized symbols: {len(sorted_symbols)}")
|
||||
lines.append(
|
||||
f"Total uncategorized size: {sum(s[2] for s in sorted_symbols):,} bytes"
|
||||
)
|
||||
lines.append("")
|
||||
lines.append(f"{'Size':>10} | {'Symbol':<60} | Demangled")
|
||||
lines.append("-" * 10 + "-+-" + "-" * 60 + "-+-" + "-" * 40)
|
||||
|
||||
for symbol, demangled, size in sorted_symbols[:100]: # Top 100
|
||||
if symbol != demangled:
|
||||
lines.append(f"{size:>10,} | {symbol[:60]:<60} | {demangled[:100]}")
|
||||
else:
|
||||
lines.append(f"{size:>10,} | {symbol[:60]:<60} | [not demangled]")
|
||||
|
||||
if len(sorted_symbols) > 100:
|
||||
lines.append(f"\n... and {len(sorted_symbols) - 100} more symbols")
|
||||
|
||||
content = "\n".join(lines)
|
||||
|
||||
if output_file:
|
||||
with open(output_file, "w") as f:
|
||||
f.write(content)
|
||||
else:
|
||||
print(content)
|
||||
|
||||
|
||||
def analyze_elf(
|
||||
elf_path: str,
|
||||
|
Loading…
x
Reference in New Issue
Block a user