diff options
Diffstat (limited to 'libc/startup')
-rw-r--r-- | libc/startup/baremetal/CMakeLists.txt | 64 | ||||
-rw-r--r-- | libc/startup/baremetal/arm/CMakeLists.txt | 16 | ||||
-rw-r--r-- | libc/startup/baremetal/arm/start.cpp | 92 | ||||
-rw-r--r-- | libc/startup/baremetal/fini.cpp | 8 | ||||
-rw-r--r-- | libc/startup/baremetal/fini.h | 16 | ||||
-rw-r--r-- | libc/startup/baremetal/init.cpp | 10 | ||||
-rw-r--r-- | libc/startup/baremetal/init.h | 18 | ||||
-rw-r--r-- | libc/startup/linux/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libc/startup/linux/do_start.cpp | 2 |
9 files changed, 212 insertions, 15 deletions
diff --git a/libc/startup/baremetal/CMakeLists.txt b/libc/startup/baremetal/CMakeLists.txt index 4faced9..e361000 100644 --- a/libc/startup/baremetal/CMakeLists.txt +++ b/libc/startup/baremetal/CMakeLists.txt @@ -1,11 +1,75 @@ +# TODO: Use generic "add_startup_object" https://github.com/llvm/llvm-project/issues/133156 +function(add_startup_object name) + cmake_parse_arguments( + "ADD_STARTUP_OBJECT" + "ALIAS" # Option argument + "SRC" # Single value arguments + "DEPENDS;COMPILE_OPTIONS" # Multi value arguments + ${ARGN} + ) + + get_fq_target_name(${name} fq_target_name) + if(ADD_STARTUP_OBJECT_ALIAS) + get_fq_deps_list(fq_dep_list ${ADD_STARTUP_OBJECT_DEPENDS}) + add_library(${fq_target_name} ALIAS ${fq_dep_list}) + return() + endif() + + add_object_library( + ${name} + SRCS ${ADD_STARTUP_OBJECT_SRC} + COMPILE_OPTIONS ${ADD_STARTUP_OBJECT_COMPILE_OPTIONS} + ${ADD_STARTUP_OBJECT_UNPARSED_ARGUMENTS} + DEPENDS ${ADD_STARTUP_OBJECT_DEPENDS} + ) + set_target_properties( + ${fq_target_name} + PROPERTIES + OUTPUT_NAME ${name}.o + ) +endfunction() + add_entrypoint_object( init SRCS init.cpp + DEPENDS + libc.hdr.stdint_proxy + libc.src.__support.common + HDRS + init.h ) add_entrypoint_object( fini SRCS fini.cpp + DEPENDS + libc.hdr.stdint_proxy + libc.src.__support.common + HDRS + fini.h +) + +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE}) + add_subdirectory(${LIBC_TARGET_ARCHITECTURE}) +else() + message(WARNING "Cannot build 'crt1.o' for ${LIBC_TARGET_ARCHITECTURE} yet.") + return() +endif() + +add_startup_object( + crt1 + ALIAS + DEPENDS + .${LIBC_TARGET_ARCHITECTURE}.crt1 ) + +add_custom_target(libc-startup) + +set(fq_target_name libc.startup.baremetal.${LIBC_TARGET_ARCHITECTURE}.crt1) +add_dependencies(libc-startup ${fq_target_name}) +install(FILES $<TARGET_OBJECTS:${fq_target_name}> + DESTINATION ${LIBC_INSTALL_LIBRARY_DIR} + RENAME $<TARGET_PROPERTY:${fq_target_name},OUTPUT_NAME> + COMPONENT libc) diff --git a/libc/startup/baremetal/arm/CMakeLists.txt b/libc/startup/baremetal/arm/CMakeLists.txt new file mode 100644 index 0000000..f75bd89 --- /dev/null +++ b/libc/startup/baremetal/arm/CMakeLists.txt @@ -0,0 +1,16 @@ +add_startup_object( + crt1 + SRC + start.cpp + DEPENDS + libc.src.stdlib.atexit + libc.src.stdlib.exit + libc.src.string.memcpy + libc.src.string.memset + libc.startup.baremetal.init + libc.startup.baremetal.fini + COMPILE_OPTIONS + -ffreestanding # To avoid compiler warnings about calling the main function. + -fno-builtin + -Wno-global-constructors # To allow vector table initialization +) diff --git a/libc/startup/baremetal/arm/start.cpp b/libc/startup/baremetal/arm/start.cpp new file mode 100644 index 0000000..123efc4 --- /dev/null +++ b/libc/startup/baremetal/arm/start.cpp @@ -0,0 +1,92 @@ +//===-- Implementation of crt for arm -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/macros/config.h" +#include "src/stdlib/atexit.h" +#include "src/stdlib/exit.h" +#include "src/string/memcpy.h" +#include "src/string/memset.h" +#include "startup/baremetal/fini.h" +#include "startup/baremetal/init.h" + +#include <stdint.h> + +extern "C" { +int main(int argc, char **argv); +void _start(); + +// Semihosting library initialisation if applicable. Required for printf, etc. +[[gnu::weak]] void _platform_init() {} + +// These symbols are provided by the linker. The exact names are not defined by +// a standard. +extern uintptr_t __stack; +extern uintptr_t __data_source[]; +extern uintptr_t __data_start[]; +extern uintptr_t __data_size[]; +extern uintptr_t __bss_start[]; +extern uintptr_t __bss_size[]; + +// Based on +// https://developer.arm.com/documentation/107565/0101/Use-case-examples/Generic-Information/What-is-inside-a-program-image-/Vector-table +void NMI_Handler() {} +void HardFault_Handler() { LIBC_NAMESPACE::exit(1); } +void MemManage_Handler() { LIBC_NAMESPACE::exit(1); } +void BusFault_Handler() { LIBC_NAMESPACE::exit(1); } +void UsageFault_Handler() { LIBC_NAMESPACE::exit(1); } +void SVC_Handler() {} +void DebugMon_Handler() {} +void PendSV_Handler() {} +void SysTick_Handler() {} + +// Architecturally the bottom 7 bits of VTOR are zero, meaning the vector table +// has to be 128-byte aligned, however an implementation can require more bits +// to be zero and Cortex-M23 can require up to 10, so 1024-byte align the vector +// table. +using HandlerType = void (*)(void); +const HandlerType vector_table[] + __attribute__((section(".vectors"), aligned(1024), used)) = { + (HandlerType)&__stack, // SP + _start, // Reset + NMI_Handler, // NMI Handler + HardFault_Handler, // Hard Fault Handlerß + MemManage_Handler, // MPU Fault Han`dler + BusFault_Handler, // Bus Fault Handler + UsageFault_Handler, // Usage Fault Handler + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + SVC_Handler, // SVC Handler + DebugMon_Handler, // Debug Monitor Handler + 0, // Reserved + PendSV_Handler, // PendSV Handler + SysTick_Handler, // SysTick Handler + // Unused +}; +} // extern "C" + +namespace LIBC_NAMESPACE_DECL { +[[noreturn]] void do_start() { + // FIXME: set up the QEMU test environment + + // Perform the equivalent of scatterloading + LIBC_NAMESPACE::memcpy(__data_start, __data_source, (uintptr_t)__data_size); + LIBC_NAMESPACE::memset(__bss_start, '\0', (uintptr_t)__bss_size); + __libc_init_array(); + + _platform_init(); + LIBC_NAMESPACE::atexit(&__libc_fini_array); + LIBC_NAMESPACE::exit(main(0, 0)); +} +} // namespace LIBC_NAMESPACE_DECL + +extern "C" void _start() { + asm volatile("mov sp, %0" : : "r"(&__stack)); + asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start)); +} diff --git a/libc/startup/baremetal/fini.cpp b/libc/startup/baremetal/fini.cpp index 263d7192..66714e2 100644 --- a/libc/startup/baremetal/fini.cpp +++ b/libc/startup/baremetal/fini.cpp @@ -6,17 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "startup/baremetal/fini.h" + #include "src/__support/macros/config.h" #include <stddef.h> -#include <stdint.h> namespace LIBC_NAMESPACE_DECL { -extern "C" { -extern uintptr_t __fini_array_start[]; -extern uintptr_t __fini_array_end[]; -} - using FiniCallback = void(void); extern "C" void __libc_fini_array(void) { diff --git a/libc/startup/baremetal/fini.h b/libc/startup/baremetal/fini.h new file mode 100644 index 0000000..74e9601 --- /dev/null +++ b/libc/startup/baremetal/fini.h @@ -0,0 +1,16 @@ +//===-- Implementation header of __libc_fini_array ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "hdr/stdint_proxy.h" + +extern "C" { +extern uintptr_t __fini_array_start[]; +extern uintptr_t __fini_array_end[]; + +void __libc_fini_array(void); +} // extern "C" diff --git a/libc/startup/baremetal/init.cpp b/libc/startup/baremetal/init.cpp index ce38701..89065fd 100644 --- a/libc/startup/baremetal/init.cpp +++ b/libc/startup/baremetal/init.cpp @@ -6,19 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "startup/baremetal/init.h" + #include "src/__support/macros/config.h" #include <stddef.h> -#include <stdint.h> namespace LIBC_NAMESPACE_DECL { -extern "C" { -extern uintptr_t __preinit_array_start[]; -extern uintptr_t __preinit_array_end[]; -extern uintptr_t __init_array_start[]; -extern uintptr_t __init_array_end[]; -} - using InitCallback = void(void); extern "C" void __libc_init_array(void) { diff --git a/libc/startup/baremetal/init.h b/libc/startup/baremetal/init.h new file mode 100644 index 0000000..6b545db3 --- /dev/null +++ b/libc/startup/baremetal/init.h @@ -0,0 +1,18 @@ +//===-- Implementation header of __libc_init_array ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "hdr/stdint_proxy.h" + +extern "C" { +extern uintptr_t __preinit_array_start[]; +extern uintptr_t __preinit_array_end[]; +extern uintptr_t __init_array_start[]; +extern uintptr_t __init_array_end[]; + +void __libc_init_array(void); +} // extern "C" diff --git a/libc/startup/linux/CMakeLists.txt b/libc/startup/linux/CMakeLists.txt index eaa724e..7af1819 100644 --- a/libc/startup/linux/CMakeLists.txt +++ b/libc/startup/linux/CMakeLists.txt @@ -96,6 +96,7 @@ add_object_library( do_start.h DEPENDS libc.config.app_h + libc.hdr.stdint_proxy libc.include.sys_mman libc.include.sys_syscall libc.include.llvm-libc-macros.link_macros diff --git a/libc/startup/linux/do_start.cpp b/libc/startup/linux/do_start.cpp index ff104c7..94c4ec7 100644 --- a/libc/startup/linux/do_start.cpp +++ b/libc/startup/linux/do_start.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "startup/linux/do_start.h" #include "config/linux/app.h" +#include "hdr/stdint_proxy.h" #include "include/llvm-libc-macros/link-macros.h" #include "src/__support/OSUtil/syscall.h" #include "src/__support/macros/config.h" @@ -17,7 +18,6 @@ #include <linux/auxvec.h> #include <linux/elf.h> -#include <stdint.h> #include <sys/mman.h> #include <sys/syscall.h> |