Link-time optimization (LTO) lets the compiler inline and optimize across
translation units. ESP-IDF relies heavily on linker-script placement rules
that match object files by name, which LTO does not preserve, so LTO cannot
be enabled for the whole framework. This change adds two opt-in options that
side-step that conflict:
- CONFIG_COMPILER_LTO_LINKTIME tells the linker to perform LTO on any object
files that carry LTO information (compiled with -flto). On its own this is
safe: users can add -flto to specific components (e.g. their own libraries)
to shrink them, without affecting components that use linker fragments.
- CONFIG_COMPILER_LTO_COMPILETIME automatically compiles most
components with -flto. A component is excluded when it has its own linker
fragments, when it opts out via the NO_LTO component property, or when its
object code is placed by *another* component's linker fragment (matched by
archive name). The last case is handled by tools/cmake/lto.cmake, which
scans linker fragments for explicit "archive: libNAME.a" placement and
excludes those components. Without it, functions that must run from IRAM
while the flash cache is disabled (e.g. the spi_flash / GDMA HAL routines,
placed in IRAM by spi_flash/esp_driver_dma fragments) would be moved to
flash by LTO and the device would panic with a cache error at run time.
Both options are disabled for the bootloader and ESP-TEE builds, which depend
on object-file-name based placement. LTO is also gated off for Clang
(needs LLD, IDF-8286) and host builds.
LTO works together with CONFIG_APP_REPRODUCIBLE_BUILD, but needs extra
flags: LTO defers code generation and most debug-info emission from compile
time to link time, where the reproducible-build path remapping (applied to
compile_options only) does not take effect. When both options are enabled,
three extra flags keep the .elf, .bin and .map byte-identical across build
directories (verified on esp32 / GCC 16.1):
- the -f*-prefix-map options are passed to the linker as well, so the LTO
code generator remaps DW_AT_comp_dir (otherwise the build dir leaks into
.debug_str, and cascades into esp_app_desc_t.app_elf_sha256 in the .bin);
- -save-temps makes lto-wrapper use stable LTRANS object names in the build
dir instead of random $TMPDIR paths that leak into the .map;
- -frandom-seed=1 makes LTO GIMPLE bytecode objects byte-identical (a
shared seed was verified not to collide, including for C++ file-local
static variables and anonymous namespaces promoted by LTO).
The gcc-ar / gcc-ranlib wrappers are selected in the GCC toolchain file so
that the LTO plugin is loaded when creating and indexing static archives;
plain ar/ranlib do not record LTO symbols in the archive index.
Note: LTO, like other inlining, can also increase binary size. Enable it
together with CONFIG_COMPILER_OPTIMIZATION_SIZE to get a code-size benefit.
Related: IDF-71, IDF-8286
Closes https://github.com/espressif/esp-idf/issues/18741
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add KASAN support for detecting heap memory safety bugs (buffer
overflows, underflows, use-after-free) at runtime using compiler
instrumentation and shadow memory. Gated behind
CONFIG_IDF_EXPERIMENTAL_FEATURES, with touch points kept to esp_system
and heap so other components stay untouched.
- Core runtime (esp_system/kasan.c, esp_kasan.h): nibble-based shadow
memory in DRAM, poison/unpoison, per-access validation, and __asan_*
stubs; hot-path stubs in IRAM so they stay valid with the flash cache
off. Shadow init runs before heap bring-up.
- Heap integration (heap/heap_kasan*.c): alloc/free hooks add redzones,
a quarantine FIFO, and shadow updates.
- Panic handling: disable checks once at the panic handler entry so
backtrace and stack dumps can read redzones without nested reports.
- Build system: -fsanitize=kernel-address for app code, with HAL, SoC,
esp_rom, SPI flash, esp_hw_support, bootloader_support, FreeRTOS, and
heap internals excluded from instrumentation.
- Test app (tools/test_apps/system/kasan_test): Unity tests for
overflow, underflow, use-after-free, and all sized __asan_* stubs,
with halt and no-halt configurations.
- Docs: document KASAN in the heap memory debugging guide (EN and CN).
Implement the NAN Data Path encrypted datapath per Wi-Fi Aware v4.0
(§7.1.3.5, §9.5.16):
- Responder + initiator sides of the M1-M4 Shared-Key Descriptor
exchange, with MIC compute/verify, PTK derivation, and PMK/PMKID
derivation via PBKDF2-SHA256 over passphrase or pre-shared PMK.
- CSIA / SCIA attribute build + parse, NCS-SK-128 cipher suite.
- Per-NDL security context on ndl_info::security_ctx; per-svc PMK cache.
- ndp_response_indication callback for initiator peer-NDI binding.
- host<->blob ABI migrated from 27 direct esp_nan_* externs to a single
nan_secure_dp_funcs callback struct in esp_private/wifi.h.
- nan_security.c split out of nan_app.c (~340 lines de-duplicated into
shared M1-M4 helpers).
- CONFIG_ESP_WIFI_NAN_ENCRYPTED_DATAPATH gates the secure path so non-
security builds compile out the crypto/handshake code.
- ROM patch (esp32s31): mask ieee80211_encap_esfbuf to match the
c5/c6/c61 pattern for NAN-capable chips.
Hardening: PMK stack copies zeroized on every return, NDP attribute
parsers bounds-checked, CSID range-checked before shifting, NDL slot
reuse only when handshake state is IDLE, get_csia/scia_len aligned with
their builders on empty input.
API surface: NDP security types moved out of esp_wifi_types_generic.h
into esp_private/wifi.h (internal-only). security pointer dropped from
struct ndp_cb_peer_info. Discovery-side wifi_nan_security_type_t and
the NDP Info callbacks removed (subsumed by csid_bitmap and SSI
respectively).
Applicable for chips affected by interrupt issue:
- ESP32C5
- ESP32C61
- ESP32H4
For all other chips that support the ZCMP extension without issues,
it will be enabled unconditionally.
Introduce ESPTOOLPY_FAST_REFLASHING configuration option. It instructs
ldgen to group entity mappings for libraries deemed mutable (prone to
change) separately from those considered immutable (unlikely to change).
Organizing mutable and immutable libraries separately in the linker
script allows the linker to form larger contiguous blocks of data for
immutable libraries in the application's output sections. These blocks
are likely to stay mostly unchanged between application recompilations,
enabling them to be skipped during reflashing.
Separating mutable and immutable libraries in the linker script to
minimize changes in the output sections is insufficient. Padding is
added after the input sections of mutable libraries in the default data
and text output sections. This creates a buffer for the mutable
libraries, allowing additional changes to be made without altering the
layout of the binary image.
Additionally two optimizations currently in use can still mix data from
these libraries, leading to significant changes even within the grouped
immutable libraries.
1. constant merging
Linker will try to merge input sections that have the MERGE and
STRING flags from different libraries (object files) to perform
optimizations like tail merging. For example, adding a string
literal in a mutable library will also change the addresses of
string literals from immutable libraries in such a merged section,
causing changes in the generated code when those literals are
referenced.
Disabled with COMPILER_DISABLE_MERGE_CONSTANTS(-fno-merge-constants)
2. literal pools on Xtensa
As optimization, the linker may merge literal pools from different
libraries (object files) to improve the generated code size. This
has the same effect as constant merging, and changes in mutable
libraries may cause changes in the generated code for immutable
libraries. To get larger unchanged continuous blocks in the text
output sections for immutable libraries, we need to ensure that the
Xtensa literal pools remain close to their references and are not
merged.
Disabled with CONFIG_COMPILER_ENABLE_TEXT_SECTION_LITERALS(-mtext-section-literals)
When ESPTOOLPY_FAST_REFLASHING is enabled, these two optimizations are
disabled to achieve larger unchaged continuous blocks for the grouped
immutable libraries, even though disabling these optimizations results
in slightly larger code.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Currently both menu configs, for component's project configuration and
component's configuration, for components not included in the build have
the same name: "Configuration for components not included in the build".
This might be confusing. Let's use "Project configuration for components
not included in the build" for component Kconfig.projbuild files.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Introduce new configuration menus for components that are not part of
the build. These menus will only be visible if the IDF_BUILD_V2
environment variable is defined and it will be set only in cmakev2. This
enables sharing of the root Kconfig file between cmakev1 and cmakev2.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Allow to disable implicit inlining of constexpr functions from libstdc++.
This is a known GCC issue https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93008
that may affect C++ application size depending on its structure.