551b4677c325a5e53120bf089c5bd5a5e323e3a3
[platform/upstream/glibc.git] / sysdeps / arm / elf / start.S
1 /* Startup code for ARM & ELF
2    Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002, 2005, 2008
3    Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    In addition to the permissions in the GNU Lesser General Public
12    License, the Free Software Foundation gives you unlimited
13    permission to link the compiled version of this file with other
14    programs, and to distribute those programs without any restriction
15    coming from the use of this file. (The GNU Lesser General Public
16    License restrictions do apply in other respects; for example, they
17    cover modification of the file, and distribution when not linked
18    into another program.)
19
20    Note that people who make modified versions of this file are not
21    obligated to grant this special exception for their modified
22    versions; it is their choice whether to do so. The GNU Lesser
23    General Public License gives permission to release a modified
24    version without this exception; this exception also makes it
25    possible to release a modified version which carries forward this
26    exception.
27
28    The GNU C Library is distributed in the hope that it will be useful,
29    but WITHOUT ANY WARRANTY; without even the implied warranty of
30    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31    Lesser General Public License for more details.
32
33    You should have received a copy of the GNU Lesser General Public
34    License along with the GNU C Library; if not, write to the Free
35    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
36    02111-1307 USA.  */
37
38 /* This is the canonical entry point, usually the first thing in the text
39    segment.
40
41         Note that the code in the .init section has already been run.
42         This includes _init and _libc_init
43
44
45         At this entry point, most registers' values are unspecified, except:
46
47    a1           Contains a function pointer to be registered with `atexit'.
48                 This is how the dynamic linker arranges to have DT_FINI
49                 functions called for shared libraries that have been loaded
50                 before this code runs.
51
52    sp           The stack contains the arguments and environment:
53                 0(sp)                   argc
54                 4(sp)                   argv[0]
55                 ...
56                 (4*argc)(sp)            NULL
57                 (4*(argc+1))(sp)        envp[0]
58                 ...
59                                         NULL
60 */
61
62 #if defined(__ARM_EABI__)
63 /* Tag_ABI_align8_preserved: This code preserves 8-byte
64    alignment in any callee.  */
65         .eabi_attribute 25, 1
66 /* Tag_ABI_align8_needed: This code may require 8-byte alignment from
67    the caller.  */
68         .eabi_attribute 24, 1
69 #endif
70
71 #if defined(__thumb2__)
72         .thumb
73         .syntax unified
74 #endif
75
76         .text
77         .globl _start
78         .type _start,#function
79 _start:
80 #if !defined(__USING_SJLJ_EXCEPTIONS__)
81        /* Protect against unhandled exceptions.  */
82        .fnstart
83 #endif
84         /* Clear the frame pointer and link register since this is the outermost frame. */
85         mov fp, #0
86         mov lr, #0
87
88         /* Pop argc off the stack and save a pointer to argv */
89         ldr a2, [sp], #4
90         mov a3, sp
91
92         /* Push stack limit */
93         str a3, [sp, #-4]!
94
95         /* Push rtld_fini */
96         str a1, [sp, #-4]!
97
98 #ifdef SHARED
99         ldr sl, .L_GOT
100         adr a4, .L_GOT
101         add sl, sl, a4
102
103         ldr ip, .L_GOT+4        /* __libc_csu_fini */
104         ldr ip, [sl, ip]
105
106         str ip, [sp, #-4]!      /* Push __libc_csu_fini */
107
108         ldr a4, .L_GOT+8        /* __libc_csu_init */
109         ldr a4, [sl, a4]
110
111         ldr a1, .L_GOT+12       /* main */
112         ldr a1, [sl, a1]
113
114         /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
115         /* Let the libc call main and exit with its return code.  */
116         bl __libc_start_main(PLT)
117 #else
118         /* Fetch address of __libc_csu_fini */
119         ldr ip, =__libc_csu_fini
120
121         /* Push __libc_csu_fini */
122         str ip, [sp, #-4]!
123
124         /* Set up the other arguments in registers */
125         ldr a1, =main
126         ldr a4, =__libc_csu_init
127
128         /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
129         /* Let the libc call main and exit with its return code.  */
130         bl __libc_start_main
131 #endif
132
133         /* should never get here....*/
134         bl abort
135
136 #ifdef SHARED
137         .align 2
138 .L_GOT:
139         .word _GLOBAL_OFFSET_TABLE_ - .L_GOT
140         .word __libc_csu_fini(GOT)
141         .word __libc_csu_init(GOT)
142         .word main(GOT)
143 #endif
144
145
146 #if !defined(__USING_SJLJ_EXCEPTIONS__)
147        .cantunwind
148        .fnend
149 #endif
150
151 /* Define a symbol for the first piece of initialized data.  */
152         .data
153         .globl __data_start
154 __data_start:
155         .long 0
156         .weak data_start
157         data_start = __data_start