| 1 | //===-- Implementation of _start for aarch64 ------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "startup/linux/do_start.h" |
| 10 | extern "C" [[noreturn]] void _start() { |
| 11 | // Skip the Frame Pointer and the Link Register |
| 12 | // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst |
| 13 | // Section 6.2.3. Note that this only works if the current function |
| 14 | // is not using any callee-saved registers (x19 to x28). If the |
| 15 | // function uses such registers, then their value is pushed on to the |
| 16 | // stack before the frame pointer an link register values. That breaks |
| 17 | // the assumption that stepping over the frame pointer and link register |
| 18 | // will take us to the previous stack pointer. That is the reason why the |
| 19 | // actual business logic of the startup code is pushed into a non-inline |
| 20 | // function do_start so that this function is free of any stack usage. |
| 21 | LIBC_NAMESPACE::app.args = reinterpret_cast<LIBC_NAMESPACE::Args *>( |
| 22 | reinterpret_cast<uintptr_t *>(__builtin_frame_address(0)) + 2); |
| 23 | LIBC_NAMESPACE::do_start(); |
| 24 | } |
| 25 | |