Added support for creation of Static Position-Independent Executables (PIE) on mips
[uclibc-ng.git] / ldso / ldso / mips / dl-startup.h
blobc2168d7740c5b3c78d0888a16e0b2fb4cce1ea27
1 /* Any assembly language/system dependent hacks needed to setup boot1.c so it
2 * will work as expected and cope with whatever platform specific wierdness is
3 * needed for this architecture.
4 * Copyright (C) 2005 by Joakim Tjernlund
5 * Copyright (C) 2005 by Erik Andersen
6 */
9 #include <sgidefs.h>
10 #ifndef L_rcrt1
11 __asm__(""
12 " .text\n"
13 " .globl _start\n"
14 " .ent _start\n"
15 " .type _start,@function\n"
16 " .hidden _start\n"
17 "_start:\n"
18 " .set noreorder\n"
19 " move $25, $31\n"
20 " bal 0f\n"
21 " nop\n"
22 "0:\n"
23 #if _MIPS_SIM == _MIPS_SIM_ABI32
24 " .cpload $31\n"
25 #else /* N32 || N64 */
26 " .cpsetup $31, $2, 0b\n"
27 #endif /* N32 || N64 */
28 " move $31, $25\n"
29 " .set reorder\n"
30 #if _MIPS_SIM == _MIPS_SIM_ABI64
31 " dla $4, _DYNAMIC\n"
32 " sd $4, -0x7ff0($28)\n"
33 #else /* O32 || N32 */
34 " la $4, _DYNAMIC\n"
35 " sw $4, -0x7ff0($28)\n"
36 #endif /* O32 || N32 */
37 " move $4, $29\n"
38 #if _MIPS_SIM == _MIPS_SIM_ABI32
39 " subu $29, 16\n"
40 #endif
41 #if _MIPS_SIM == _MIPS_SIM_ABI64
42 " dla $8, .coff\n"
43 #else /* O32 || N32 */
44 " la $8, .coff\n"
45 #endif /* O32 || N32 */
46 # if !defined __mips_isa_rev || __mips_isa_rev < 6
47 " bltzal $8, .coff\n"
48 ".coff:\n"
49 # else
50 ".coff:\n"
51 " lapc $31, .coff\n"
52 # endif
53 #if _MIPS_SIM == _MIPS_SIM_ABI64
54 " dsubu $8, $31, $8\n"
55 " dla $25, _dl_start\n"
56 " daddu $25, $8\n"
57 #else /* O32 || N32 */
58 " subu $8, $31, $8\n"
59 " la $25, _dl_start\n"
60 " addu $25, $8\n"
61 #endif /* O32 || N32 */
62 " jalr $25\n"
63 #if _MIPS_SIM == _MIPS_SIM_ABI32
64 " addiu $29, 16\n"
65 #endif
66 " move $16, $28\n"
67 " move $17, $2\n"
68 #if _MIPS_SIM == _MIPS_SIM_ABI64
69 " ld $2, _dl_skip_args\n"
70 " beq $2, $0, 1f\n"
71 " ld $4, 0($29)\n"
72 " dsubu $4, $2\n"
73 " dsll $2, 2\n"
74 " daddu $29, $2\n"
75 " sd $4, 0($29)\n"
76 "1:\n"
77 " ld $5, 0($29)\n"
78 " dla $6, 8 ($29)\n"
79 " dsll $7, $5, 2\n"
80 " daddu $7, $7, $6\n"
81 " daddu $7, $7, 4\n"
82 " and $2, $29, -4 * 4\n"
83 " sd $29, -8($2)\n"
84 " dsubu $29, $2, 32\n"
85 " ld $29, 24($29)\n"
86 " dla $2, _dl_fini\n"
87 #else /* O32 || N32 */
88 " lw $2, _dl_skip_args\n"
89 " beq $2, $0, 1f\n"
90 " lw $4, 0($29)\n"
91 " subu $4, $2\n"
92 " sll $2, 2\n"
93 " addu $29, $2\n"
94 " sw $4, 0($29)\n"
95 "1:\n"
96 " lw $5, 0($29)\n"
97 " la $6, 4 ($29)\n"
98 " sll $7, $5, 2\n"
99 " addu $7, $7, $6\n"
100 " addu $7, $7, 4\n"
101 " and $2, $29, -2 * 4\n"
102 " sw $29, -4($2)\n"
103 " subu $29, $2, 32\n"
104 #if _MIPS_SIM == _MIPS_SIM_ABI32
105 " .cprestore 16\n"
106 #endif
107 " lw $29, 28($29)\n"
108 " la $2, _dl_fini\n"
109 #endif /* O32 || N32 */
110 " move $25, $17\n"
111 " jr $25\n"
112 ".end _start\n"
113 ".size _start, . -_start\n"
114 "\n\n"
115 "\n\n"
116 ".previous\n"
118 #endif
121 * Get a pointer to the argv array. On many platforms this can be just
122 * the address of the first argument, on other platforms we need to
123 * do something a little more subtle here.
125 #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1)
128 /* We can't call functions earlier in the dl startup process */
129 #define NO_FUNCS_BEFORE_BOOTSTRAP
133 * Here is a macro to perform the GOT relocation. This is only
134 * used when bootstrapping the dynamic loader.
136 #define PERFORM_BOOTSTRAP_GOT(tpnt) \
137 do { \
138 ElfW(Sym) *sym; \
139 ElfW(Addr) i; \
140 register ElfW(Addr) gp __asm__ ("$28"); \
141 ElfW(Addr) *mipsgot = elf_mips_got_from_gpreg (gp); \
143 /* Add load address displacement to all local GOT entries */ \
144 i = 2; \
145 while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
146 mipsgot[i++] += tpnt->loadaddr; \
148 /* Handle global GOT entries */ \
149 mipsgot += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; \
150 sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] + \
151 tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; \
152 i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\
154 while (i--) { \
155 if (sym->st_shndx == SHN_UNDEF || \
156 sym->st_shndx == SHN_COMMON) \
157 *mipsgot = tpnt->loadaddr + sym->st_value; \
158 else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && \
159 *mipsgot != sym->st_value) \
160 *mipsgot += tpnt->loadaddr; \
161 else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { \
162 if (sym->st_other == 0) \
163 *mipsgot += tpnt->loadaddr; \
165 else \
166 *mipsgot = tpnt->loadaddr + sym->st_value; \
168 mipsgot++; \
169 sym++; \
171 } while (0)
174 * Here is a macro to perform a relocation. This is only used when
175 * bootstrapping the dynamic loader.
177 #if _MIPS_SIM == _MIPS_SIM_ABI64 /* consult with glibc sysdeps/mips/dl-machine.h 1.69 */
178 #define R_MIPS_BOOTSTRAP_RELOC ((R_MIPS_64 << 8) | R_MIPS_REL32)
179 #else /* N32 || O32 */
180 #define R_MIPS_BOOTSTRAP_RELOC R_MIPS_REL32
181 #endif
182 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
183 switch(ELF_R_TYPE((RELP)->r_info)) { \
184 case R_MIPS_BOOTSTRAP_RELOC: \
185 if (SYMTAB) { \
186 if (symtab_index<tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])\
187 *REL += SYMBOL; \
189 else { \
190 *REL += LOAD; \
192 break; \
193 case R_MIPS_NONE: \
194 break; \
195 default: \
196 _dl_exit(1); \