dl-sysdep.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Various assmbly language/system dependent hacks that are required
  3. * so that we can minimize the amount of platform specific code.
  4. */
  5. #define LINUXBIN
  6. /* Define this if the system uses RELOCA. */
  7. #define ELF_USES_RELOCA
  8. #include <elf.h>
  9. /*
  10. * Initialization sequence for a GOT. For the Sparc, this points to the
  11. * PLT, and we need to initialize a couple of the slots. The PLT should
  12. * look like:
  13. *
  14. * save %sp, -64, %sp
  15. * call _dl_linux_resolve
  16. * nop
  17. * .word implementation_dependent
  18. */
  19. #define INIT_GOT(GOT_BASE,MODULE) \
  20. { \
  21. GOT_BASE[0] = 0x9de3bfc0; /* save %sp, -64, %sp */ \
  22. GOT_BASE[1] = 0x40000000 | (((unsigned int) _dl_linux_resolve - (unsigned int) GOT_BASE - 4) >> 2); \
  23. GOT_BASE[2] = 0x01000000; /* nop */ \
  24. GOT_BASE[3] = (int) MODULE; \
  25. }
  26. /* Here we define the magic numbers that this dynamic loader should accept */
  27. #define MAGIC1 EM_SPARC
  28. #undef MAGIC2
  29. /* Used for error messages */
  30. #define ELF_TARGET "Sparc"
  31. #ifndef COMPILE_ASM
  32. extern unsigned int _dl_linux_resolver(unsigned int reloc_entry,
  33. unsigned int * i);
  34. #endif
  35. /*
  36. * Define this if you want a dynamic loader that works on Solaris.
  37. */
  38. #ifndef __linux__
  39. #define SOLARIS_COMPATIBLE
  40. #endif
  41. #ifndef COMPILE_ASM
  42. /* Cheap modulo implementation, taken from arm/ld_sysdep.h. */
  43. static inline unsigned long
  44. sparc_mod(unsigned long m, unsigned long p)
  45. {
  46. unsigned long i, t, inc;
  47. i = p;
  48. t = 0;
  49. while (!(i & (1 << 31))) {
  50. i <<= 1;
  51. t++;
  52. }
  53. t--;
  54. for (inc = t; inc > 2; inc--) {
  55. i = p << inc;
  56. if (i & (1 << 31))
  57. break;
  58. while (m >= i) {
  59. m -= i;
  60. i <<= 1;
  61. if (i & (1 << 31))
  62. break;
  63. if (i < p)
  64. break;
  65. }
  66. }
  67. while (m >= p)
  68. m -= p;
  69. return m;
  70. }
  71. #define do_rem(result, n, base) ((result) = sparc_mod(n, base))
  72. #endif
  73. /*
  74. * dbx wants the binder to have a specific name. Mustn't disappoint it.
  75. */
  76. #ifdef SOLARIS_COMPATIBLE
  77. #define _dl_linux_resolve _elf_rtbndr
  78. #endif
  79. /* 4096 bytes alignment */
  80. /* ...but 8192 is required for mmap() on sparc64 kernel */
  81. #define PAGE_ALIGN 0xffffe000
  82. #define ADDR_ALIGN 0x1fff
  83. #define OFFS_ALIGN 0x7fffe000
  84. /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
  85. PLT entries should not be allowed to define the value.
  86. ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
  87. of the main executable's symbols, as for a COPY reloc. */
  88. #define elf_machine_type_class(type) \
  89. ((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
  90. | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
  91. /* The SPARC overlaps DT_RELA and DT_PLTREL. */
  92. #define ELF_MACHINE_PLTREL_OVERLAP 1
  93. /* We have to do this because elf_machine_{dynamic,load_address} can be
  94. invoked from functions that have no GOT references, and thus the compiler
  95. has no obligation to load the PIC register. */
  96. #define LOAD_PIC_REG(PIC_REG) \
  97. do { register Elf32_Addr pc __asm("o7"); \
  98. __asm("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \
  99. "call 1f\n\t" \
  100. "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n" \
  101. "1:\tadd %1, %0, %1" \
  102. : "=r" (pc), "=r" (PIC_REG)); \
  103. } while (0)
  104. /* Return the link-time address of _DYNAMIC. Conveniently, this is the
  105. first element of the GOT. This must be inlined in a function which
  106. uses global data. */
  107. static inline Elf32_Addr
  108. elf_machine_dynamic (void)
  109. {
  110. register Elf32_Addr *got asm ("%l7");
  111. LOAD_PIC_REG (got);
  112. return *got;
  113. }
  114. /* Return the run-time load address of the shared object. */
  115. static inline Elf32_Addr
  116. elf_machine_load_address (void)
  117. {
  118. register Elf32_Addr *pc __asm ("%o7"), *got __asm ("%l7");
  119. __asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"
  120. "call 1f\n\t"
  121. " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"
  122. "call _DYNAMIC\n\t"
  123. "call _GLOBAL_OFFSET_TABLE_\n"
  124. "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got));
  125. /* got is now l_addr + _GLOBAL_OFFSET_TABLE_
  126. *got is _DYNAMIC
  127. pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8
  128. pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12 */
  129. return (Elf32_Addr) got - *got + (pc[2] - pc[3]) * 4 - 4;
  130. }
  131. static inline void
  132. elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
  133. Elf32_Word relative_count)
  134. {
  135. Elf32_Rela * rpnt = (void *) (rel_addr + load_off);
  136. --rpnt;
  137. do {
  138. Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
  139. *reloc_addr = load_off + rpnt->r_addend;
  140. } while (--relative_count);
  141. }