dl-sysdep.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Various assmbly language/system dependent hacks that are required
  4. * so that we can minimize the amount of platform specific code.
  5. */
  6. /*
  7. * Define this if the system uses RELOCA.
  8. */
  9. #undef ELF_USES_RELOCA
  10. /*
  11. * Get a pointer to the argv array. On many platforms this can be just
  12. * the address if the first argument, on other platforms we need to
  13. * do something a little more subtle here.
  14. */
  15. #define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *) ARGS)
  16. /*
  17. * Initialization sequence for the application or library GOT.
  18. */
  19. #define INIT_GOT(GOT_BASE,MODULE) \
  20. do { \
  21. Elf32_Sym *sym; \
  22. char *strtab; \
  23. unsigned long i; \
  24. \
  25. /* Check if this is the dynamic linker itself */ \
  26. if (MODULE->libtype == program_interpreter) \
  27. continue; \
  28. \
  29. /* Fill in first two GOT entries according to the ABI */ \
  30. GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
  31. GOT_BASE[1] = (unsigned long) MODULE; \
  32. \
  33. /* Add load address displacement to all local GOT entries */ \
  34. i = 2; \
  35. while (i < MODULE->mips_local_gotno) \
  36. GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \
  37. \
  38. /* Handle global GOT entries */ \
  39. GOT_BASE += MODULE->mips_local_gotno; \
  40. sym = (Elf32_Sym *) (MODULE->dynamic_info[DT_SYMTAB] + \
  41. (unsigned long) MODULE->loadaddr) + MODULE->mips_gotsym; \
  42. strtab = (char *) (MODULE->dynamic_info[DT_STRTAB] + \
  43. (unsigned long) MODULE->loadaddr); \
  44. i = MODULE->mips_symtabno - MODULE->mips_gotsym; \
  45. while (i--) { \
  46. if (sym->st_shndx == SHN_UNDEF) { \
  47. if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
  48. sym->st_value) \
  49. *GOT_BASE = sym->st_value + \
  50. (unsigned long) MODULE->loadaddr; \
  51. else { \
  52. *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
  53. sym->st_name, MODULE->symbol_scope, NULL, 1); \
  54. } \
  55. } \
  56. else if (sym->st_shndx == SHN_COMMON) { \
  57. *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
  58. sym->st_name, MODULE->symbol_scope, NULL, 1); \
  59. } \
  60. else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
  61. *GOT_BASE != sym->st_value) \
  62. *GOT_BASE += (unsigned long) MODULE->loadaddr; \
  63. else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
  64. if (sym->st_other == 0) \
  65. *GOT_BASE += (unsigned long) MODULE->loadaddr; \
  66. } \
  67. else { \
  68. *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
  69. sym->st_name, MODULE->symbol_scope, NULL, 1); \
  70. } \
  71. \
  72. ++GOT_BASE; \
  73. ++sym; \
  74. } \
  75. } while (0)
  76. /*
  77. * Here is a macro to perform the GOT relocation. This is only
  78. * used when bootstrapping the dynamic loader.
  79. */
  80. #define PERFORM_BOOTSTRAP_GOT(got) \
  81. do { \
  82. Elf32_Sym *sym; \
  83. unsigned long i; \
  84. \
  85. /* Add load address displacement to all local GOT entries */ \
  86. i = 2; \
  87. while (i < tpnt->mips_local_gotno) \
  88. got[i++] += load_addr; \
  89. \
  90. /* Handle global GOT entries */ \
  91. got += tpnt->mips_local_gotno; \
  92. sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + \
  93. load_addr) + tpnt->mips_gotsym; \
  94. i = tpnt->mips_symtabno - tpnt->mips_gotsym; \
  95. \
  96. while (i--) { \
  97. if (sym->st_shndx == SHN_UNDEF || \
  98. sym->st_shndx == SHN_COMMON) \
  99. *got = load_addr + sym->st_value; \
  100. else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
  101. *got != sym->st_value) \
  102. *got += load_addr; \
  103. else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
  104. if (sym->st_other == 0) \
  105. *got += load_addr; \
  106. } \
  107. else \
  108. *got = load_addr + sym->st_value; \
  109. \
  110. got++; \
  111. sym++; \
  112. } \
  113. } while (0)
  114. /*
  115. * Here is a macro to perform a relocation. This is only used when
  116. * bootstrapping the dynamic loader.
  117. */
  118. #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) \
  119. switch(ELF32_R_TYPE((RELP)->r_info)) { \
  120. case R_MIPS_REL32: \
  121. if (symtab_index) { \
  122. if (symtab_index < tpnt->mips_gotsym) \
  123. *REL += SYMBOL; \
  124. } \
  125. else { \
  126. *REL += LOAD; \
  127. } \
  128. break; \
  129. case R_MIPS_NONE: \
  130. break; \
  131. default: \
  132. SEND_STDERR("Aiieeee!"); \
  133. _dl_exit(1); \
  134. }
  135. /*
  136. * Transfer control to the user's application, once the dynamic loader
  137. * is done. This routine has to exit the current function, then
  138. * call the _dl_elf_main function. For MIPS, we do it in assembly
  139. * because the stack doesn't get properly restored otherwise. Got look
  140. * at boot1_arch.h
  141. */
  142. #define START()
  143. /* Here we define the magic numbers that this dynamic loader should accept */
  144. #define MAGIC1 EM_MIPS
  145. #define MAGIC2 EM_MIPS_RS3_LE
  146. /* Used for error messages */
  147. #define ELF_TARGET "MIPS"
  148. unsigned long _dl_linux_resolver(unsigned long sym_index,
  149. unsigned long old_gpreg);
  150. #define do_rem(result, n, base) result = (n % base)