1 /* vi: set sw=4 ts=4: */
3 * Architecture specific code used by dl-startup.c
4 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
6 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
11 #if !defined(__thumb__)
15 " .type _start,%function\n"
17 " @ at start time, all the args are on the stack\n"
20 " @ returns user entry point in r0\n"
22 " @ we are PIC code, so get global offset table\n"
23 " ldr sl, .L_GET_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"
30 " @ get the original arg count\n"
32 " @ subtract _dl_skip_args from it\n"
34 " @ adjust the stack pointer to skip them\n"
35 " add sp, sp, r4, lsl #2\n"
36 " @ get the argv address\n"
38 " @ store the new argc in the new stack location\n"
41 " add r3, r2, r1, lsl #2\n"
44 " @ load the finalizer function\n"
45 " ldr r0, .L_FINI_PROC\n"
47 " @ jump to the user_s entry point\n"
48 #if defined(__USE_BX__)
54 " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
56 " .word _dl_skip_args(GOTOFF)\n"
58 " .word _dl_fini(GOT)\n"
60 " .size _start,.-_start\n"
68 " .type _start,%function\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"
73 " adr r0, __dl_thumb_start+1\n"
77 " .globl __dl_thumb_start\n"
79 " .type __dl_thumb_start,%function\n"
81 " @ at start time, all the args are on the stack\n"
84 " @ returns user entry point in r0\n"
86 " @ we are PIC code, so get global offset table\n"
87 " ldr r7, .L_GET_GOT\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"
94 " @ get the original arg count\n"
96 " @ subtract _dl_skip_args from it\n"
98 " @ adjust the stack pointer to skip them\n"
101 " @ get the argv address\n"
103 " @ store the new argc in the new stack location\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__)
121 " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
123 " .word _dl_skip_args(GOTOFF)\n"
125 " .word _dl_fini(GOT)\n"
127 " .size _start,.-_start\n"
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)
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)
143 switch (ELF32_R_TYPE(rpnt->r_info)) {
147 *reloc_addr += symbol_addr;
151 unsigned long addend;
152 long newvalue, topbits;
154 addend = *reloc_addr & 0x00ffffff;
155 if (addend & 0x00800000) addend |= 0xff000000;
157 newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
158 topbits = newvalue & 0xfe000000;
159 if (topbits != 0xfe000000 && topbits != 0x00000000)
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))
168 SEND_STDERR("R_ARM_PC24 relocation out of range\n");
172 SEND_STDERR("R_ARM_PC24 relocation out of range\n");
177 symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
178 *reloc_addr = symbol_addr;
182 case R_ARM_JUMP_SLOT:
183 *reloc_addr = symbol_addr;
186 *reloc_addr += load_addr;
191 SEND_STDERR("Unsupported relocation type\n");