dl-startup.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright (C) 2016 Andes Technology, Inc.
  3. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  4. */
  5. /* Need bootstrap relocations */
  6. #define ARCH_NEEDS_BOOTSTRAP_RELOCS
  7. #if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
  8. # define STACK_PUSH
  9. # define STACK_POP
  10. #else
  11. # define STACK_PUSH "addi $sp, $sp, -24"
  12. # define STACK_POP "addi $sp, $sp, 24"
  13. #endif
  14. #ifdef __NDS32_N1213_43U1H__
  15. __asm__("\
  16. .text\n\
  17. .globl _start\n\
  18. .globl _dl_start\n\
  19. .globl _dl_start_user\n\
  20. .type _start,#function\n\
  21. .type _dl_start,#function\n\
  22. .type _dl_start_user,#function\n\
  23. .align 4\n\
  24. .pic\n\
  25. 1:\n\
  26. ret\n\
  27. _start:\n\
  28. ! we are PIC code, so get global offset table\n\
  29. jal 1b\n\
  30. sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_)\n\
  31. ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_+4)\n\
  32. add $gp, $lp, $gp\n\
  33. \n\
  34. ! at start time, all the args are on the stack\n\
  35. addi $r0, $sp, 0\n\
  36. ! adjust stack\n\
  37. !addi $sp, $sp, -24\n\
  38. "STACK_PUSH"\n\
  39. bal _dl_start@PLT\n\
  40. ! save user entry point in r6\n\
  41. addi $r6, $r0, 0\n\
  42. ! adjust sp and reload registers\n\
  43. !addi $sp, $sp, 24\n\
  44. "STACK_POP"\n\
  45. \n\
  46. _dl_start_user:\n\
  47. \n\
  48. ! See if we were run as a command with the executable file\n\
  49. ! name as an extra leading argument.\n\
  50. ! skip these arguments\n\
  51. l.w $r2, _dl_skip_args@GOTOFF ! args to skip\n\
  52. lwi $r0, [$sp+0] ! original argc\n\
  53. slli $r1, $r2, 2 ! offset for new sp\n\
  54. add $sp, $sp, $r1 ! adjust sp to skip args\n\
  55. sub $r0, $r0, $r2 ! set new argc\n\
  56. swi $r0, [$sp+0] ! save new argc\n\
  57. \n\
  58. ! load address of _dl_fini finalizer function\n\
  59. la $r5, _dl_fini@GOTOFF\n\
  60. ! jump to the user_s entry point\n\
  61. addi $r15, $r6, 0\n\
  62. jr $r15\n\
  63. .size _dl_start_user, . - _dl_start_user\n\
  64. .previous\n\
  65. ");
  66. #else
  67. __asm__("\
  68. .text\n\
  69. .globl _start\n\
  70. .globl _dl_start\n\
  71. .globl _dl_start_user\n\
  72. .type _start,#function\n\
  73. .type _dl_start,#function\n\
  74. .type _dl_start_user,#function\n\
  75. .align 4\n\
  76. .pic\n\
  77. _start:\n\
  78. ! we are PIC code, so get global offset table\n\
  79. mfusr $r15, $PC \n\
  80. sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_ + 4)\n\
  81. ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_ + 8)\n\
  82. add $gp, $r15, $gp\n\
  83. \n\
  84. ! at start time, all the args are on the stack\n\
  85. addi $r0, $sp, 0\n\
  86. ! adjust stack\n\
  87. !addi $sp, $sp, -24\n\
  88. "STACK_PUSH"\n\
  89. bal _dl_start@PLT\n\
  90. ! save user entry point in r6\n\
  91. addi $r6, $r0, 0\n\
  92. ! adjust sp and reload registers\n\
  93. !addi $sp, $sp, 24\n\
  94. "STACK_POP"\n\
  95. \n\
  96. _dl_start_user:\n\
  97. ! See if we were run as a command with the executable file\n\
  98. ! name as an extra leading argument.\n\
  99. ! skip these arguments\n\
  100. l.w $r2, _dl_skip_args@GOTOFF ! args to skip\n\
  101. lwi $r0, [$sp+0] ! original argc\n\
  102. slli $r1, $r2, 2 ! offset for new sp\n\
  103. add $sp, $sp, $r1 ! adjust sp to skip args\n\
  104. sub $r0, $r0, $r2 ! set new argc\n\
  105. swi $r0, [$sp+0] ! save new argc\n\
  106. \n\
  107. ! load address of _dl_fini finalizer function\n\
  108. la $r5, _dl_fini@GOTOFF\n\
  109. ! jump to the user_s entry point\n\
  110. jr $r6\n\
  111. .size _dl_start_user, . - _dl_start_user\n\
  112. .previous\n\
  113. ");
  114. #endif
  115. #define COPY_UNALIGNED_WORD(swp, twp, align) \
  116. { \
  117. void *__s = (swp), *__t = (twp); \
  118. unsigned char *__s1 = __s, *__t1 = __t; \
  119. unsigned short *__s2 = __s, *__t2 = __t; \
  120. unsigned long *__s4 = __s, *__t4 = __t; \
  121. switch ((align)) \
  122. { \
  123. case 0: \
  124. *__t4 = *__s4; \
  125. break; \
  126. case 2: \
  127. *__t2++ = *__s2++; \
  128. *__t2 = *__s2; \
  129. break; \
  130. default: \
  131. *__t1++ = *__s1++; \
  132. *__t1++ = *__s1++; \
  133. *__t1++ = *__s1++; \
  134. *__t1 = *__s1; \
  135. break; \
  136. } \
  137. }
  138. /* Get a pointer to the argv array. On many platforms this can be just
  139. * the address if the first argument, on other platforms we need to
  140. * do something a little more subtle here. */
  141. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
  142. /* Handle relocation of the symbols in the dynamic loader. */
  143. static __always_inline
  144. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
  145. unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
  146. {
  147. Elf32_Addr value;
  148. switch (ELF32_R_TYPE(rpnt->r_info)) {
  149. case R_NDS32_NONE:
  150. break;
  151. case R_NDS32_32:
  152. case R_NDS32_GLOB_DAT:
  153. case R_NDS32_JMP_SLOT:
  154. *reloc_addr = symbol_addr + rpnt->r_addend;
  155. break;
  156. case R_NDS32_32_RELA:
  157. value = symbol_addr + rpnt->r_addend;
  158. COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3);
  159. break;
  160. #undef COPY_UNALIGNED_WORD
  161. case R_NDS32_RELATIVE:
  162. *reloc_addr = load_addr + rpnt->r_addend;
  163. break;
  164. default:
  165. SEND_STDERR("Unsupported relocation type\n");
  166. _dl_exit(1);
  167. }
  168. }