1 | /* Machine-dependent ELF startup code. PowerPC version. |
2 | Copyright (C) 1995-2024 Free Software Foundation, Inc. |
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 |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the 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 | /* Initial entry point code for the dynamic linker. |
22 | The C function `_dl_start' is the real entry point; |
23 | its return value is the user program's entry point. */ |
24 | ENTRY(_start) |
25 | /* We start with the following on the stack, from top: |
26 | argc (4 bytes); |
27 | arguments for program (terminated by NULL); |
28 | environment variables (terminated by NULL); |
29 | arguments for the program loader. */ |
30 | |
31 | /* Call _dl_start with one parameter pointing at argc */ |
32 | mr r3,r1 |
33 | /* (we have to frob the stack pointer a bit to allow room for |
34 | _dl_start to save the link register). */ |
35 | li r4,0 |
36 | addi r1,r1,-16 |
37 | cfi_adjust_cfa_offset (16) |
38 | /* Mark lr as undefined to stop unwinding. */ |
39 | cfi_undefined (lr) |
40 | stw r4,0(r1) |
41 | bl _dl_start@local |
42 | |
43 | /* FALLTHRU */ |
44 | _dl_start_user: |
45 | /* Now, we do our main work of calling initialisation procedures. |
46 | The ELF ABI doesn't say anything about parameters for these, |
47 | so we just pass argc, argv, and the environment. |
48 | Changing these is strongly discouraged (not least because argc is |
49 | passed by value!). */ |
50 | |
51 | /* Put our GOT pointer in r31, */ |
52 | SETUP_GOT_ACCESS(r31,got_label) |
53 | addis r31,r31,_GLOBAL_OFFSET_TABLE_-got_label@ha |
54 | addi r31,r31,_GLOBAL_OFFSET_TABLE_-got_label@l |
55 | /* the address of _start in r30, */ |
56 | mr r30,r3 |
57 | /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ |
58 | lwz r28,_rtld_local@got(r31) |
59 | lwz r29,_dl_argc@got(r31) |
60 | lwz r27,__GI__dl_argv@got(r31) |
61 | |
62 | /* Call _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1). */ |
63 | lwz r3,0(r28) |
64 | lwz r4,0(r29) |
65 | lwz r5,0(r27) |
66 | slwi r6,r4,2 |
67 | add r6,r5,r6 |
68 | addi r6,r6,4 |
69 | bl _dl_init@local |
70 | |
71 | /* Now, to conform to the ELF ABI, we have to: */ |
72 | /* Pass argc (actually _dl_argc) in r3; */ |
73 | lwz r3,0(r29) |
74 | /* pass argv (actually _dl_argv) in r4; */ |
75 | lwz r4,0(r27) |
76 | /* pass envp (actually _dl_argv+_dl_argc+1) in r5; */ |
77 | slwi r5,r3,2 |
78 | add r6,r4,r5 |
79 | addi r5,r6,4 |
80 | /* pass the auxiliary vector in r6. This is passed to us just after _envp. */ |
81 | 2: lwzu r0,4(r6) |
82 | cmpwi r0,0 |
83 | bne 2b |
84 | addi r6,r6,4 |
85 | /* Pass a termination function pointer (in this case _dl_fini) in r7. */ |
86 | lwz r7,_dl_fini@got(r31) |
87 | /* Now, call the start function in r30... */ |
88 | mtctr r30 |
89 | /* Pass the stack pointer in r1 (so far so good), pointing to a NULL value. |
90 | (This lets our startup code distinguish between a program linked statically, |
91 | which linux will call with argc on top of the stack which will hopefully |
92 | never be zero, and a dynamically linked program which will always have |
93 | a NULL on the top of the stack). |
94 | Take the opportunity to clear LR, so anyone who accidentally returns |
95 | from _start gets SEGV. Also clear the next few words of the stack. */ |
96 | |
97 | _dl_main_dispatch: |
98 | li r31,0 |
99 | stw r31,0(r1) |
100 | mtlr r31 |
101 | stw r31,4(r1) |
102 | stw r31,8(r1) |
103 | stw r31,12(r1) |
104 | /* Go do it! */ |
105 | bctr |
106 | END(_start) |
107 | |