From 02fe51719751e14dcd711e9e9055d141f0d3f0d1 Mon Sep 17 00:00:00 2001 From: alrvid <126816223+alrvid@users.noreply.github.com> Date: Thu, 31 Aug 2023 15:17:56 +0200 Subject: [PATCH 1/3] Fix that malloc() doesn't return a null pointer for too large allocations The _sbrk() function wasn't implemented. It's used by malloc() to request more heap memory. This function must be defined and correctly implemented if we want malloc() to return a null pointer if more space is requested than is available. It already works that way for the Mbed Core (although with a different implementation), but doesn't for the Renesas Core before this addition. --- cores/arduino/main.cpp | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index b13d1a22e..ee5d06678 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -145,4 +145,36 @@ extern "C" __attribute__((weak)) void __cxa_pure_virtual(void); extern "C" __attribute__((weak)) void __cxa_pure_virtual(void) { exit(1); -} \ No newline at end of file +} + +// Used by malloc() to request more heap memory. This function +// must be defined if we want malloc() to return a null pointer +// if more space is requested than is available. Notice that +// there's no support for decrement as the very first action, +// because the result of that is unspecified by the standard, +// so we can do whatever we want in that case. +extern "C" void * _sbrk(ptrdiff_t change) +{ + extern char __HeapBase; // From the linker script + extern char __HeapLimit; // From the linker script + static char *programBreak = nullptr; + + // If malloc() hasn't been called before, then set the program break + // to __HeapBase from the linker script + if (nullptr == programBreak) + { + programBreak = &__HeapBase; + } + // We must return the old program break if everything is ok, so save it + char * const oldProgramBreak = programBreak; + // Check that the new program break doesn't pass __HeapLimit from the + // linker script + if ((programBreak + change) > &__HeapLimit) + { + return (void *) -1; + } + // Update the program break according to the requested amount of heap + // memory + programBreak += change; + return oldProgramBreak; +} From 13a97354c38fc851871b664c6f25e7b6e0dba623 Mon Sep 17 00:00:00 2001 From: alrvid <126816223+alrvid@users.noreply.github.com> Date: Sat, 2 Sep 2023 12:48:32 +0200 Subject: [PATCH 2/3] Remove _sbrk() function definition This function isn't necessary when the root cause is fixed in the next commit. --- cores/arduino/main.cpp | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index ee5d06678..85e228081 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -146,35 +146,3 @@ extern "C" __attribute__((weak)) void __cxa_pure_virtual(void) { exit(1); } - -// Used by malloc() to request more heap memory. This function -// must be defined if we want malloc() to return a null pointer -// if more space is requested than is available. Notice that -// there's no support for decrement as the very first action, -// because the result of that is unspecified by the standard, -// so we can do whatever we want in that case. -extern "C" void * _sbrk(ptrdiff_t change) -{ - extern char __HeapBase; // From the linker script - extern char __HeapLimit; // From the linker script - static char *programBreak = nullptr; - - // If malloc() hasn't been called before, then set the program break - // to __HeapBase from the linker script - if (nullptr == programBreak) - { - programBreak = &__HeapBase; - } - // We must return the old program break if everything is ok, so save it - char * const oldProgramBreak = programBreak; - // Check that the new program break doesn't pass __HeapLimit from the - // linker script - if ((programBreak + change) > &__HeapLimit) - { - return (void *) -1; - } - // Update the program break according to the requested amount of heap - // memory - programBreak += change; - return oldProgramBreak; -} From b42b234cbe08e92359876f4d4faa12777a2e20cc Mon Sep 17 00:00:00 2001 From: alrvid <126816223+alrvid@users.noreply.github.com> Date: Sat, 2 Sep 2023 12:52:58 +0200 Subject: [PATCH 3/3] Fix bug where malloc() doesn't return a null pointer The malloc() function doesn't return a null pointer for too large requests. The cause is that the _sbrk() function isn't linked from the Renesas FSP as it should be, but instead from the Arm toolchain. This fix makes sure that the correct version of _sbrk() is linked. --- platform.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.txt b/platform.txt index 0d82f606a..5152ab5dd 100644 --- a/platform.txt +++ b/platform.txt @@ -76,7 +76,7 @@ recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DARDUIN recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {build.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" "-L{build.variant.path}" "-T{build.variant.path}/fsp.ld" {object_files} -Wl,--start-group {compiler.fsp} "{build.path}/{archive_file}" {compiler.fsp.extra_ldflags} {compiler.libraries.ldflags} -Wl,--end-group "-Wl,-Map,{build.path}/{build.project_name}.map" +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {build.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" "-L{build.variant.path}" "-T{build.variant.path}/fsp.ld" {object_files} -Wl,--whole-archive -Wl,--start-group {compiler.fsp} "{build.path}/{archive_file}" -Wl,--no-whole-archive {compiler.fsp.extra_ldflags} {compiler.libraries.ldflags} -Wl,--end-group "-Wl,-Map,{build.path}/{build.project_name}.map" ## Create output (bin file) recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.bin.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"