dl-startup.h 5.2 KB

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