From 5719cd6fac238f8611324f5b5bd2190dee6b0678 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 1 Apr 2019 15:21:12 +0800 Subject: [PATCH] newlib: when compiling with GCC8, use newlib headers and libraries from toolchain --- .../esp_rom/esp32/ld/esp32.rom.syscalls.ld | 10 +- components/newlib/CMakeLists.txt | 19 ++- components/newlib/component.mk | 13 +- components/newlib/heap.c | 126 ++++++++++++++++++ components/newlib/newlib.lf | 6 + components/newlib/syscalls.c | 49 +------ 6 files changed, 165 insertions(+), 58 deletions(-) create mode 100644 components/newlib/heap.c create mode 100644 components/newlib/newlib.lf diff --git a/components/esp_rom/esp32/ld/esp32.rom.syscalls.ld b/components/esp_rom/esp32/ld/esp32.rom.syscalls.ld index f358bddd37..811d879dd4 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.syscalls.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.syscalls.ld @@ -28,7 +28,7 @@ PROVIDE ( _write_r = 0x4000bd70 ); I.e.: - free (in ROM) -> _free_r (in ROM) -> syscall table entry _free_r -> _free_r (in IDF) + times (in ROM) -> _times_r (in ROM) -> syscall table entry _times_r -> _times_r (in IDF) Hence the following entries are provided only for reference and commented out. @@ -36,6 +36,8 @@ PROVIDE ( _write_r = 0x4000bd70 ); /* <--- the following lines are commented out +PROVIDE ( calloc = 0x4000bee4 ); +PROVIDE ( free = 0x4000beb8 ); PROVIDE ( _free_r = 0x4000bbcc ); PROVIDE ( _getpid_r = 0x4000bcfc ); PROVIDE ( __getreent = 0x4000be8c ); @@ -51,8 +53,10 @@ PROVIDE ( _lock_release = 0x4000be64 ); PROVIDE ( _lock_release_recursive = 0x4000be78 ); PROVIDE ( _lock_try_acquire = 0x4000be3c ); PROVIDE ( _lock_try_acquire_recursive = 0x4000be50 ); +PROVIDE ( malloc = 0x4000bea0 ); PROVIDE ( _malloc_r = 0x4000bbb4 ); PROVIDE ( _raise_r = 0x4000bc70 ); +PROVIDE ( realloc = 0x4000becc ); PROVIDE ( _realloc_r = 0x4000bbe0 ); PROVIDE ( _sbrk_r = 0x4000bce4 ); PROVIDE ( _system_r = 0x4000bc10 ); @@ -67,13 +71,9 @@ PROVIDE ( _times_r = 0x4000bc40 ); as the first argument. */ -calloc = 0x4000bee4; close = 0x40001778; -free = 0x4000beb8; -malloc = 0x4000bea0; open = 0x4000178c; read = 0x400017dc; -realloc = 0x4000becc; sbrk = 0x400017f4; times = 0x40001808; write = 0x4000181c; diff --git a/components/newlib/CMakeLists.txt b/components/newlib/CMakeLists.txt index 6cb6fb8e51..a5bae29adf 100644 --- a/components/newlib/CMakeLists.txt +++ b/components/newlib/CMakeLists.txt @@ -1,14 +1,15 @@ -set(COMPONENT_SRCS "locks.c" +set(COMPONENT_SRCS "heap.c" + "locks.c" + "poll.c" "pthread.c" "random.c" "reent_init.c" "select.c" - "poll.c" "syscall_table.c" "syscalls.c" "termios.c" - "utime.c" - "time.c") + "time.c" + "utime.c") set(COMPONENT_ADD_INCLUDEDIRS platform_include) @@ -25,9 +26,11 @@ if(GCC_NOT_5_2_0) set(COMPONENT_ADD_LDFRAGMENTS esp32-spiram-rom-functions-c.lf) endif() - # Forces the linker to include locks.o from this component, which - # replaces weak locking functions defined in libc.a:locks.o + # Forces the linker to include locks, heap, and syscalls from this component, + # instead of the implementations provided by newlib. set(EXTRA_LINK_FLAGS "-u newlib_include_locks_impl") + list(APPEND EXTRA_LINK_FLAGS "-u newlib_include_heap_impl") + list(APPEND EXTRA_LINK_FLAGS "-u newlib_include_syscalls_impl") else() # Remove this section when GCC 5.2.0 is no longer supported @@ -54,6 +57,8 @@ else() endif() set(COMPONENT_REQUIRES vfs) # for sys/ioctl.h +list(APPEND COMPONENT_ADD_LDFRAGMENTS newlib.lf) + register_component() if (LIB_PATH) @@ -61,7 +66,7 @@ if (LIB_PATH) endif() target_link_libraries(${COMPONENT_TARGET} ${LIBC} ${LIBM}) -set_source_files_properties(syscalls.c PROPERTIES COMPILE_FLAGS -fno-builtin) +set_source_files_properties(heap.c PROPERTIES COMPILE_FLAGS -fno-builtin) if(EXTRA_LINK_FLAGS) target_link_libraries(${COMPONENT_TARGET} "${EXTRA_LINK_FLAGS}") diff --git a/components/newlib/component.mk b/components/newlib/component.mk index 008497acef..1f99816aa9 100644 --- a/components/newlib/component.mk +++ b/components/newlib/component.mk @@ -7,16 +7,19 @@ else # CONFIG_NEWLIB_NANO_FORMAT LIBC := c endif # CONFIG_NEWLIB_NANO_FORMAT -COMPONENT_ADD_LDFLAGS := -l$(LIBC) -lm -lnewlib +# Order of linking matters: libnewlib.a should go before libc.a +COMPONENT_ADD_LDFLAGS := -lnewlib -l$(LIBC) -lm COMPONENT_ADD_INCLUDEDIRS := platform_include ifdef CONFIG_SPIRAM_CACHE_WORKAROUND COMPONENT_ADD_LDFRAGMENTS := esp32-spiram-rom-functions-c.lf endif -# Forces the linker to include locks.o from this component, which -# replaces weak locking functions defined in libc.a:locks.o +# Forces the linker to include locks, heap, and syscalls from this component, +# instead of the implementations provided by newlib. COMPONENT_ADD_LDFLAGS += -u newlib_include_locks_impl +COMPONENT_ADD_LDFLAGS += -u newlib_include_heap_impl +COMPONENT_ADD_LDFLAGS += -u newlib_include_syscalls_impl else # GCC_NOT_5_2_0 # Remove this section when GCC 5.2.0 is no longer supported @@ -44,4 +47,6 @@ COMPONENT_ADD_LINKER_DEPS := $(LIBC_PATH) $(LIBM_PATH) COMPONENT_ADD_INCLUDEDIRS := platform_include include endif # GCC_NOT_5_2_0 -syscalls.o: CFLAGS += -fno-builtin +COMPONENT_ADD_LDFRAGMENTS += newlib.lf + +heap.o: CFLAGS += -fno-builtin diff --git a/components/newlib/heap.c b/components/newlib/heap.c new file mode 100644 index 0000000000..37380a3474 --- /dev/null +++ b/components/newlib/heap.c @@ -0,0 +1,126 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "esp_heap_caps.h" + + +/* + These contain the business logic for the malloc() and realloc() implementation. Because of heap tracing + wrapping reasons, we do not want these to be a public api, however, so they're not defined publicly. +*/ +extern void *heap_caps_malloc_default( size_t size ); +extern void *heap_caps_realloc_default( void *ptr, size_t size ); + + +void* malloc(size_t size) +{ + return heap_caps_malloc_default(size); +} + +void* calloc(size_t n, size_t size) +{ + return _calloc_r(_REENT, n, size); +} + +void* realloc(void* ptr, size_t size) +{ + return heap_caps_realloc_default(ptr, size); +} + +void free(void *ptr) +{ + heap_caps_free(ptr); +} + +void* _malloc_r(struct _reent *r, size_t size) +{ + return heap_caps_malloc_default(size); +} + +void _free_r(struct _reent *r, void* ptr) +{ + heap_caps_free(ptr); +} + +void* _realloc_r(struct _reent *r, void* ptr, size_t size) +{ + return heap_caps_realloc_default( ptr, size ); +} + +void* _calloc_r(struct _reent *r, size_t nmemb, size_t size) +{ + void *result; + size_t size_bytes; + if (__builtin_mul_overflow(nmemb, size, &size_bytes)) { + return NULL; + } + + result = heap_caps_malloc_default(size_bytes); + if (result != NULL) { + bzero(result, size_bytes); + } + return result; +} + +/* No-op function, used to force linking this file, + instead of the heap implementation from newlib. + */ +void newlib_include_heap_impl() +{ +} + +/* The following functions are implemented by newlib's heap allocator, + but aren't available in the heap component. + Define them as non-functional stubs here, so that the application + can not cause the newlib heap implementation to be linked in + */ +void* memalign(size_t alignment, size_t n) +{ + extern void memalign_function_was_linked_but_unsupported_in_esp_idf(void); + memalign_function_was_linked_but_unsupported_in_esp_idf(); + return NULL; +} + +int malloc_trim(size_t pad) +{ + return 0; // indicates failure +} + +size_t malloc_usable_size(void* p) +{ + return 0; +} + +void malloc_stats() +{ +} + +int mallopt(int parameter_number, int parameter_value) +{ + return 0; // indicates failure +} + +struct mallinfo mallinfo() +{ + struct mallinfo dummy = {0}; + return dummy; +} + +void* valloc(size_t n) __attribute__((alias("malloc"))); +void* pvalloc(size_t n) __attribute__((alias("malloc"))); +void cfree(void* p) __attribute__((alias("free"))); diff --git a/components/newlib/newlib.lf b/components/newlib/newlib.lf new file mode 100644 index 0000000000..59d3ace559 --- /dev/null +++ b/components/newlib/newlib.lf @@ -0,0 +1,6 @@ +# Places the heap related functions from heap.c into IRAM + +[mapping:newlib] +archive: libnewlib.a +entries: + heap (noflash) diff --git a/components/newlib/syscalls.c b/components/newlib/syscalls.c index d1c06a472f..899f21d488 100644 --- a/components/newlib/syscalls.c +++ b/components/newlib/syscalls.c @@ -14,54 +14,13 @@ #include #include +#include #include #include #include #include -#include -#include "esp_attr.h" -#include "freertos/FreeRTOS.h" -#include "esp_heap_caps.h" -/* - These contain the business logic for the malloc() and realloc() implementation. Because of heap tracing - wrapping reasons, we do not want these to be a public api, however, so they're not defined publicly. -*/ -extern void *heap_caps_malloc_default( size_t size ); -extern void *heap_caps_realloc_default( void *ptr, size_t size ); - - -void* IRAM_ATTR _malloc_r(struct _reent *r, size_t size) -{ - return heap_caps_malloc_default( size ); -} - -void IRAM_ATTR _free_r(struct _reent *r, void* ptr) -{ - heap_caps_free( ptr ); -} - -void* IRAM_ATTR _realloc_r(struct _reent *r, void* ptr, size_t size) -{ - return heap_caps_realloc_default( ptr, size ); -} - -void* IRAM_ATTR _calloc_r(struct _reent *r, size_t nmemb, size_t size) -{ - void *result; - size_t size_bytes; - if (__builtin_mul_overflow(nmemb, size, &size_bytes)) { - return NULL; - } - - result = malloc(size_bytes); - if (result != NULL) { - bzero(result, size_bytes); - } - return result; -} - int _system_r(struct _reent *r, const char *str) { __errno_r(r) = ENOSYS; @@ -95,3 +54,9 @@ void _exit(int __status) abort(); } +/* No-op function, used to force linking this file, + instead of the syscalls implementation from libgloss. + */ +void newlib_include_syscalls_impl() +{ +}