From 6f5a3cf48fbee4c74f71a068404f41d12a0c21c3 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Thu, 8 Dec 2016 14:48:47 +0100 Subject: [PATCH 1/4] [libaxx] Explicitely define __cxa_pure_virtual Change-Id: I07315f1bf84771a2784788e0d0eea4360245701d --- ion/src/device/boot/flash.ld | 5 ----- libaxx/Makefile | 1 + libaxx/src/cxxabi/pure_virtual.cpp | 10 ++++++++++ 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 libaxx/src/cxxabi/pure_virtual.cpp diff --git a/ion/src/device/boot/flash.ld b/ion/src/device/boot/flash.ld index 37c3e5e02..3925a4949 100644 --- a/ion/src/device/boot/flash.ld +++ b/ion/src/device/boot/flash.ld @@ -36,11 +36,6 @@ SECTIONS { .text : { . = ALIGN(4); - - /* C++ code calls __cxa_pure_virtual when a pure-virtual method is called. - * This is an error case, so we just redirect it to abort. */ - PROVIDE(__cxa_pure_virtual = abort); - *(.text) *(.text.*) } >FLASH diff --git a/libaxx/Makefile b/libaxx/Makefile index 2f64bd449..b4c97c60f 100644 --- a/libaxx/Makefile +++ b/libaxx/Makefile @@ -1 +1,2 @@ objs += $(addprefix libaxx/src/, new.o) +objs += $(addprefix libaxx/src/cxxabi/, pure_virtual.o) diff --git a/libaxx/src/cxxabi/pure_virtual.cpp b/libaxx/src/cxxabi/pure_virtual.cpp new file mode 100644 index 000000000..eee71e8aa --- /dev/null +++ b/libaxx/src/cxxabi/pure_virtual.cpp @@ -0,0 +1,10 @@ +extern "C" { +#include +} + +/* C++ code calls __cxa_pure_virtual when a pure-virtual method is called. + * This is an error case, so we just redirect it to abort. */ + +extern "C" void __cxa_pure_virtual() { + abort(); +} From 7fb1f78f6f219f58e56e420acea43773a007408d Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Thu, 8 Dec 2016 14:49:35 +0100 Subject: [PATCH 2/4] [libaxx] Define __cxa_atexit In practice, it does nothing! Change-Id: I5fb92299c4672d1635d0b77c2fc5de4e666c7213 --- libaxx/Makefile | 2 +- libaxx/src/cxxabi/atexit.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 libaxx/src/cxxabi/atexit.cpp diff --git a/libaxx/Makefile b/libaxx/Makefile index b4c97c60f..6911cbcb3 100644 --- a/libaxx/Makefile +++ b/libaxx/Makefile @@ -1,2 +1,2 @@ objs += $(addprefix libaxx/src/, new.o) -objs += $(addprefix libaxx/src/cxxabi/, pure_virtual.o) +objs += $(addprefix libaxx/src/cxxabi/, atexit.o pure_virtual.o) diff --git a/libaxx/src/cxxabi/atexit.cpp b/libaxx/src/cxxabi/atexit.cpp new file mode 100644 index 000000000..ee32fc39c --- /dev/null +++ b/libaxx/src/cxxabi/atexit.cpp @@ -0,0 +1,14 @@ +/* C++ expects the __dso_handle symbol to be defined to some unique value in + * each dynamic shared object. Even though we're not using dynamic loading, + * we still have to define __dso_handle. */ + +void * __dso_handle = nullptr; + +/* The __cxa_atexit function registers a function to be called when the program + * exits or when a shared library is unloaded. + * We don't support shared libraries and our program should never exit, so we + * can simply do nothing and return zero. */ + +extern "C" int __cxa_atexit(void (*dtor)(void *), void * object, void * handle) { + return 0; +} From a0ad3c76a449f5c418f9f6fda5390a622897925c Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Thu, 8 Dec 2016 14:50:12 +0100 Subject: [PATCH 3/4] [liba] Define __aeabi_atexit Change-Id: Ibf8d2f5453d457d62989e0adcc070ae09e1c9074 --- liba/Makefile | 1 + liba/src/aeabi-rt/atexit.c | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 liba/src/aeabi-rt/atexit.c diff --git a/liba/Makefile b/liba/Makefile index c27ce43f4..a01f8b0b6 100644 --- a/liba/Makefile +++ b/liba/Makefile @@ -56,6 +56,7 @@ tests += $(addprefix liba/test/, \ # The use of aeabi-rt could be made conditional to an AEABI target. # In practice we're always using liba on such a target. objs += $(addprefix liba/src/aeabi-rt/, \ + atexit.o \ memclr.o \ memcpy.o \ ) diff --git a/liba/src/aeabi-rt/atexit.c b/liba/src/aeabi-rt/atexit.c new file mode 100644 index 000000000..097301d2a --- /dev/null +++ b/liba/src/aeabi-rt/atexit.c @@ -0,0 +1,7 @@ +/* See the "Run-time ABI for the ARM Architecture", Section 4.4.5 */ + +int __cxa_atexit(void (* dtor)(void * this), void * object, void * handle); + +int __aeabi_atexit(void * object, void (*destroyer)(void *), void * dso_handle) { + return __cxa_atexit(destroyer, object, dso_handle); +} From 0ea0a0139acdc44dd1266f7da252f5341ba8486c Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Thu, 8 Dec 2016 15:02:30 +0100 Subject: [PATCH 4/4] [ion] Initialize static C++ objects Change-Id: I8ee7d11985c5de61fb09bf69a02867f2a0d40425 --- ion/src/device/boot/flash.ld | 7 +++++++ ion/src/device/boot/rt0.cpp | 26 +++++++++++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ion/src/device/boot/flash.ld b/ion/src/device/boot/flash.ld index 3925a4949..fc68ffec2 100644 --- a/ion/src/device/boot/flash.ld +++ b/ion/src/device/boot/flash.ld @@ -40,6 +40,13 @@ SECTIONS { *(.text.*) } >FLASH + .init_array : { + . = ALIGN(4); + _init_array_start = .; + KEEP (*(.init_array*)) + _init_array_end = .; + } >FLASH + .rodata : { . = ALIGN(4); *(.rodata) diff --git a/ion/src/device/boot/rt0.cpp b/ion/src/device/boot/rt0.cpp index 5aaade29b..b3a6a8b1a 100644 --- a/ion/src/device/boot/rt0.cpp +++ b/ion/src/device/boot/rt0.cpp @@ -6,11 +6,17 @@ extern "C" { #include #include "../device.h" -extern char _data_section_start_flash; -extern char _data_section_start_ram; -extern char _data_section_end_ram; -extern char _bss_section_start_ram; -extern char _bss_section_end_ram; +typedef void (*cxx_constructor)(); + +extern "C" { + char _data_section_start_flash; + char _data_section_start_ram; + char _data_section_end_ram; + char _bss_section_start_ram; + char _bss_section_end_ram; + cxx_constructor _init_array_start; + cxx_constructor _init_array_end; +} void abort() { #ifdef DEBUG @@ -38,6 +44,16 @@ void start() { size_t bssSectionLength = (&_bss_section_end_ram - &_bss_section_start_ram); memset(&_bss_section_start_ram, 0, bssSectionLength); + /* Call static C++ object constructors + * The C++ compiler creates an initialization function for each static object. + * The linker then stores the address of each of those functions consecutively + * between _init_array_start and _init_array_end. So to initialize all C++ + * static objects we just have to iterate between theses two addresses and + * call the pointed function. */ + for (cxx_constructor * c = &_init_array_start; c<&_init_array_end; c++) { + (*c)(); + } + Ion::Device::init(); ion_app();