diff options
Diffstat (limited to 'ldso/ldso/c6x/dl-sysdep.h')
-rw-r--r-- | ldso/ldso/c6x/dl-sysdep.h | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/ldso/ldso/c6x/dl-sysdep.h b/ldso/ldso/c6x/dl-sysdep.h new file mode 100644 index 000000000..8f1b122d3 --- /dev/null +++ b/ldso/ldso/c6x/dl-sysdep.h @@ -0,0 +1,209 @@ +/* Copyright (C) 2010 Texas Instruments Incorporated + * Contributed by Mark Salter <msalter@redhat.com> + * + * Borrowed heavily from frv arch: + * Copyright (C) 2003, 2004 Red Hat, Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <bits/elf-dsbt.h> + +/* + * Define this if the system uses RELOCA. + */ +#define ELF_USES_RELOCA 1 + +/* JMPREL relocs are inside the DT_RELA table. */ +/* Actually looks like a linker bug sets DT_JMPREL anyway */ +#define ELF_MACHINE_PLTREL_OVERLAP 1 + +#undef DL_NO_COPY_RELOCS + +#define HAVE_DL_INLINES_H + + +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_TI_C6000 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "C6000" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; + +extern int _dl_linux_resolve(void) attribute_hidden; + +struct funcdesc_ht; +struct elf32_dsbt_loadaddr; + +/* We must force strings used early in the bootstrap into the text + segment (const data), such that they are referenced relative to + the DP register rather than through the GOT which will not have + been relocated when these are used. */ +#undef SEND_EARLY_STDERR +#define SEND_EARLY_STDERR(S) \ + do { static char __s[] = (S); SEND_STDERR (__s); } while (0) + +#define DL_LOADADDR_TYPE struct elf32_dsbt_loadaddr + +#define DL_RELOC_ADDR(LOADADDR, ADDR) \ + ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map)) + +#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ + do { \ + struct elf32_dsbt_loadmap *map; \ + map = dl_boot_ldsomap ?: dl_boot_progmap; \ + if (map->version != 0) { \ + SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \ + _dl_exit(-1); \ + } \ + if (map->nsegs < 2) { \ + SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \ + _dl_exit(-1); \ + } \ + (LOADADDR).map = map; \ + } while(0) + +#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ + do { \ + if (dl_boot_progmap->version != 0) { \ + SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \ + _dl_exit(-1); \ + } \ + if (dl_boot_progmap->nsegs < 2) { \ + SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \ + _dl_exit(-1); \ + } \ + (LOADADDR).map = dl_boot_progmap; \ + } while(0) + +#define DL_INIT_LOADADDR_EXTRA_DECLS \ + int dl_init_loadaddr_load_count; + +#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ + (dl_init_loadaddr_load_count = \ + __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT))) + +#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \ + (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \ + dl_init_loadaddr_load_count)) + +#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \ + (__dl_loadaddr_unmap ((LOADADDR))) + +#define DL_LIB_UNMAP(LIB, LEN) \ + (__dl_loadaddr_unmap ((LIB)->loadaddr)) + +#define DL_LOADADDR_BASE(LOADADDR) \ + ((LOADADDR).map->dsbt_table) + +#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ + (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr)) + + +/* We only support loading DSBT relocatable shared libraries. + It probably wouldn't be too hard to support loading statically + linked executables that require relocation.*/ +#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \ +do \ +{ \ + (piclib) = 2; \ +} \ +while (0) + +/* We want want to apply all relocations in the interpreter during + bootstrap. Because of this, we have to skip the interpreter + relocations in _dl_parse_relocation_information(), see + elfinterp.c. */ +#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0 + +#ifdef __NR_pread64 +#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \ + (_dl_pread((FD), (BUF), (SIZE), (OFFSET))) +#endif + +#define DL_GET_READY_TO_RUN_EXTRA_PARMS \ + , struct elf32_dsbt_loadmap *dl_boot_progmap \ + , struct elf32_dsbt_loadmap *dl_boot_ldsomap +#define DL_GET_READY_TO_RUN_EXTRA_ARGS \ + , dl_boot_progmap \ + , dl_boot_ldsomap + + +/* + * Compute the GOT address. + * Also setup program and interpreter DSBT table entries. + */ +#define DL_BOOT_COMPUTE_GOT(GOT) \ + do { \ + unsigned long *ldso_dsbt, *prog_dsbt; \ + ldso_dsbt = dl_boot_ldsomap->dsbt_table; \ + prog_dsbt = dl_boot_progmap->dsbt_table; \ + ldso_dsbt[0] = prog_dsbt[0] = (unsigned long)prog_dsbt; \ + ldso_dsbt[1] = prog_dsbt[1] = (unsigned long)ldso_dsbt; \ + (GOT) = ldso_dsbt + dl_boot_ldsomap->dsbt_size; \ + } while(0) + +#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \ + ((dpnt) = dl_boot_ldso_dyn_pointer) + + +#ifdef __USE_GNU +# include <link.h> +#else +# define __USE_GNU +# include <link.h> +# undef __USE_GNU +#endif + +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + /* this is never an issue on DSBT systems */ + return 0; +} + +static __always_inline void +elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ +} + +/* 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_C6000_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_C6000_COPY) * ELF_RTYPE_CLASS_COPY)) + +#define ARCH_NUM 3 +#define DT_DSBT_BASE_IDX (DT_NUM + OS_NUM) +#define DT_DSBT_SIZE_IDX (DT_NUM + OS_NUM + 1) +#define DT_DSBT_INDEX_IDX (DT_NUM + OS_NUM + 2) + +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ +do { \ +if (dpnt->d_tag == DT_C6000_DSBT_BASE) \ + dynamic[DT_DSBT_BASE_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_C6000_DSBT_SIZE) \ + dynamic[DT_DSBT_SIZE_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_C6000_DSBT_INDEX) \ + dynamic[DT_DSBT_INDEX_IDX] = dpnt->d_un.d_val; \ +} while (0) |