]>
Commit | Line | Data |
---|---|---|
052b6a6c | 1 | /* Machine-dependent ELF startup code. PowerPC version. |
9759bbf1 | 2 | Copyright (C) 1995-2000, 2002, 2004, 2005, 2006 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 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
9759bbf1 UD |
17 | Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA |
18 | 02110-1301 USA. */ | |
052b6a6c UD |
19 | |
20 | #include <sysdep.h> | |
21 | ||
22 | /* Initial entry point code for the dynamic linker. | |
23 | The C function `_dl_start' is the real entry point; | |
24 | its return value is the user program's entry point. */ | |
25 | ENTRY(_start) | |
26 | /* We start with the following on the stack, from top: | |
27 | argc (4 bytes); | |
28 | arguments for program (terminated by NULL); | |
29 | environment variables (terminated by NULL); | |
30 | arguments for the program loader. */ | |
31 | ||
32 | /* Call _dl_start with one parameter pointing at argc */ | |
217eb19b | 33 | mr r3,r1 |
052b6a6c UD |
34 | /* (we have to frob the stack pointer a bit to allow room for |
35 | _dl_start to save the link register). */ | |
217eb19b UD |
36 | li r4,0 |
37 | addi r1,r1,-16 | |
38 | stw r4,0(r1) | |
052b6a6c UD |
39 | bl _dl_start@local |
40 | ||
5a59a3a5 | 41 | /* FALLTHRU */ |
9759bbf1 | 42 | _dl_start_user: |
052b6a6c UD |
43 | /* Now, we do our main work of calling initialisation procedures. |
44 | The ELF ABI doesn't say anything about parameters for these, | |
45 | so we just pass argc, argv, and the environment. | |
46 | Changing these is strongly discouraged (not least because argc is | |
47 | passed by value!). */ | |
48 | ||
49 | /* Put our GOT pointer in r31, */ | |
99c7f870 UD |
50 | bcl 20,31,1f |
51 | 1: mflr r31 | |
52 | addis r31,r31,_GLOBAL_OFFSET_TABLE_-1b@ha | |
53 | addi r31,r31,_GLOBAL_OFFSET_TABLE_-1b@l | |
052b6a6c | 54 | /* the address of _start in r30, */ |
217eb19b | 55 | mr r30,r3 |
5a59a3a5 | 56 | /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ |
5688da55 | 57 | lwz r28,_rtld_global@got(r31) |
217eb19b UD |
58 | lwz r29,_dl_argc@got(r31) |
59 | lwz r27,_dl_argv@got(r31) | |
5a59a3a5 | 60 | |
b6299091 | 61 | /* Call _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1). */ |
217eb19b | 62 | lwz r3,0(r28) |
5a59a3a5 GK |
63 | lwz r4,0(r29) |
64 | lwz r5,0(r27) | |
65 | slwi r6,r4,2 | |
66 | add r6,r5,r6 | |
67 | addi r6,r6,4 | |
7969407a | 68 | bl _dl_init_internal@local |
ec215d43 | 69 | |
052b6a6c UD |
70 | /* Now, to conform to the ELF ABI, we have to: */ |
71 | /* Pass argc (actually _dl_argc) in r3; */ | |
217eb19b | 72 | lwz r3,0(r29) |
052b6a6c | 73 | /* pass argv (actually _dl_argv) in r4; */ |
217eb19b | 74 | lwz r4,0(r27) |
052b6a6c | 75 | /* pass envp (actually _dl_argv+_dl_argc+1) in r5; */ |
217eb19b UD |
76 | slwi r5,r3,2 |
77 | add r6,r4,r5 | |
78 | addi r5,r6,4 | |
052b6a6c | 79 | /* pass the auxilary vector in r6. This is passed to us just after _envp. */ |
217eb19b UD |
80 | 2: lwzu r0,4(r6) |
81 | cmpwi r0,0 | |
052b6a6c | 82 | bne 2b |
217eb19b | 83 | addi r6,r6,4 |
052b6a6c | 84 | /* Pass a termination function pointer (in this case _dl_fini) in r7. */ |
217eb19b | 85 | lwz r7,_dl_fini@got(r31) |
052b6a6c | 86 | /* Now, call the start function in r30... */ |
217eb19b | 87 | mtctr r30 |
052b6a6c UD |
88 | /* Pass the stack pointer in r1 (so far so good), pointing to a NULL value. |
89 | (This lets our startup code distinguish between a program linked statically, | |
90 | which linux will call with argc on top of the stack which will hopefully | |
91 | never be zero, and a dynamically linked program which will always have | |
92 | a NULL on the top of the stack). | |
93 | Take the opportunity to clear LR, so anyone who accidentally returns | |
94 | from _start gets SEGV. Also clear the next few words of the stack. */ | |
95 | ||
9759bbf1 | 96 | _dl_main_dispatch: |
217eb19b UD |
97 | li r31,0 |
98 | stw r31,0(r1) | |
99 | mtlr r31 | |
100 | stw r31,4(r1) | |
101 | stw r31,8(r1) | |
102 | stw r31,12(r1) | |
052b6a6c UD |
103 | /* Go do it! */ |
104 | bctr | |
105 | END(_start) |