dl-sysdep.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Various assembly language/system dependent hacks that are required
  3. * so that we can minimize the amount of platform specific code.
  4. * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
  5. */
  6. #ifndef _ARCH_DL_SYSDEP
  7. #define _ARCH_DL_SYSDEP
  8. /* Define this if the system uses RELOCA. */
  9. #undef ELF_USES_RELOCA
  10. #include <elf.h>
  11. #ifdef __FDPIC__
  12. /* Need bootstrap relocations */
  13. #define ARCH_NEEDS_BOOTSTRAP_RELOCS
  14. #define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
  15. do \
  16. { \
  17. (piclib) = 2; \
  18. } \
  19. while (0)
  20. #endif /* __FDPIC__ */
  21. /* Initialization sequence for the GOT. */
  22. #define INIT_GOT(GOT_BASE,MODULE) \
  23. { \
  24. GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
  25. GOT_BASE[1] = (unsigned long) MODULE; \
  26. }
  27. static __always_inline unsigned long arm_modulus(unsigned long m, unsigned long p)
  28. {
  29. unsigned long i,t,inc;
  30. i=p; t=0;
  31. while (!(i&(1<<31))) {
  32. i<<=1;
  33. t++;
  34. }
  35. t--;
  36. for (inc=t;inc>2;inc--) {
  37. i=p<<inc;
  38. if (i&(1<<31))
  39. break;
  40. while (m>=i) {
  41. m-=i;
  42. i<<=1;
  43. if (i&(1<<31))
  44. break;
  45. if (i<p)
  46. break;
  47. }
  48. }
  49. while (m>=p) {
  50. m-=p;
  51. }
  52. return m;
  53. }
  54. #define do_rem(result, n, base) ((result) = arm_modulus(n, base))
  55. #define do_div_10(result, remain) ((result) = (((result) - (remain)) / 2) * -(-1ul / 5ul))
  56. /* Here we define the magic numbers that this dynamic loader should accept */
  57. #define MAGIC1 EM_ARM
  58. #undef MAGIC2
  59. /* Used for error messages */
  60. #define ELF_TARGET "ARM"
  61. struct elf_resolve;
  62. unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
  63. /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
  64. TLS variable, so undefined references should not be allowed to
  65. define the value.
  66. ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
  67. of the main executable's symbols, as for a COPY reloc. */
  68. #ifdef __FDPIC__
  69. /* Avoid R_ARM_ABS32 to go through the PLT so that R_ARM_TARGET1
  70. translated to R_ARM_ABS32 doesn't use the PLT: otherwise, this
  71. breaks init_array because functions are referenced through the
  72. PLT. */
  73. #define elf_machine_type_class(type) \
  74. ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32 \
  75. || (type) == R_ARM_FUNCDESC_VALUE || (type) == R_ARM_FUNCDESC || (type) == R_ARM_ABS32 \
  76. || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32) \
  77. * ELF_RTYPE_CLASS_PLT) \
  78. | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
  79. #else
  80. #define elf_machine_type_class(type) \
  81. ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32 \
  82. || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32) \
  83. * ELF_RTYPE_CLASS_PLT) \
  84. | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
  85. #endif /* __FDPIC__ */
  86. /* Return the link-time address of _DYNAMIC. Conveniently, this is the
  87. first element of the GOT. We used to use the PIC register to do this
  88. without a constant pool reference, but GCC 4.2 will use a pseudo-register
  89. for the PIC base, so it may not be in r10. */
  90. static __always_inline Elf32_Addr __attribute__ ((unused))
  91. elf_machine_dynamic (void)
  92. {
  93. Elf32_Addr dynamic;
  94. #if !defined __thumb__
  95. __asm__ ("ldr %0, 2f\n"
  96. "1: ldr %0, [pc, %0]\n"
  97. "b 3f\n"
  98. "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
  99. "3:" : "=r" (dynamic));
  100. #else
  101. int tmp;
  102. __asm__ (".align 2\n"
  103. "bx pc\n"
  104. "nop\n"
  105. ".arm\n"
  106. "ldr %0, 2f\n"
  107. "1: ldr %0, [pc, %0]\n"
  108. "b 3f\n"
  109. "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
  110. "3:"
  111. ".align 2\n"
  112. "orr %1, pc, #1\n"
  113. "bx %1\n"
  114. ".force_thumb\n"
  115. : "=r" (dynamic), "=&r" (tmp));
  116. #endif
  117. return dynamic;
  118. }
  119. extern char __dl_start[] __asm__("_dl_start");
  120. #ifdef __FDPIC__
  121. /* We must force strings used early in the bootstrap into the data
  122. segment. */
  123. #undef SEND_EARLY_STDERR
  124. #define SEND_EARLY_STDERR(S) \
  125. do { /* FIXME: implement */; } while (0)
  126. #undef INIT_GOT
  127. #include "../fdpic/dl-sysdep.h"
  128. #endif /* __FDPIC__ */
  129. /* Return the run-time load address of the shared object. */
  130. static __always_inline Elf32_Addr __attribute__ ((unused))
  131. elf_machine_load_address (void)
  132. {
  133. #if defined(__FDPIC__)
  134. return 0;
  135. #else
  136. Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
  137. Elf32_Addr pcrel_addr;
  138. #if defined __OPTIMIZE__ && !defined __thumb__
  139. __asm__ ("adr %0, _dl_start" : "=r" (pcrel_addr));
  140. #else
  141. /* A simple adr does not work in Thumb mode because the offset is
  142. negative, and for debug builds may be too large. */
  143. int tmp;
  144. __asm__ ("adr %1, 1f\n\t"
  145. "ldr %0, [%1]\n\t"
  146. "add %0, %0, %1\n\t"
  147. "b 2f\n\t"
  148. ".align 2\n\t"
  149. "1: .word _dl_start - 1b\n\t"
  150. "2:"
  151. : "=r" (pcrel_addr), "=r" (tmp));
  152. #endif
  153. return pcrel_addr - got_addr;
  154. #endif
  155. }
  156. static __always_inline void
  157. #ifdef __FDPIC__
  158. elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
  159. #else
  160. elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
  161. #endif
  162. Elf32_Word relative_count)
  163. {
  164. #if defined(__FDPIC__)
  165. Elf32_Rel *rpnt = (void *) rel_addr;
  166. do {
  167. unsigned long *reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_off, rpnt->r_offset);
  168. *reloc_addr = DL_RELOC_ADDR(load_off, *reloc_addr);
  169. rpnt++;
  170. #else
  171. Elf32_Rel * rpnt = (void *) rel_addr;
  172. --rpnt;
  173. do {
  174. Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
  175. *reloc_addr += load_off;
  176. #endif
  177. } while(--relative_count);
  178. }
  179. #endif /* !_ARCH_DL_SYSDEP */
  180. #ifdef __ARM_EABI__
  181. #define DL_MALLOC_ALIGN 8 /* EABI needs 8 byte alignment for STRD LDRD */
  182. #endif