dl-sysdep.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. #define elf_machine_type_class(type) \
  40. ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
  41. /* AVR32 doesn't need any COPY relocs */
  42. #define DL_NO_COPY_RELOCS
  43. /* Return the link-time address of _DYNAMIC. Conveniently, this is the
  44. first element of the GOT. This must be inlined in a function which
  45. uses global data. */
  46. static __always_inline Elf32_Addr
  47. elf_machine_dynamic (void)
  48. {
  49. register Elf32_Addr *got __asm__("r6");
  50. return *got;
  51. }
  52. /* Return the run-time load address of the shared object. */
  53. static __always_inline Elf32_Addr
  54. elf_machine_load_address (void)
  55. {
  56. extern void __dl_start __asm__("_dl_start");
  57. Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
  58. Elf32_Addr pcrel_addr;
  59. __asm__(" lddpc %0, 2f\n"
  60. "1: add %0, pc\n"
  61. " rjmp 3f\n"
  62. " .align 2\n"
  63. "2: .long _dl_start - 1b\n"
  64. "3:\n"
  65. : "=r"(pcrel_addr) : : "cc");
  66. return pcrel_addr - got_addr;
  67. }
  68. /*
  69. * Perform any RELATIVE relocations specified by DT_RELCOUNT.
  70. * Currently, we don't use that tag, but we might in the future as
  71. * this would reduce the startup time somewhat (although probably not by much).
  72. */
  73. static __always_inline void
  74. elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
  75. Elf32_Word relative_count)
  76. {
  77. Elf32_Rela *rpnt = (void *)rel_addr;
  78. do {
  79. Elf32_Addr *reloc_addr;
  80. reloc_addr = (void *)(load_off + (rpnt++)->r_offset);
  81. *reloc_addr = load_off + rpnt->r_addend;
  82. } while (--relative_count);
  83. }