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 | |