]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-startup.h
Inital import
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / ldso / ldso / arm / dl-startup.h
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Architecture specific code used by dl-startup.c
4  * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
5  *
6  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
7  */
8
9 #include <features.h>
10
11 #if !defined(__thumb__)
12 __asm__(
13     "   .text\n"
14     "   .globl  _start\n"
15     "   .type   _start,%function\n"
16         "_start:\n"
17         "       @ at start time, all the args are on the stack\n"
18         "       mov     r0, sp\n"
19         "       bl      _dl_start\n"
20         "       @ returns user entry point in r0\n"
21         "       mov     r6, r0\n"
22         "       @ we are PIC code, so get global offset table\n"
23         "       ldr     sl, .L_GET_GOT\n"
24         "       add     sl, pc, sl\n"
25         ".L_GOT_GOT:\n"
26         "       @ See if we were run as a command with the executable file\n"
27         "       @ name as an extra leading argument.\n"
28         "       ldr     r4, .L_SKIP_ARGS\n"
29         "       ldr     r4, [sl, r4]\n"
30         "       @ get the original arg count\n"
31         "       ldr     r1, [sp]\n"
32         "       @ subtract _dl_skip_args from it\n"
33         "       sub     r1, r1, r4\n"
34         "       @ adjust the stack pointer to skip them\n"
35         "       add     sp, sp, r4, lsl #2\n"
36         "       @ get the argv address\n"
37         "       add     r2, sp, #4\n"
38         "       @ store the new argc in the new stack location\n"
39         "       str     r1, [sp]\n"
40         "       @ compute envp\n"
41         "       add     r3, r2, r1, lsl #2\n"
42         "       add     r3, r3, #4\n"
43         "\n\n"
44         "       @ load the finalizer function\n"
45         "       ldr     r0, .L_FINI_PROC\n"
46         "       ldr     r0, [sl, r0]\n"
47         "       @ jump to the user_s entry point\n"
48 #if defined(__USE_BX__)
49         "       bx      r6\n"
50 #else
51         "       mov     pc, r6\n"
52 #endif
53         ".L_GET_GOT:\n"
54         "       .word   _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
55         ".L_SKIP_ARGS:\n"
56         "       .word   _dl_skip_args(GOTOFF)\n"
57         ".L_FINI_PROC:\n"
58         "       .word   _dl_fini(GOT)\n"
59         "\n\n"
60     "   .size   _start,.-_start\n"
61         ".previous\n"
62 );
63 #else
64 __asm__(
65     "   .text\n"
66     "   .arm\n"
67     "   .globl  _start\n"
68     "   .type   _start,%function\n"
69         "_start:\n"
70         "       @ dumb: can't persuade the linker to make the start address\n"
71         "       @ odd, so use an arm function and change to thumb (_dl_start\n"
72         "       @ is thumb)\n"
73         "       adr     r0, __dl_thumb_start+1\n"
74         "       bx      r0\n"
75         "\n\n"
76     "   .thumb\n"
77     "   .globl  __dl_thumb_start\n"
78     "   .thumb_func\n"
79     "   .type   __dl_thumb_start,%function\n"
80         "__dl_thumb_start:\n"
81         "       @ at start time, all the args are on the stack\n"
82         "       mov     r0, sp\n"
83         "       bl      _dl_start\n"
84         "       @ returns user entry point in r0\n"
85         "       mov     r6, r0\n"
86         "       @ we are PIC code, so get global offset table\n"
87         "       ldr     r7, .L_GET_GOT\n"
88         ".L_GOT_GOT:\n"
89         "       add     r7, pc\n"
90         "       @ See if we were run as a command with the executable file\n"
91         "       @ name as an extra leading argument.\n"
92         "       ldr     r4, .L_SKIP_ARGS\n"
93         "       ldr     r4, [r7, r4]\n"
94         "       @ get the original arg count\n"
95         "       ldr     r1, [sp]\n"
96         "       @ subtract _dl_skip_args from it\n"
97         "       sub     r1, r1, r4\n"
98         "       @ adjust the stack pointer to skip them\n"
99         "       lsl     r4, r4, #2\n"
100         "       add     sp, r4\n"
101         "       @ get the argv address\n"
102         "       add     r2, sp, #4\n"
103         "       @ store the new argc in the new stack location\n"
104         "       str     r1, [sp]\n"
105         "       @ compute envp\n"
106         "       lsl     r3, r1, #2\n"
107         "       add     r3, r3, r2\n"
108         "       add     r3, #4\n"
109         "\n\n"
110         "       @ load the finalizer function\n"
111         "       ldr     r0, .L_FINI_PROC\n"
112         "       ldr     r0, [r7, r0]\n"
113         "       @ jump to the user_s entry point\n"
114 #if defined(__USE_BX__)
115         "       bx      r6\n"
116 #else
117         "       mov     pc, r6\n"
118 #endif
119         "\n\n"
120         ".L_GET_GOT:\n"
121         "       .word   _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
122         ".L_SKIP_ARGS:\n"
123         "       .word   _dl_skip_args(GOTOFF)\n"
124         ".L_FINI_PROC:\n"
125         "       .word   _dl_fini(GOT)\n"
126         "\n\n"
127     "   .size   _start,.-_start\n"
128         ".previous\n"
129 );
130 #endif
131
132
133 /* Get a pointer to the argv array.  On many platforms this can be just
134  * the address of the first argument, on other platforms we need to
135  * do something a little more subtle here.  */
136 #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
137
138 /* Handle relocation of the symbols in the dynamic loader. */
139 static __always_inline
140 void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
141         unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
142 {
143         switch (ELF32_R_TYPE(rpnt->r_info)) {
144                 case R_ARM_NONE:
145                         break;
146                 case R_ARM_ABS32:
147                         *reloc_addr += symbol_addr;
148                         break;
149                 case R_ARM_PC24:
150                         {
151                                 unsigned long addend;
152                                 long newvalue, topbits;
153
154                                 addend = *reloc_addr & 0x00ffffff;
155                                 if (addend & 0x00800000) addend |= 0xff000000;
156
157                                 newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
158                                 topbits = newvalue & 0xfe000000;
159                                 if (topbits != 0xfe000000 && topbits != 0x00000000)
160                                 {
161 #if 0
162                                         /* Don't bother with this during ldso initilization... */
163                                         newvalue = fix_bad_pc24(reloc_addr, symbol_addr)
164                                                 - (unsigned long)reloc_addr + (addend << 2);
165                                         topbits = newvalue & 0xfe000000;
166                                         if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000))
167                                         {
168                                                 SEND_STDERR("R_ARM_PC24 relocation out of range\n");
169                                                 _dl_exit(1);
170                                         }
171 #else
172                                         SEND_STDERR("R_ARM_PC24 relocation out of range\n");
173                                         _dl_exit(1);
174 #endif
175                                 }
176                                 newvalue >>= 2;
177                                 symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
178                                 *reloc_addr = symbol_addr;
179                                 break;
180                         }
181                 case R_ARM_GLOB_DAT:
182                 case R_ARM_JUMP_SLOT:
183                         *reloc_addr = symbol_addr;
184                         break;
185                 case R_ARM_RELATIVE:
186                         *reloc_addr += load_addr;
187                         break;
188                 case R_ARM_COPY:
189                         break;
190                 default:
191                         SEND_STDERR("Unsupported relocation type\n");
192                         _dl_exit(1);
193         }
194 }