dl-startup.h 5.0 KB

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