dl-startup.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /* Any assmbly 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. asm(""
  8. " .text\n"
  9. " .globl _start\n"
  10. " .ent _start\n"
  11. " .type _start,@function\n"
  12. "_start:\n"
  13. " .set noreorder\n"
  14. " move $25, $31\n"
  15. " bal 0f\n"
  16. " nop\n"
  17. "0:\n"
  18. " .cpload $31\n"
  19. " move $31, $25\n"
  20. " .set reorder\n"
  21. " la $4, _DYNAMIC\n"
  22. " sw $4, -0x7ff0($28)\n"
  23. " move $4, $29\n"
  24. " subu $29, 16\n"
  25. " la $8, .coff\n"
  26. " bltzal $8, .coff\n"
  27. ".coff:\n"
  28. " subu $8, $31, $8\n"
  29. " la $25, _dl_start\n"
  30. " addu $25, $8\n"
  31. " jalr $25\n"
  32. " addiu $29, 16\n"
  33. " move $16, $28\n"
  34. " move $17, $2\n"
  35. " lw $2, _dl_skip_args\n"
  36. " beq $2, $0, 1f\n"
  37. " lw $4, 0($29)\n"
  38. " subu $4, $2\n"
  39. " sll $2, 2\n"
  40. " addu $29, $2\n"
  41. " sw $4, 0($29)\n"
  42. "1:\n"
  43. " lw $5, 0($29)\n"
  44. " la $6, 4 ($29)\n"
  45. " sll $7, $5, 2\n"
  46. " addu $7, $7, $6\n"
  47. " addu $7, $7, 4\n"
  48. " and $2, $29, -2 * 4\n"
  49. " sw $29, -4($2)\n"
  50. " subu $29, $2, 32\n"
  51. " .cprestore 16\n"
  52. " lw $29, 28($29)\n"
  53. " la $2, _dl_fini\n"
  54. " move $25, $17\n"
  55. " jr $25\n"
  56. ".end _start\n"
  57. ".size _start, . -_start\n"
  58. "\n\n"
  59. "\n\n"
  60. ".previous\n"
  61. );
  62. /*
  63. * Get a pointer to the argv array. On many platforms this can be just
  64. * the address if the first argument, on other platforms we need to
  65. * do something a little more subtle here.
  66. */
  67. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1)
  68. /* We can't call functions earlier in the dl startup process */
  69. #define NO_FUNCS_BEFORE_BOOTSTRAP
  70. /*
  71. * Here is a macro to perform the GOT relocation. This is only
  72. * used when bootstrapping the dynamic loader.
  73. */
  74. #define PERFORM_BOOTSTRAP_GOT(tpnt) \
  75. do { \
  76. Elf32_Sym *sym; \
  77. Elf32_Addr i; \
  78. register ElfW(Addr) gp __asm__ ("$28"); \
  79. Elf32_Addr *mipsgot = elf_mips_got_from_gpreg (gp); \
  80. \
  81. /* Add load address displacement to all local GOT entries */ \
  82. i = 2; \
  83. while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
  84. mipsgot[i++] += tpnt->loadaddr; \
  85. \
  86. /* Handle global GOT entries */ \
  87. mipsgot += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; \
  88. sym = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB] + \
  89. tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; \
  90. i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\
  91. \
  92. while (i--) { \
  93. if (sym->st_shndx == SHN_UNDEF || \
  94. sym->st_shndx == SHN_COMMON) \
  95. *mipsgot = tpnt->loadaddr + sym->st_value; \
  96. else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
  97. *mipsgot != sym->st_value) \
  98. *mipsgot += tpnt->loadaddr; \
  99. else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
  100. if (sym->st_other == 0) \
  101. *mipsgot += tpnt->loadaddr; \
  102. } \
  103. else \
  104. *mipsgot = tpnt->loadaddr + sym->st_value; \
  105. \
  106. mipsgot++; \
  107. sym++; \
  108. } \
  109. } while (0)
  110. /*
  111. * Here is a macro to perform a relocation. This is only used when
  112. * bootstrapping the dynamic loader.
  113. */
  114. #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
  115. switch(ELF32_R_TYPE((RELP)->r_info)) { \
  116. case R_MIPS_REL32: \
  117. if (SYMTAB) { \
  118. if (symtab_index<tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])\
  119. *REL += SYMBOL; \
  120. } \
  121. else { \
  122. *REL += LOAD; \
  123. } \
  124. break; \
  125. case R_MIPS_NONE: \
  126. break; \
  127. default: \
  128. SEND_STDERR("Aiieeee!"); \
  129. _dl_exit(1); \
  130. }
  131. /*
  132. * Transfer control to the user's application, once the dynamic loader
  133. * is done. This routine has to exit the current function, then
  134. * call the _dl_elf_main function. For MIPS, we do it in assembly
  135. * because the stack doesn't get properly restored otherwise. Got look
  136. * at boot1_arch.h
  137. */
  138. #define START() return _dl_elf_main