1 | /* Copyright (C) 1995-2022 Free Software Foundation, Inc. |
2 | |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public License as |
7 | published by the Free Software Foundation; either version 2.1 of the |
8 | License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library. If not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <sysdep.h> |
20 | |
21 | /* This is the canonical entry point, usually the first thing in the text |
22 | segment. |
23 | |
24 | Note that the code in the .init section has already been run. |
25 | This includes _init and _libc_init |
26 | |
27 | |
28 | At this entry point, most registers' values are unspecified, except: |
29 | |
30 | x0/w0 Contains a function pointer to be registered with `atexit'. |
31 | This is how the dynamic linker arranges to have DT_FINI |
32 | functions called for shared libraries that have been loaded |
33 | before this code runs. |
34 | |
35 | sp The stack contains the arguments and environment: |
36 | 0(sp) argc |
37 | 8(sp) argv[0] |
38 | ... |
39 | (8*argc)(sp) NULL |
40 | (8*(argc+1))(sp) envp[0] |
41 | ... |
42 | NULL |
43 | */ |
44 | |
45 | .text |
46 | ENTRY(_start) |
47 | /* Create an initial frame with 0 LR and FP */ |
48 | cfi_undefined (x30) |
49 | mov x29, #0 |
50 | mov x30, #0 |
51 | |
52 | /* Setup rtld_fini in argument register */ |
53 | mov x5, x0 |
54 | |
55 | /* Load argc and a pointer to argv */ |
56 | ldr PTR_REG (1), [sp, #0] |
57 | add x2, sp, #PTR_SIZE |
58 | |
59 | /* Setup stack limit in argument register */ |
60 | mov x6, sp |
61 | |
62 | #ifdef PIC |
63 | # ifdef SHARED |
64 | adrp x0, :got:main |
65 | ldr PTR_REG (0), [x0, #:got_lo12:main] |
66 | # else |
67 | adrp x0, __wrap_main |
68 | add x0, x0, :lo12:__wrap_main |
69 | # endif |
70 | #else |
71 | /* Set up the other arguments in registers */ |
72 | MOVL (0, main) |
73 | #endif |
74 | mov x3, #0 /* Used to be init. */ |
75 | mov x4, #0 /* Used to be fini. */ |
76 | |
77 | /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, |
78 | stack_end) */ |
79 | |
80 | /* Let the libc call main and exit with its return code. */ |
81 | bl __libc_start_main |
82 | |
83 | /* should never get here....*/ |
84 | bl abort |
85 | |
86 | #if defined PIC && !defined SHARED |
87 | /* When main is not defined in the executable but in a shared library |
88 | then a wrapper is needed in crt1.o of the static-pie enabled libc, |
89 | because crt1.o and rcrt1.o share code and the later must avoid the |
90 | use of GOT relocations before __libc_start_main is called. */ |
91 | __wrap_main: |
92 | BTI_C |
93 | b main |
94 | #endif |
95 | END(_start) |
96 | |
97 | /* Define a symbol for the first piece of initialized data. */ |
98 | .data |
99 | .globl __data_start |
100 | __data_start: |
101 | .long 0 |
102 | .weak data_start |
103 | data_start = __data_start |
104 | |