dl-startup.h 3.5 KB

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