summaryrefslogtreecommitdiff
path: root/ldso/ldso/avr32/dl-sysdep.h
diff options
context:
space:
mode:
Diffstat (limited to 'ldso/ldso/avr32/dl-sysdep.h')
-rw-r--r--ldso/ldso/avr32/dl-sysdep.h105
1 files changed, 105 insertions, 0 deletions
diff --git a/ldso/ldso/avr32/dl-sysdep.h b/ldso/ldso/avr32/dl-sysdep.h
new file mode 100644
index 000000000..270800ade
--- /dev/null
+++ b/ldso/ldso/avr32/dl-sysdep.h
@@ -0,0 +1,105 @@
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ *
+ * Copyright (C) 2004-2007 Atmel Corporation
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+
+#include <elf.h>
+
+#define ARCH_NUM 1
+#define DT_AVR32_GOTSZ_IDX (DT_NUM + OS_NUM)
+
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+ do { \
+ if (dpnt->d_tag == DT_AVR32_GOTSZ) \
+ dynamic[DT_AVR32_GOTSZ_IDX] = dpnt->d_un.d_val; \
+ } while (0)
+
+/* Initialization sequence for the application/library GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+ do { \
+ unsigned long i, nr_got; \
+ \
+ GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+ \
+ /* Add load address displacement to all GOT entries */ \
+ nr_got = MODULE->dynamic_info[DT_AVR32_GOTSZ_IDX] / 4; \
+ for (i = 2; i < nr_got; i++) \
+ GOT_BASE[i] += (unsigned long)MODULE->loadaddr; \
+ } while (0)
+
+#define do_rem(result, n, base) ((result) = (n) % (base))
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_AVR32
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "AVR32"
+
+unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
+
+/* 4096 bytes alignment */
+#define PAGE_ALIGN 0xfffff000
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000
+
+#define elf_machine_type_class(type) \
+ ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
+
+/* AVR32 doesn't need any COPY relocs */
+#define DL_NO_COPY_RELOCS
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+ register Elf32_Addr *got asm ("r6");
+ return *got;
+}
+
+/* Return the run-time load address of the shared object. */
+static inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ extern void __dl_start asm("_dl_start");
+ Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+ Elf32_Addr pcrel_addr;
+
+ asm (" lddpc %0, 2f\n"
+ "1: add %0, pc\n"
+ " rjmp 3f\n"
+ " .align 2\n"
+ "2: .long _dl_start - 1b\n"
+ "3:\n"
+ : "=r"(pcrel_addr) : : "cc");
+
+ return pcrel_addr - got_addr;
+}
+
+/*
+ * Perform any RELATIVE relocations specified by DT_RELCOUNT.
+ * Currently, we don't use that tag, but we might in the future as
+ * this would reduce the startup time somewhat (although probably not by much).
+ */
+static inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rela *rpnt = (void *)rel_addr;
+
+ do {
+ Elf32_Addr *reloc_addr;
+ reloc_addr = (void *)(load_off + (rpnt++)->r_offset);
+ *reloc_addr = load_off + rpnt->r_addend;
+ } while (--relative_count);
+}