dl-sysdep.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* CRIS can never use Elf32_Rel relocations. */
  2. #define ELF_USES_RELOCA
  3. #include <elf.h>
  4. /* Initialization sequence for the GOT. */
  5. #define INIT_GOT(GOT_BASE,MODULE) \
  6. { \
  7. GOT_BASE[1] = (unsigned long) MODULE; \
  8. GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
  9. }
  10. /* Defined some magic numbers that this ld.so should accept. */
  11. #define MAGIC1 EM_CRIS
  12. #undef MAGIC2
  13. #define ELF_TARGET "CRIS"
  14. struct elf_resolve;
  15. extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry);
  16. /* Cheap modulo implementation, taken from arm/dl-sysdep.h. */
  17. static inline unsigned long
  18. cris_mod(unsigned long m, unsigned long p)
  19. {
  20. unsigned long i, t, inc;
  21. i = p;
  22. t = 0;
  23. while (!(i & (1 << 31))) {
  24. i <<= 1;
  25. t++;
  26. }
  27. t--;
  28. for (inc = t; inc > 2; inc--) {
  29. i = p << inc;
  30. if (i & (1 << 31))
  31. break;
  32. while (m >= i) {
  33. m -= i;
  34. i <<= 1;
  35. if (i & (1 << 31))
  36. break;
  37. if (i < p)
  38. break;
  39. }
  40. }
  41. while (m >= p)
  42. m -= p;
  43. return m;
  44. }
  45. #define do_rem(result, n, base) ((result) = cris_mod(n, base))
  46. /* 8192 bytes alignment */
  47. #define PAGE_ALIGN 0xffffe000
  48. #define ADDR_ALIGN 0x1fff
  49. #define OFFS_ALIGN 0xffffe000
  50. /* The union of reloc-type-classes where the reloc TYPE is a member.
  51. TYPE is in the class ELF_RTYPE_CLASS_PLT if it can describe a
  52. relocation for a PLT entry, that is, for which a PLT entry should not
  53. be allowed to define the value. The GNU linker for CRIS can merge a
  54. .got.plt entry (R_CRIS_JUMP_SLOT) with a .got entry (R_CRIS_GLOB_DAT),
  55. so we need to match both these reloc types.
  56. TYPE is in the class ELF_RTYPE_CLASS_NOCOPY if it should not be allowed
  57. to resolve to one of the main executable's symbols, as for a COPY
  58. reloc. */
  59. #define elf_machine_type_class(type) \
  60. ((((((type) == R_CRIS_JUMP_SLOT)) \
  61. || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT) \
  62. | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY))
  63. static inline Elf32_Addr
  64. elf_machine_dynamic(void)
  65. {
  66. /* Don't just set this to an asm variable "r0" since that's not logical
  67. (like, the variable is uninitialized and the register is fixed) and
  68. may make GCC trip over itself doing register allocation. Yes, I'm
  69. paranoid. Why do you ask? */
  70. Elf32_Addr *got;
  71. __asm__ ("move.d $r0,%0" : "=rm" (got));
  72. return *got;
  73. }
  74. /* Return the run-time load address of the shared object. We do it like
  75. m68k and i386, by taking an arbitrary local symbol, forcing a GOT entry
  76. for it, and peeking into the GOT table, which is set to the link-time
  77. file-relative symbol value (regardless of whether the target is REL or
  78. RELA). We subtract this link-time file-relative value from the "local"
  79. value we calculate from GOT position and GOT offset. FIXME: Perhaps
  80. there's some other symbol we could use, that we don't *have* to force a
  81. GOT entry for. */
  82. static inline Elf32_Addr
  83. elf_machine_load_address(void)
  84. {
  85. Elf32_Addr gotaddr_diff;
  86. __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t"
  87. "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff));
  88. return gotaddr_diff;
  89. }
  90. static inline void
  91. elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr,
  92. Elf32_Word relative_count)
  93. {
  94. Elf32_Rela *rpnt = (void *)(rel_addr + load_off);
  95. --rpnt;
  96. do {
  97. Elf32_Addr *const reloc_addr =
  98. (void *)(load_off + (++rpnt)->r_offset);
  99. *reloc_addr = load_off + rpnt->r_addend;
  100. } while (--relative_count);
  101. }