dl-startup.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* Copyright (C) 2003 Red Hat, Inc.
  2. Contributed by Alexandre Oliva <aoliva@redhat.com>
  3. This file is part of uClibc.
  4. uClibc is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU Lesser General Public License as
  6. published by the Free Software Foundation; either version 2.1 of the
  7. License, or (at your option) any later version.
  8. uClibc is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with uClibc; see the file COPYING.LIB. If not, see
  14. <http://www.gnu.org/licenses/>. */
  15. /* Any assembly language/system dependent hacks needed to setup
  16. * boot1.c so it will work as expected and cope with whatever platform
  17. * specific wierdness is needed for this architecture.
  18. */
  19. /* At program start-up, p0 contains a pointer to a
  20. elf32_fdpic_loadmap that describes how the executable was loaded
  21. into memory. p1 contains a pointer to the interpreter (our!)
  22. loadmap, if there is an interpreter, or 0 if we're being run as an
  23. executable. p2 holds a pointer to the interpreter's dynamic
  24. section, if there is an interpreter, or to the executable's dynamic
  25. section, otherwise. If the executable is not dynamic, gr18 is 0.
  26. We rely on the fact that the linker adds a pointer to the
  27. _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that
  28. __self_reloc returns the relocated pointer to us, so that we can
  29. use this value to initialize the PIC register. */
  30. __asm__(
  31. " .text\n"
  32. " .global __start\n"
  33. " .type __start,@function\n"
  34. " .hidden __start\n"
  35. "__start:\n"
  36. " call .Lcall\n"
  37. ".Lcall:\n"
  38. " R4 = RETS;\n"
  39. " SP += -32;\n"
  40. " R5 = P0;\n"
  41. " R6 = P1;\n"
  42. " R7 = P2;\n"
  43. " R0.L = .Lcall;\n"
  44. " R0.H = .Lcall;\n"
  45. " R1.L = __ROFIXUP_LIST__;\n"
  46. " R1.H = __ROFIXUP_LIST__;\n"
  47. " R2.L = __ROFIXUP_END__;\n"
  48. " R2.H = __ROFIXUP_END__;\n"
  49. " R1 = R1 - R0;\n"
  50. " R1 = R1 + R4;\n"
  51. " R2 = R2 - R0;\n"
  52. " R2 = R2 + R4;\n"
  53. " R0 = P1;\n"
  54. " CC = R0 == 0;\n"
  55. " IF CC R0 = P0;\n"
  56. " CALL ___self_reloc;\n"
  57. " P3 = R0;\n"
  58. " P5 = R0;\n"
  59. " R1 = R5;\n"
  60. " R2 = R6;\n"
  61. " [SP + 12] = R7;\n"
  62. " P0 = SP;\n"
  63. " P0 += 24;\n"
  64. " [SP + 16] = P0;\n"
  65. " P0 += 8;\n"
  66. " [SP + 20] = P0;\n"
  67. " CALL __dl_start;\n"
  68. " /* Pass our FINI ptr() to the user in P1 */\n"
  69. " R7 = [P5 + __dl_fini@FUNCDESC_GOT17M4];\n"
  70. " P4 = [SP + 24];\n"
  71. " P3 = [SP + 28];\n"
  72. " P0 = R5;\n"
  73. " SP += 32;\n"
  74. " JUMP (P4);\n"
  75. " .size __start,.-__start\n"
  76. );
  77. #undef DL_START
  78. #define DL_START(X) \
  79. static void __attribute__ ((used)) \
  80. _dl_start (Elf32_Addr dl_boot_got_pointer, \
  81. struct elf32_fdpic_loadmap *dl_boot_progmap, \
  82. struct elf32_fdpic_loadmap *dl_boot_ldsomap, \
  83. Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
  84. struct funcdesc_value *dl_main_funcdesc, \
  85. X)
  86. /*
  87. * Get a pointer to the argv array. On many platforms this can be just
  88. * the address of the first argument, on other platforms we need to
  89. * do something a little more subtle here.
  90. */
  91. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1)
  92. /*
  93. * Here is a macro to perform a relocation. This is only used when
  94. * bootstrapping the dynamic loader. RELP is the relocation that we
  95. * are performing, REL is the pointer to the address we are relocating.
  96. * SYMBOL is the symbol involved in the relocation, and LOAD is the
  97. * load address.
  98. */
  99. #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
  100. switch(ELF_R_TYPE((RELP)->r_info)){ \
  101. case R_BFIN_BYTE4_DATA: \
  102. *(REL) += (SYMBOL); \
  103. break; \
  104. case R_BFIN_FUNCDESC_VALUE: \
  105. { \
  106. struct funcdesc_value fv = { \
  107. (void*)((SYMBOL) + *(REL)), \
  108. (LOAD).got_value \
  109. }; \
  110. *(struct funcdesc_value volatile *)(REL) = fv; \
  111. break; \
  112. } \
  113. default: \
  114. _dl_exit(1); \
  115. }
  116. /*
  117. * Transfer control to the user's application, once the dynamic loader
  118. * is done. We return the address of the function's entry point to
  119. * _dl_boot, see boot1_arch.h.
  120. */
  121. #define START() do { \
  122. struct elf_resolve *exec_mod = _dl_loaded_modules; \
  123. dl_main_funcdesc->entry_point = _dl_elf_main; \
  124. while (exec_mod->libtype != elf_executable) \
  125. exec_mod = exec_mod->next; \
  126. dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \
  127. return; \
  128. } while (0)