diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2016-04-21 01:25:29 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-06-30 03:24:42 +0200 |
commit | ee92c0fe5c1b9d59508273916e2c9a75b68dbc13 (patch) | |
tree | 65a22258b12f84325910fc2ad47e2b02696ef593 /ldso/ldso/nds32/dl-sysdep.h | |
parent | dd46699e46decb7273f44dc2cbf307f096dc39e8 (diff) |
nds32: add support for new architecture
Add support for Andes Technology NDS32 architecture.
See here http://www.andestech.com/en/index/index.htm for more
informaton. Verification of the port from an older uClibc
port was done on a sponsored AG101p board.
The testsuite only has 5 errors, three are related to
an existing bug in dlclose() with LT.old, also happening
on cris32 and m68k.
Failures to fallocate/posix_fallocate are unresolved.
Thanks to Andes Technology sponsoring the hardware and
being very helpful while doing the uClibc-ng porting.
Signed-off-by: Waldemar Brodkorb <wbx@uclibc-ng.org>
Diffstat (limited to 'ldso/ldso/nds32/dl-sysdep.h')
-rw-r--r-- | ldso/ldso/nds32/dl-sysdep.h | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/ldso/ldso/nds32/dl-sysdep.h b/ldso/ldso/nds32/dl-sysdep.h new file mode 100644 index 000000000..c4a32ca71 --- /dev/null +++ b/ldso/ldso/nds32/dl-sysdep.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * 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> +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +static __inline__ unsigned long nds32_modulus(unsigned long m, unsigned long p) +{ + unsigned long i,t,inc; + i=p; t=0; + while (!(i&(1<<31))) { + i<<=1; + t++; + } + t--; + for (inc=t;inc>2;inc--) { + i=p<<inc; + if (i&(1<<31)) + break; + while (m>=i) { + m-=i; + i<<=1; + if (i&(1<<31)) + break; + if (i<p) + break; + } + } + while (m>=p) { + m-=p; + } + return m; +} +#define do_rem(result, n, base) ((result) = nds32_modulus(n, base)) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_NDS32 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "NDS32" + +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_NDS32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_NDS32_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. We used to use the PIC register to do this + without a constant pool reference, but GCC 4.2 will use a pseudo-register + for the PIC base, so it may not be in r10. */ +static __inline__ Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + Elf32_Addr link_addr; + __asm__ ( "l.w %0, _GLOBAL_OFFSET_TABLE_@GOTOFF": "=r" (link_addr) ); + return link_addr; +} + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + /* It doesn't matter what variable this is, the reference never makes + it to assembly. We need a dummy reference to some global variable + via the GOT to make sure the compiler initialized %ebx in time. */ + + Elf32_Addr addr; + __asm__ ("la %0, _dl_start@GOTOFF\n" : "=r" (addr) ); + return addr - elf_machine_dynamic(); +} + +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; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} |