dl-sysdep.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * Various assembly language/system dependent hacks that are required
  3. * so that we can minimize the amount of platform specific code.
  4. *
  5. * Copyright (C) 2004-2007 Atmel Corporation
  6. *
  7. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  8. */
  9. /* Define this if the system uses RELOCA. */
  10. #define ELF_USES_RELOCA
  11. #include <elf.h>
  12. #define ARCH_NUM 1
  13. #define DT_AVR32_GOTSZ_IDX (DT_NUM + OS_NUM)
  14. #define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
  15. do { \
  16. if (dpnt->d_tag == DT_AVR32_GOTSZ) \
  17. dynamic[DT_AVR32_GOTSZ_IDX] = dpnt->d_un.d_val; \
  18. } while (0)
  19. /* Initialization sequence for the application/library GOT. */
  20. #define INIT_GOT(GOT_BASE,MODULE) \
  21. do { \
  22. unsigned long _i, _nr_got; \
  23. \
  24. GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
  25. GOT_BASE[1] = (unsigned long) MODULE; \
  26. \
  27. /* Add load address displacement to all GOT entries */ \
  28. _nr_got = MODULE->dynamic_info[DT_AVR32_GOTSZ_IDX] / 4; \
  29. for (_i = 2; _i < _nr_got; _i++) \
  30. GOT_BASE[_i] += (unsigned long)MODULE->loadaddr; \
  31. } while (0)
  32. /* Here we define the magic numbers that this dynamic loader should accept */
  33. #define MAGIC1 EM_AVR32
  34. #undef MAGIC2
  35. /* Used for error messages */
  36. #define ELF_TARGET "AVR32"
  37. /* Need bootstrap relocations */
  38. #define ARCH_NEEDS_BOOTSTRAP_RELOCS
  39. unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
  40. #define elf_machine_type_class(type) \
  41. ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
  42. /* AVR32 doesn't need any COPY relocs */
  43. #define DL_NO_COPY_RELOCS
  44. /* Return the link-time address of _DYNAMIC. Conveniently, this is the
  45. first element of the GOT. This must be inlined in a function which
  46. uses global data. */
  47. static __always_inline Elf32_Addr
  48. elf_machine_dynamic (void)
  49. {
  50. register Elf32_Addr *got __asm__("r6");
  51. return *got;
  52. }
  53. /* Return the run-time load address of the shared object. */
  54. static __always_inline Elf32_Addr
  55. elf_machine_load_address (void)
  56. {
  57. extern void __dl_start __asm__("_dl_start");
  58. Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
  59. Elf32_Addr pcrel_addr;
  60. __asm__(" lddpc %0, 2f\n"
  61. "1: add %0, pc\n"
  62. " rjmp 3f\n"
  63. " .align 2\n"
  64. "2: .long _dl_start - 1b\n"
  65. "3:\n"
  66. : "=r"(pcrel_addr) : : "cc");
  67. return pcrel_addr - got_addr;
  68. }
  69. /*
  70. * Perform any RELATIVE relocations specified by DT_RELCOUNT.
  71. * Currently, we don't use that tag, but we might in the future as
  72. * this would reduce the startup time somewhat (although probably not by much).
  73. */
  74. static __always_inline void
  75. elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
  76. Elf32_Word relative_count)
  77. {
  78. Elf32_Rela *rpnt = (void *)rel_addr;
  79. do {
  80. Elf32_Addr *reloc_addr;
  81. reloc_addr = (void *)(load_off + (rpnt++)->r_offset);
  82. *reloc_addr = load_off + rpnt->r_addend;
  83. } while (--relative_count);
  84. }