From 08334b8a5da590f719a949935daf648b8bd9651c Mon Sep 17 00:00:00 2001 From: Alberto Nidasio <alberto.nidasio@skywarder.eu> Date: Mon, 20 Jan 2025 14:13:37 +0100 Subject: [PATCH] [WIP] Added tests entrypoints for processes --- .../exception_unwinding/CMakeLists.txt | 40 ++++++++++++++++ .../exception_unwinding/debugging_notes.md | 34 +++++++++++++ .../how_to_debug_with_clang.md | 21 ++++++++ .../exception_unwinding/main.cpp | 16 +++++++ .../extern_const/CMakeLists.txt | 42 ++++++++++++++++ .../processes_tests/extern_const/main.cpp | 14 ++++++ .../processes_tests/processes_patch_recap.md | 48 +++++++++++++++++++ 7 files changed, 215 insertions(+) create mode 100644 miosix/_tools/processes_tests/exception_unwinding/CMakeLists.txt create mode 100644 miosix/_tools/processes_tests/exception_unwinding/debugging_notes.md create mode 100644 miosix/_tools/processes_tests/exception_unwinding/how_to_debug_with_clang.md create mode 100644 miosix/_tools/processes_tests/exception_unwinding/main.cpp create mode 100644 miosix/_tools/processes_tests/extern_const/CMakeLists.txt create mode 100644 miosix/_tools/processes_tests/extern_const/main.cpp create mode 100644 miosix/_tools/processes_tests/processes_patch_recap.md diff --git a/miosix/_tools/processes_tests/exception_unwinding/CMakeLists.txt b/miosix/_tools/processes_tests/exception_unwinding/CMakeLists.txt new file mode 100644 index 00000000..ab938ed5 --- /dev/null +++ b/miosix/_tools/processes_tests/exception_unwinding/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright (C) 2024 by Skyward +# +# This program is free software; you can redistribute it and/or +# it under the terms of the GNU General Public License as published +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# As a special exception, if other files instantiate templates or use +# macros or inline functions from this file, or you compile this file +# and link it with other works to produce a work based on this file, +# this file does not by itself cause the resulting work to be covered +# by the GNU General Public License. However the source code for this +# file must still be made available in accordance with the GNU +# Public License. This exception does not invalidate any other +# why a work based on this file might be covered by the GNU General +# Public License. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/> + +cmake_minimum_required(VERSION 3.16) + +project(ProcessesExamples C CXX ASM) + +# Set Miosix definitions and options +add_compile_definitions($<$<COMPILE_LANGUAGE:C,CXX>:MIOSIX_SKIP_SETTINGS_EDIT>) +set(MIOSIX_OPT_BOARD stm32f429zi_stm32f4discovery CACHE STRING "Target board") +set(MIOSIX_LINKER_SCRIPT stm32_2m+stm32_2m+8m_xram.ld CACHE FILEPATH "Linker script") + +add_subdirectory(../../.. miosix EXCLUDE_FROM_ALL) +include(LinkTarget) + +# Kernel level program +add_executable(main main.cpp) +miosix_link_target(main) diff --git a/miosix/_tools/processes_tests/exception_unwinding/debugging_notes.md b/miosix/_tools/processes_tests/exception_unwinding/debugging_notes.md new file mode 100644 index 00000000..66828dab --- /dev/null +++ b/miosix/_tools/processes_tests/exception_unwinding/debugging_notes.md @@ -0,0 +1,34 @@ +# When compiling with `clang` + +`__cxa_throw` gets called with: + +``` +__cxxabiv1::__cxa_throw (obj=0xd0002348, tinfo=0x801fa84 <typeinfo for int>, dest=0x0) +``` + +These 3 parameters are (from [The Secret Life of C++: Day 3: Exceptions](https://www.mit.edu/~sipb-iap/2004/inside-c/day3/exceptions.html)): + +- An exception object +- A typeinfo for that object +- A pointer to the destructor to call when we are done with that object. + +They are correct because: + +- The exception object address is returned from `__cxa_allocate_exception`, and by reading that address from memory the correct value (1) is found +- The exception object is an `int` +- There is no constructor + +`__cxa_throw` is defined in `miosix/_tools/compiler/gcc-9.2.0-mp3.2/gcc-9.2.0/libstdc++-v3/libsupc++/eh_throw.cc:75`. + +`__cxa_throw` calls `_Unwind_RaiseException` from `gcc-9.2.0/libgcc/config/arm/libunwind.S:356` but this is just a wrapper for `__gnu_Unwind_RaiseException` in `gcc-9.2.0/libgcc/unwind-arm-common.inc:429`. + +``` +__gnu_Unwind_RaiseException (ucbp=0xd00022f0, entry_vrs=0xd0001a74) +``` + +Where the parameters are: + +- `ucbp` is the pointer to the unwind control block, which contains information about the exception being raised. It is used to manage the state of the exception. +- `entry_vrs` is the pointer to a structure that contains the virtual register set for pahse 2 of the unsinding process. This holds the state of the registers at the point where the exception was raised and is used to restore the state when transferring control to a catch block or cleanup code. + +In `__gnu_Unwind_RaiseException` the personality routing gets called through `UCB_PR_ADDR`. diff --git a/miosix/_tools/processes_tests/exception_unwinding/how_to_debug_with_clang.md b/miosix/_tools/processes_tests/exception_unwinding/how_to_debug_with_clang.md new file mode 100644 index 00000000..9084095e --- /dev/null +++ b/miosix/_tools/processes_tests/exception_unwinding/how_to_debug_with_clang.md @@ -0,0 +1,21 @@ +Compile and flash with: + +```shell +cmake -DCMAKE_BUILD_TYPE=Debug -Bbuild -DCMAKE_TOOLCHAIN_FILE=../../../cmake/Toolchains/clang.cmake +cmake --build build -j 16 --target main_program +``` + +Run OpenOCD: + +```shell +openocd -f /home/alberton/Documents/CTO/miosix-kernel/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/stm32f4discovery.cfg +``` + +Run `gdb`: + +```shell +gdb build/main.elf +(gdb) target remote :3333 +``` + +`monitor reset halt` to reset the board. diff --git a/miosix/_tools/processes_tests/exception_unwinding/main.cpp b/miosix/_tools/processes_tests/exception_unwinding/main.cpp new file mode 100644 index 00000000..6b62dfc0 --- /dev/null +++ b/miosix/_tools/processes_tests/exception_unwinding/main.cpp @@ -0,0 +1,16 @@ +#include <cstdio> + +void __attribute__((noinline)) f() +{ + throw 1; +} + +int main() try { + puts("in"); + f(); + puts("out"); + return 0; +} catch(int& e) { + puts("exc"); + return e; +} diff --git a/miosix/_tools/processes_tests/extern_const/CMakeLists.txt b/miosix/_tools/processes_tests/extern_const/CMakeLists.txt new file mode 100644 index 00000000..749fddec --- /dev/null +++ b/miosix/_tools/processes_tests/extern_const/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (C) 2024 by Skyward +# +# This program is free software; you can redistribute it and/or +# it under the terms of the GNU General Public License as published +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# As a special exception, if other files instantiate templates or use +# macros or inline functions from this file, or you compile this file +# and link it with other works to produce a work based on this file, +# this file does not by itself cause the resulting work to be covered +# by the GNU General Public License. However the source code for this +# file must still be made available in accordance with the GNU +# Public License. This exception does not invalidate any other +# why a work based on this file might be covered by the GNU General +# Public License. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/> + +cmake_minimum_required(VERSION 3.16) + +project(ProcessesExamples C CXX ASM) + +# Set Miosix definitions and options +add_compile_definitions($<$<COMPILE_LANGUAGE:C,CXX>:MIOSIX_SKIP_SETTINGS_EDIT>) +set(MIOSIX_OPT_BOARD stm32f767zi_nucleo CACHE STRING "Target board") +set(MIOSIX_LINKER_SCRIPT stm32_2m+384k_ram_processes.ld CACHE FILEPATH "Linker script") + +add_subdirectory(../../.. miosix EXCLUDE_FROM_ALL) +add_subdirectory(../../../libsyscalls libsyscalls EXCLUDE_FROM_ALL) + +include(LinkTarget) +include(AddProcess) + +# Processes +miosix_add_process(main main.cpp) diff --git a/miosix/_tools/processes_tests/extern_const/main.cpp b/miosix/_tools/processes_tests/extern_const/main.cpp new file mode 100644 index 00000000..d6104653 --- /dev/null +++ b/miosix/_tools/processes_tests/extern_const/main.cpp @@ -0,0 +1,14 @@ +extern const int aRodata; +extern int aData; +const char str[] = "Hello world\n"; + +int get1() { return aRodata; } + +int get2() { return aData; } + +const char *get3() { return str; } + +int main() +{ + return 0; +} diff --git a/miosix/_tools/processes_tests/processes_patch_recap.md b/miosix/_tools/processes_tests/processes_patch_recap.md new file mode 100644 index 00000000..36b246b5 --- /dev/null +++ b/miosix/_tools/processes_tests/processes_patch_recap.md @@ -0,0 +1,48 @@ +## `extern const` + +In processes compiled with GCC 4.7.3: + +- stuff in `.data` are accessed from the GOT, which is OK +- strings in `.rodata` are accessed PC-relative, which is OK +- consts in `.rodata` are accessed from the GOT, which is WRONG! (more on that later when pointer are involved, though) + +Here's an example: + +```cpp +extern const int aRodata; +extern int aData; +const char str[]="Hello world\n"; + +int get1() { return aRodata; } +int get2() { return aData; } +const char *get3() { return str; } +``` + +Compiled with `arm-miosix-eabi-gcc -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base -O2 -S processes.c`: + +```asm +get1: + ldr r3, .L3 + ldr r3, [r9, r3] + ldr r0, [r3] + bx lr + +get2: + ldr r3, .L6 + ldr r3, [r9, r3] + ldr r0, [r3] + bx lr + + +get3: + ldr r0, .L9 +.LPIC0: + add r0, pc + bx lr +``` + +`get1()` is the wrong one, of course. + +What usually masks the issue is constant folding. Unless it's an extern const the value gets folded and the problem does not arise. + +Solution: The previous patch relied on a GCC function, `decl_readonly_section()` to check whether the global variable to be loaded is const or not, but that function missed a few cases, so a dedicated function, the `miosix_processes_ref_demux()` function was added in `arm.c`. This new function handles the corner cases better, and also allows to fix some of the next issues. -- GitLab