]>
Commit | Line | Data |
---|---|---|
052b6a6c | 1 | /* Machine-dependent ELF startup code. PowerPC version. |
dff8da6b | 2 | Copyright (C) 1995-2024 Free Software Foundation, Inc. |
052b6a6c UD |
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 | |
41bdb6e2 AJ |
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. | |
052b6a6c UD |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
052b6a6c | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 | 16 | License along with the GNU C Library; if not, see |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
052b6a6c UD |
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 */ | |
217eb19b | 32 | mr r3,r1 |
052b6a6c UD |
33 | /* (we have to frob the stack pointer a bit to allow room for |
34 | _dl_start to save the link register). */ | |
217eb19b UD |
35 | li r4,0 |
36 | addi r1,r1,-16 | |
6ca8284e AS |
37 | cfi_adjust_cfa_offset (16) |
38 | /* Mark lr as undefined to stop unwinding. */ | |
39 | cfi_undefined (lr) | |
217eb19b | 40 | stw r4,0(r1) |
052b6a6c UD |
41 | bl _dl_start@local |
42 | ||
5a59a3a5 | 43 | /* FALLTHRU */ |
9759bbf1 | 44 | _dl_start_user: |
052b6a6c UD |
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, */ | |
91d2a845 WS |
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 | |
052b6a6c | 55 | /* the address of _start in r30, */ |
217eb19b | 56 | mr r30,r3 |
5a59a3a5 | 57 | /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ |
37fb1dc0 | 58 | lwz r28,_rtld_local@got(r31) |
217eb19b | 59 | lwz r29,_dl_argc@got(r31) |
4243cbea | 60 | lwz r27,__GI__dl_argv@got(r31) |
5a59a3a5 | 61 | |
b6299091 | 62 | /* Call _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1). */ |
217eb19b | 63 | lwz r3,0(r28) |
5a59a3a5 GK |
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 | |
c5684fdb | 69 | bl _dl_init@local |
ec215d43 | 70 | |
052b6a6c UD |
71 | /* Now, to conform to the ELF ABI, we have to: */ |
72 | /* Pass argc (actually _dl_argc) in r3; */ | |
217eb19b | 73 | lwz r3,0(r29) |
052b6a6c | 74 | /* pass argv (actually _dl_argv) in r4; */ |
217eb19b | 75 | lwz r4,0(r27) |
052b6a6c | 76 | /* pass envp (actually _dl_argv+_dl_argc+1) in r5; */ |
217eb19b UD |
77 | slwi r5,r3,2 |
78 | add r6,r4,r5 | |
79 | addi r5,r6,4 | |
2ccdea26 | 80 | /* pass the auxiliary vector in r6. This is passed to us just after _envp. */ |
217eb19b UD |
81 | 2: lwzu r0,4(r6) |
82 | cmpwi r0,0 | |
052b6a6c | 83 | bne 2b |
217eb19b | 84 | addi r6,r6,4 |
052b6a6c | 85 | /* Pass a termination function pointer (in this case _dl_fini) in r7. */ |
217eb19b | 86 | lwz r7,_dl_fini@got(r31) |
052b6a6c | 87 | /* Now, call the start function in r30... */ |
217eb19b | 88 | mtctr r30 |
052b6a6c UD |
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 | ||
9759bbf1 | 97 | _dl_main_dispatch: |
217eb19b UD |
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) | |
052b6a6c UD |
104 | /* Go do it! */ |
105 | bctr | |
106 | END(_start) |