]> granicus.if.org Git - esp-idf/commitdiff
C++: add provisions for optional RTTI support
authorIvan Grokhotkov <ivan@espressif.com>
Thu, 6 Jun 2019 08:53:26 +0000 (16:53 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Sun, 13 Oct 2019 12:46:44 +0000 (14:46 +0200)
Ref. https://github.com/espressif/esp-idf/issues/1684

This change allows RTTI to be enabled in menuconfig. For full RTTI
support, libstdc++.a in the toolchain should be built without
-fno-rtti, as it is done now.

Generally if libstdc++.a is built with RTTI, applications which do not
use RTTI (and build with -fno-rtti) could still include typeinfo
structures referenced from STL classes’ vtables. This change works
around this, by moving all typeinfo structures from libstdc++.a into
a non-loadable section, placed into a non-existent memory region
starting at address 0. This can be done because when the application
is compiled with -fno-rtti, typeinfo structures are not used at run
time. This way, typeinfo structures do not contribute to the
application binary size.

If the application is build with RTTI support, typeinfo structures are
linked into the application .rodata section as usual.

Note that this commit does not actually enable RTTI support.
The respective Kconfig option is hidden, and will be made visible when
the toolchain is updated.

CMakeLists.txt
Kconfig
components/esp32/CMakeLists.txt
components/esp32/component.mk
components/esp32/ld/esp32.discard-rtti.ld [new file with mode: 0644]
components/esp32/ld/esp32.ld
make/project.mk
tools/cmake/build.cmake

index 4dae14c8cd94811f7a2353ee74f575c629504fe1..55c9109f90c6dedaade8ca8a0638d4e5b4152d50 100644 (file)
@@ -27,6 +27,12 @@ else()
     list(APPEND cxx_compile_options "-fno-exceptions")
 endif()
 
+if(CONFIG_COMPILER_CXX_RTTI)
+    list(APPEND cxx_compile_options "-frtti")
+else()
+    list(APPEND cxx_compile_options "-fno-rtti")
+endif()
+
 if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS)
     list(APPEND compile_options "-Wno-parentheses"
                                 "-Wno-sizeof-pointer-memaccess"
diff --git a/Kconfig b/Kconfig
index 92c76c38d59d943fd1dbec42452bbb36c6f71480..815f87d072cfd30dd6272fcf08828ac8cf8ffa9b 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -237,6 +237,15 @@ mainmenu "Espressif IoT Development Framework Configuration"
                 Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate
                 memory for thrown exceptions when there is not enough memory on the heap.
 
+        config COMPILER_CXX_RTTI
+            # Invisible option, until the toolchain with RTTI support is released.
+            # Use prompt "Enable C++ run-time type info (RTTI)" when updating.
+            bool
+            help
+                Enabling this option compiles all C++ files with RTTI support enabled.
+                This increases binary size (typically by tens of kB) but allows using
+                dynamic_cast conversion and typeid operator.
+
         choice COMPILER_STACK_CHECK_MODE
             prompt "Stack smashing protection mode"
             default COMPILER_STACK_CHECK_MODE_NONE
index 7d9ad3872d5d140843b19b52670b84f50930b02a..70a380593949bca134ff7ca78bc9c6ee7ee4c4ab 100644 (file)
@@ -56,6 +56,11 @@ else()
         target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32.extram.bss.ld")
     endif()
 
+    if(NOT CONFIG_COMPILER_CXX_RTTI)
+        # This has to be linked before esp32.project.ld
+        target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32.discard-rtti.ld")
+    endif()
+
     # Process the template file through the linker script generation mechanism, and use the output for linking the
     # final binary
     target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp32.project.ld.in" 
index 8f999b26d66b82b101390aa2a9fb64857d37104f..836f242e207e8310e625d64c458f48376f98aa59 100644 (file)
@@ -5,18 +5,23 @@
 COMPONENT_SRCDIRS := .
 
 ifdef CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
-   # This linker script must come before esp32.project.ld
-   LINKER_SCRIPTS += esp32.extram.bss.ld
+       # This linker script must come before esp32.project.ld
+       LINKER_SCRIPTS += esp32.extram.bss.ld
 endif
 
-#Linker scripts used to link the final application.
-#Warning: These linker scripts are only used when the normal app is compiled; the bootloader
-#specifies its own scripts.
+ifndef CONFIG_COMPILER_CXX_RTTI
+       # This linker script must come before esp32.project.ld
+       LINKER_SCRIPTS += esp32.discard-rtti.ld
+endif
+
+# Linker scripts used to link the final application.
+# Warning: These linker scripts are only used when the normal app is compiled; the bootloader
+# specifies its own scripts.
 LINKER_SCRIPTS += $(COMPONENT_BUILD_DIR)/esp32.project.ld esp32.peripherals.ld
 
-#ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the
-#linker will ignore panic_highint_hdl.S as it has no other files depending on any
-#symbols in it.
+# ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the
+# linker will ignore panic_highint_hdl.S as it has no other files depending on any
+# symbols in it.
 COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH)/ld \
                          -T esp32_out.ld \
                          -u ld_include_panic_highint_hdl \
