dl-sysdep.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. /* Need bootstrap relocations */
  15. #define ARCH_NEEDS_BOOTSTRAP_RELOCS
  16. struct elf_resolve;
  17. extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry);
  18. /* The union of reloc-type-classes where the reloc TYPE is a member.
  19. TYPE is in the class ELF_RTYPE_CLASS_PLT if it can describe a
  20. relocation for a PLT entry, that is, for which a PLT entry should not
  21. be allowed to define the value. The GNU linker for CRIS can merge a
  22. .got.plt entry (R_CRIS_JUMP_SLOT) with a .got entry (R_CRIS_GLOB_DAT),
  23. so we need to match both these reloc types.
  24. TYPE is in the class ELF_RTYPE_CLASS_NOCOPY if it should not be allowed
  25. to resolve to one of the main executable's symbols, as for a COPY
  26. reloc. */
  27. #define elf_machine_type_class(type) \
  28. ((((((type) == R_CRIS_JUMP_SLOT)) \
  29. || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT) \
  30. | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY))
  31. static __always_inline Elf32_Addr
  32. elf_machine_dynamic(void)
  33. {
  34. /* Don't just set this to an asm variable "r0" since that's not logical
  35. (like, the variable is uninitialized and the register is fixed) and
  36. may make GCC trip over itself doing register allocation. Yes, I'm
  37. paranoid. Why do you ask? */
  38. Elf32_Addr *got;
  39. __asm__ ("move.d $r0,%0" : "=rm" (got));
  40. return *got;
  41. }
  42. /* Return the run-time load address of the shared object. We do it like
  43. m68k and i386, by taking an arbitrary local symbol, forcing a GOT entry
  44. for it, and peeking into the GOT table, which is set to the link-time
  45. file-relative symbol value (regardless of whether the target is REL or
  46. RELA). We subtract this link-time file-relative value from the "local"
  47. value we calculate from GOT position and GOT offset. FIXME: Perhaps
  48. there's some other symbol we could use, that we don't *have* to force a
  49. GOT entry for. */
  50. static __always_inline Elf32_Addr
  51. elf_machine_load_address(void)
  52. {
  53. Elf32_Addr gotaddr_diff;
  54. #ifdef __arch_v32
  55. extern char ___CRISv32_dummy[] __asm__ ("_dl_start");
  56. __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t"
  57. "lapc _dl_start,%0\n\t"
  58. "sub.d [$acr],%0"
  59. /* For v32, we need to force GCC to have R0 loaded with
  60. _GLOBAL_OFFSET_TABLE_ at this point, which might not
  61. otherwise have happened in the caller. (For v10, it's
  62. loaded for non-global variables too, so we don't need
  63. anything special there.) We accomplish this by faking the
  64. address of a global variable (as seen by GCC) as input to
  65. the asm; that address calculation goes through the GOT.
  66. Use of this function happens before we've filled in the
  67. GOT, so the address itself will not be correctly
  68. calculated, therefore we don't use any symbol whose
  69. address may be re-used later on. Let's just reuse the
  70. _dl_start symbol, faking it as a global by renaming it as
  71. another variable through an asm. */
  72. : "=r" (gotaddr_diff)
  73. : "g" (___CRISv32_dummy)
  74. : "acr");
  75. #else
  76. __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t"
  77. "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff));
  78. #endif
  79. return gotaddr_diff;
  80. }
  81. static __always_inline void
  82. elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr,
  83. Elf32_Word relative_count)
  84. {
  85. Elf32_Rela *rpnt = (void *)rel_addr;
  86. --rpnt;
  87. do {
  88. Elf32_Addr *const reloc_addr =
  89. (void *)(load_off + (++rpnt)->r_offset);
  90. *reloc_addr = load_off + rpnt->r_addend;
  91. } while (--relative_count);
  92. }