dl-sysdep.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. #define do_rem(result, n, base) ((result) = (n) % (base))
  33. /* Here we define the magic numbers that this dynamic loader should accept */
  34. #define MAGIC1 EM_AVR32
  35. #undef MAGIC2
  36. /* Used for error messages */
  37. #define ELF_TARGET "AVR32"
  38. unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
  39. /* 4096 bytes alignment */
  40. #define PAGE_ALIGN 0xfffff000
  41. #define ADDR_ALIGN 0xfff
  42. #define OFFS_ALIGN 0x7ffff000
  43. #define elf_machine_type_class(type) \
  44. ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
  45. /* AVR32 doesn't need any COPY relocs */
  46. #define DL_NO_COPY_RELOCS
  47. /* Return the link-time address of _DYNAMIC. Conveniently, this is the
  48. first element of the GOT. This must be inlined in a function which
  49. uses global data. */
  50. static inline Elf32_Addr
  51. elf_machine_dynamic (void)
  52. {
  53. register Elf32_Addr *got asm ("r6");
  54. return *got;
  55. }
  56. /* Return the run-time load address of the shared object. */
  57. static inline Elf32_Addr
  58. elf_machine_load_address (void)
  59. {
  60. extern void __dl_start asm("_dl_start");
  61. Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
  62. Elf32_Addr pcrel_addr;
  63. asm (" lddpc %0, 2f\n"
  64. "1: add %0, pc\n"
  65. " rjmp 3f\n"
  66. " .align 2\n"
  67. "2: .long _dl_start - 1b\n"
  68. "3:\n"
  69. : "=r"(pcrel_addr) : : "cc");
  70. return pcrel_addr - got_addr;
  71. }
  72. /*
  73. * Perform any RELATIVE relocations specified by DT_RELCOUNT.
  74. * Currently, we don't use that tag, but we might in the future as
  75. * this would reduce the startup time somewhat (although probably not by much).
  76. */
  77. static inline void
  78. elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
  79. Elf32_Word relative_count)
  80. {
  81. Elf32_Rela *rpnt = (void *)rel_addr;
  82. do {
  83. Elf32_Addr *reloc_addr;
  84. reloc_addr = (void *)(load_off + (rpnt++)->r_offset);
  85. *reloc_addr = load_off + rpnt->r_addend;
  86. } while (--relative_count);
  87. }