diff options
Diffstat (limited to 'ldso/ldso/avr32/dl-sysdep.h')
-rw-r--r-- | ldso/ldso/avr32/dl-sysdep.h | 105 |
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); +} |