dl-startup.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Architecture specific code used by dl-startup.c
  3. * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
  4. *
  5. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  6. */
  7. #include <features.h>
  8. #include <bits/arm_bx.h>
  9. #if defined(__FDPIC__)
  10. #if !defined(__thumb__) || defined(__thumb2__)
  11. __asm__(
  12. " .text\n"
  13. " .globl _start\n"
  14. " .type _start,%function\n"
  15. #if defined(__thumb2__)
  16. " .thumb_func\n"
  17. #endif
  18. " .align 2\n"
  19. "_start:\n"
  20. /* We compute the parameters for __self_reloc:
  21. - r0 is a pointer to the loadmap (either from r8 or r7 if rtld is
  22. lauched in standalone mode)
  23. - r1 is a pointer to the start of .rofixup section
  24. - r2 is a pointer to the last word of .rofixup section
  25. __self_reloc will fix indirect addresses in .rofixup
  26. section and will return the relocated GOT value.
  27. */
  28. #if defined(__thumb2__)
  29. " sub r4, pc, #4\n"
  30. #else
  31. " sub r4, pc, #8\n"
  32. #endif
  33. " ldr r1, .L__ROFIXUP_LIST__\n"
  34. " add r1, r1, r4\n"
  35. " ldr r2, .L__ROFIXUP_END__\n"
  36. " add r2, r2, r4\n"
  37. " movs r0, r8\n"
  38. " it eq\n"
  39. " moveq r0, r7\n"
  40. " push {r7, r8, r9, r10}\n"
  41. " bl __self_reloc;\n"
  42. " pop {r7, r8, r9, r10}\n"
  43. /* We compute the parameters for dl_start(). See DL_START()
  44. macro below. The address of the user entry point is
  45. returned in dl_main_funcdesc (on stack). */
  46. " mov r1, r7\n"
  47. " mov r2, r8\n"
  48. " mov r3, r9\n"
  49. " mov r4, sp\n"
  50. " sub r5, sp, #8\n"
  51. " sub sp, sp, #16\n"
  52. " str r4, [sp, #4]\n"
  53. " str r5, [sp, #0]\n"
  54. " mov r9, r0\n"
  55. /* Save r9 into r4, to preserve the GOT pointer. */
  56. " mov r4, r9\n"
  57. " bl _dl_start;\n"
  58. /* Now compute parameters for entry point according to FDPIC ABI. */
  59. " ldr r10, .L_dl_fini_gotofffuncdesc\n"
  60. /* Save GOT value from r4. */
  61. " add r10, r10, r4\n"
  62. " ldr r5, [sp, #8]\n"
  63. " ldr r9, [sp, #12]\n"
  64. " add sp, sp, #16\n"
  65. " bx r5\n"
  66. ".loopforever:\n"
  67. " b .loopforever\n"
  68. ".L__ROFIXUP_LIST__:\n"
  69. " .word __ROFIXUP_LIST__ - _start\n"
  70. ".L__ROFIXUP_END__:\n"
  71. " .word __ROFIXUP_END__ - _start\n"
  72. ".L_dl_fini_gotofffuncdesc:\n"
  73. " .word _dl_fini(GOTOFFFUNCDESC)\n"
  74. " .size _start,.-_start\n"
  75. " .previous\n"
  76. );
  77. #else /* !defined(__thumb__) */
  78. #error Thumb-1 is not supported
  79. #endif /* !defined(__thumb__) */
  80. #else /* defined(__FDPIC__) */
  81. #if !defined(__thumb__)
  82. __asm__(
  83. " .text\n"
  84. " .globl _start\n"
  85. " .type _start,%function\n"
  86. " .hidden _start\n"
  87. "_start:\n"
  88. " @ at start time, all the args are on the stack\n"
  89. " mov r0, sp\n"
  90. " bl _dl_start\n"
  91. " @ returns user entry point in r0\n"
  92. " mov r6, r0\n"
  93. " @ we are PIC code, so get global offset table\n"
  94. " ldr sl, .L_GET_GOT\n"
  95. " add sl, pc, sl\n"
  96. ".L_GOT_GOT:\n"
  97. " @ See if we were run as a command with the executable file\n"
  98. " @ name as an extra leading argument.\n"
  99. " ldr r4, .L_SKIP_ARGS\n"
  100. " ldr r4, [sl, r4]\n"
  101. " @ get the original arg count\n"
  102. " ldr r1, [sp]\n"
  103. " @ subtract _dl_skip_args from it\n"
  104. " sub r1, r1, r4\n"
  105. " @ adjust the stack pointer to skip them\n"
  106. " add sp, sp, r4, lsl #2\n"
  107. " @ get the argv address\n"
  108. " add r2, sp, #4\n"
  109. " @ store the new argc in the new stack location\n"
  110. " str r1, [sp]\n"
  111. " @ compute envp\n"
  112. " add r3, r2, r1, lsl #2\n"
  113. " add r3, r3, #4\n"
  114. "\n\n"
  115. " @ load the finalizer function\n"
  116. " ldr r0, .L_FINI_PROC\n"
  117. " ldr r0, [sl, r0]\n"
  118. " @ jump to the user_s entry point\n"
  119. " " __stringify(BX(r6)) "\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. #else
  131. __asm__(
  132. " .text\n"
  133. " .arm\n"
  134. " .globl _start\n"
  135. " .type _start,%function\n"
  136. "_start:\n"
  137. " @ dumb: can't persuade the linker to make the start address\n"
  138. " @ odd, so use an arm function and change to thumb (_dl_start\n"
  139. " @ is thumb)\n"
  140. " adr r0, __dl_thumb_start+1\n"
  141. " bx r0\n"
  142. "\n\n"
  143. " .thumb\n"
  144. " .globl __dl_thumb_start\n"
  145. " .thumb_func\n"
  146. " .type __dl_thumb_start,%function\n"
  147. "__dl_thumb_start:\n"
  148. " @ at start time, all the args are on the stack\n"
  149. " mov r0, sp\n"
  150. " bl _dl_start\n"
  151. " @ returns user entry point in r0\n"
  152. " mov r6, r0\n"
  153. " @ we are PIC code, so get global offset table\n"
  154. " ldr r7, .L_GET_GOT\n"
  155. ".L_GOT_GOT:\n"
  156. " add r7, pc\n"
  157. " @ See if we were run as a command with the executable file\n"
  158. " @ name as an extra leading argument.\n"
  159. " ldr r4, .L_SKIP_ARGS\n"
  160. " ldr r4, [r7, r4]\n"
  161. " @ get the original arg count\n"
  162. " ldr r1, [sp]\n"
  163. " @ subtract _dl_skip_args from it\n"
  164. " sub r1, r1, r4\n"
  165. " @ adjust the stack pointer to skip them\n"
  166. " lsl r4, r4, #2\n"
  167. " add sp, r4\n"
  168. " @ get the argv address\n"
  169. " add r2, sp, #4\n"
  170. " @ store the new argc in the new stack location\n"
  171. " str r1, [sp]\n"
  172. " @ compute envp\n"
  173. " lsl r3, r1, #2\n"
  174. " add r3, r3, r2\n"
  175. " add r3, #4\n"
  176. "\n\n"
  177. " @ load the finalizer function\n"
  178. " ldr r0, .L_FINI_PROC\n"
  179. " ldr r0, [r7, r0]\n"
  180. " @ jump to the user_s entry point\n"
  181. " " __stringify(BX(r6)) "\n"
  182. "\n\n"
  183. ".L_GET_GOT:\n"
  184. " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
  185. ".L_SKIP_ARGS:\n"
  186. " .word _dl_skip_args(GOTOFF)\n"
  187. ".L_FINI_PROC:\n"
  188. " .word _dl_fini(GOT)\n"
  189. "\n\n"
  190. " .size _start,.-_start\n"
  191. ".previous\n"
  192. );
  193. #endif
  194. #endif /* defined(__FDPIC__) */
  195. /* Get a pointer to the argv array. On many platforms this can be just
  196. * the address of the first argument, on other platforms we need to
  197. * do something a little more subtle here. */
  198. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
  199. /* Handle relocation of the symbols in the dynamic loader. */
  200. static __always_inline
  201. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
  202. unsigned long symbol_addr, DL_LOADADDR_TYPE load_addr, Elf32_Sym *symtab)
  203. {
  204. switch (ELF_R_TYPE(rpnt->r_info)) {
  205. case R_ARM_NONE:
  206. break;
  207. case R_ARM_ABS32:
  208. *reloc_addr += symbol_addr;
  209. break;
  210. case R_ARM_PC24:
  211. {
  212. unsigned long addend;
  213. long newvalue, topbits;
  214. addend = *reloc_addr & 0x00ffffff;
  215. if (addend & 0x00800000) addend |= 0xff000000;
  216. newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
  217. topbits = newvalue & 0xfe000000;
  218. if (topbits != 0xfe000000 && topbits != 0x00000000)
  219. {
  220. #if 0
  221. /* Don't bother with this during ldso initilization... */
  222. newvalue = fix_bad_pc24(reloc_addr, symbol_addr)
  223. - (unsigned long)reloc_addr + (addend << 2);
  224. topbits = newvalue & 0xfe000000;
  225. if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000))
  226. {
  227. SEND_STDERR("R_ARM_PC24 relocation out of range\n");
  228. _dl_exit(1);
  229. }
  230. #else
  231. SEND_STDERR("R_ARM_PC24 relocation out of range\n");
  232. _dl_exit(1);
  233. #endif
  234. }
  235. newvalue >>= 2;
  236. symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
  237. *reloc_addr = symbol_addr;
  238. break;
  239. }
  240. case R_ARM_GLOB_DAT:
  241. case R_ARM_JUMP_SLOT:
  242. *reloc_addr = symbol_addr;
  243. break;
  244. case R_ARM_RELATIVE:
  245. *reloc_addr = DL_RELOC_ADDR(load_addr, *reloc_addr);
  246. break;
  247. case R_ARM_COPY:
  248. break;
  249. #ifdef __FDPIC__
  250. case R_ARM_FUNCDESC_VALUE:
  251. {
  252. struct funcdesc_value *dst = (struct funcdesc_value *) reloc_addr;
  253. dst->entry_point += symbol_addr;
  254. dst->got_value = load_addr.got_value;
  255. }
  256. break;
  257. #endif
  258. default:
  259. SEND_STDERR("Unsupported relocation type\n");
  260. _dl_exit(1);
  261. }
  262. }
  263. #ifdef __FDPIC__
  264. #undef DL_START
  265. #define DL_START(X) \
  266. static void __attribute__ ((used)) \
  267. _dl_start (Elf32_Addr dl_boot_got_pointer, \
  268. struct elf32_fdpic_loadmap *dl_boot_progmap, \
  269. struct elf32_fdpic_loadmap *dl_boot_ldsomap, \
  270. Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
  271. struct funcdesc_value *dl_main_funcdesc, \
  272. X)
  273. /*
  274. * Transfer control to the user's application, once the dynamic loader
  275. * is done. We return the address of the function's entry point to
  276. * _dl_boot, see boot1_arch.h.
  277. */
  278. #define START() do { \
  279. struct elf_resolve *exec_mod = _dl_loaded_modules; \
  280. dl_main_funcdesc->entry_point = _dl_elf_main; \
  281. while (exec_mod->libtype != elf_executable) \
  282. exec_mod = exec_mod->next; \
  283. dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \
  284. return; \
  285. } while (0)
  286. /* We use __aeabi_idiv0 in _dl_find_hash, so we need to have the raise
  287. symbol. */
  288. int raise(int sig)
  289. {
  290. _dl_exit(1);
  291. }
  292. #endif /* __FDPIC__ */