diff --git a/components/esp32/ld/esp32.discard-rtti.ld b/components/esp32/ld/esp32.discard-rtti.ld
new file mode 100644 (file)
index 0000000..f9fdff9
--- /dev/null
@@ -0,0 +1,11 @@
+/* This is only included if CONFIG_COMPILER_CXX_RTTI is not set, to
+ * move RTTI sections of libstdc++ to an unused non-loadable memory region.
+ */
+
+SECTIONS
+{
+  .rodata.discard-rtti (NOLOAD):
+  {
+    *libstdc++.a:(.rodata._ZTI* .rodata._ZTS*)
+  } > discard_seg
+}
index 0400fc2ab31dcff03aa8bab32bd006e032595507..cb0f14437be5c4c502f9c3138d74cf2b859c06bc 100644 (file)
@@ -98,6 +98,11 @@ MEMORY
   /* external memory ,including data and text */
   extern_ram_seg(RWX)  :             org = 0x3F800000,
                                      len = 0x400000
+
+  /* This is not a memory range which can really be accessed; we use it as a "bitbucket"
+     where non-loadable sections, which aren't used at run time, can be discarded.
+   */
+  discard_seg (R) :                  org = 0x00000000, len = 0x10000000
 }
 
 #if defined(CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE)
index a8ec59f405538da7956a8ddad8e9d0ab6330efe0..61e80ac068a87a6702c097032c9a44710e374073 100644 (file)
@@ -468,7 +468,6 @@ CXXFLAGS ?=
 EXTRA_CXXFLAGS ?=
 CXXFLAGS := $(strip \
        -std=gnu++11 \
-       -fno-rtti \
        $(OPTIMIZATION_FLAGS) $(DEBUG_FLAGS) \
        $(COMMON_FLAGS) \
        $(COMMON_WARNING_FLAGS) \
@@ -481,6 +480,12 @@ else
 CXXFLAGS += -fno-exceptions
 endif
 
+ifdef CONFIG_COMPILER_CXX_RTTI
+CXXFLAGS += -frtti
+else
+CXXFLAGS += -fno-rtti
+endif
+
 ARFLAGS := cru
 
 export CFLAGS CPPFLAGS CXXFLAGS ARFLAGS
index f495ed8fa906a625b2e9c368a8a2f20dd971e448..c3bbdeafffc8b2b72918229ede0ec45606bd5e69 100644 (file)
@@ -114,8 +114,7 @@ function(__build_set_default_build_specifications)
     list(APPEND c_compile_options   "-std=gnu99"
                                     "-Wno-old-style-declaration")
 
-    list(APPEND cxx_compile_options "-std=gnu++11"
-                                    "-fno-rtti")
+    list(APPEND cxx_compile_options "-std=gnu++11")
 
     idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND)
     idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)