diff --git a/components/esp_common/include/esp_attr.h b/components/esp_common/include/esp_attr.h index c8c6c4d5f0c..8d78cfa9be6 100644 --- a/components/esp_common/include/esp_attr.h +++ b/components/esp_common/include/esp_attr.h @@ -90,7 +90,17 @@ extern "C" { // Forces a string into DRAM instead of flash // Use as esp_rom_printf(DRAM_STR("Hello world!\n")); -#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;})) +// The string is placed into a uniquely-named variable in a uniquely-named +// subsection of .dram1. Both names are derived from a single __COUNTER__ value. +// This avoids "section type conflict" errors under LTO, where the local static +// variables generated by DRAM_STR in different translation units would otherwise +// share the same name and the same DRAM_ATTR section name after the units are merged. +#define DRAM_STR(str) _DRAM_STR_IMPL(str, __COUNTER__) +#define _DRAM_STR_COMBINE(x, y) x ## y +#define _DRAM_STR_IMPL(str, counter) \ + _DRAM_STR_IMPL2(str, _DRAM_STR_COMBINE(__c, counter), _SECTION_ATTR_IMPL(".dram1.str", counter)) +#define _DRAM_STR_IMPL2(str, varname, attr) \ + (__extension__({static const attr char varname[] = (str); (const char *)&varname;})) #if CONFIG_SOC_RTC_FAST_MEM_SUPPORTED || CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED // Forces data into RTC memory. See "docs/deep-sleep-stub.rst"