diff options
Diffstat (limited to 'sysdeps/arm/dl-machine.h')
-rw-r--r-- | sysdeps/arm/dl-machine.h | 636 |
1 files changed, 0 insertions, 636 deletions
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h deleted file mode 100644 index 761f8da..0000000 --- a/sysdeps/arm/dl-machine.h +++ /dev/null @@ -1,636 +0,0 @@ -/* Machine-dependent ELF dynamic relocation inline functions. ARM version. - Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef dl_machine_h -#define dl_machine_h - -#define ELF_MACHINE_NAME "ARM" - -#include <sys/param.h> - -#define VALID_ELF_ABIVERSION(ver) (ver == 0) -#define VALID_ELF_OSABI(osabi) \ - (osabi == ELFOSABI_SYSV || osabi == ELFOSABI_ARM) -#define VALID_ELF_HEADER(hdr,exp,size) \ - memcmp (hdr,exp,size-2) == 0 \ - && VALID_ELF_OSABI (hdr[EI_OSABI]) \ - && VALID_ELF_ABIVERSION (hdr[EI_ABIVERSION]) - -#define CLEAR_CACHE(BEG,END) \ -{ \ - register unsigned long _beg __asm ("a1") = (unsigned long)(BEG); \ - register unsigned long _end __asm ("a2") = (unsigned long)(END); \ - register unsigned long _flg __asm ("a3") = 0; \ - __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" \ - : /* no outputs */ \ - : /* no inputs */ \ - : "a1"); \ -} - -/* Return nonzero iff ELF header is compatible with the running host. */ -static inline int __attribute__ ((unused)) -elf_machine_matches_host (const Elf32_Ehdr *ehdr) -{ - return ehdr->e_machine == EM_ARM; -} - - -/* 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 __attribute__ ((unused)) -elf_machine_dynamic (void) -{ - register Elf32_Addr *got asm ("r10"); - return *got; -} - - -/* Return the run-time load address of the shared object. */ -static inline Elf32_Addr __attribute__ ((unused)) -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 ("adr %0, _dl_start" : "=r" (pcrel_addr)); - return pcrel_addr - got_addr; -} - - -/* Set up the loaded object described by L so its unrelocated PLT - entries will jump to the on-demand fixup code in dl-runtime.c. */ - -static inline int __attribute__ ((unused)) -elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) -{ - Elf32_Addr *got; - extern void _dl_runtime_resolve (Elf32_Word); - extern void _dl_runtime_profile (Elf32_Word); - - if (l->l_info[DT_JMPREL] && lazy) - { - /* patb: this is different than i386 */ - /* The GOT entries for functions in the PLT have not yet been filled - in. Their initial contents will arrange when called to push an - index into the .got section, load ip with &_GLOBAL_OFFSET_TABLE_[3], - and then jump to _GLOBAL_OFFSET_TABLE[2]. */ - got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]); - /* If a library is prelinked but we have to relocate anyway, - we have to be able to undo the prelinking of .got.plt. - The prelinker saved us here address of .plt. */ - if (got[1]) - l->l_mach.plt = got[1] + l->l_addr; - got[1] = (Elf32_Addr) l; /* Identify this shared object. */ - - /* The got[2] entry contains the address of a function which gets - called to get the address of a so far unresolved function and - jump to it. The profiling extension of the dynamic linker allows - to intercept the calls to collect information. In this case we - don't store the address in the GOT so that all future calls also - end in this function. */ - if (profile) - { - got[2] = (Elf32_Addr) &_dl_runtime_profile; - - if (_dl_name_match_p (GLRO(dl_profile), l)) - /* Say that we really want profiling and the timers are - started. */ - GL(dl_profile_map) = l; - } - else - /* This function will get called to fix up the GOT entry indicated by - the offset on the stack, and then jump to the resolved address. */ - got[2] = (Elf32_Addr) &_dl_runtime_resolve; - } - return lazy; -} - -#if defined(__USE_BX__) -#define BX(x) "bx\t" #x -#else -#define BX(x) "mov\tpc, " #x -#endif - -#ifndef PROF -# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ - .text\n\ - .globl _dl_runtime_resolve\n\ - .type _dl_runtime_resolve, #function\n\ - .align 2\n\ -_dl_runtime_resolve:\n\ - @ we get called with\n\ - @ stack[0] contains the return address from this call\n\ - @ ip contains &GOT[n+3] (pointer to function)\n\ - @ lr points to &GOT[2]\n\ -\n\ - @ stack arguments\n\ - stmdb sp!,{r0-r3}\n\ -\n\ - @ get pointer to linker struct\n\ - ldr r0, [lr, #-4]\n\ -\n\ - @ prepare to call fixup()\n\ - @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\ - sub r1, ip, lr\n\ - sub r1, r1, #4\n\ - add r1, r1, r1\n\ -\n\ - @ call fixup routine\n\ - bl fixup\n\ -\n\ - @ save the return\n\ - mov ip, r0\n\ -\n\ - @ get arguments and return address back\n\ - ldmia sp!, {r0-r3,lr}\n\ -\n\ - @ jump to the newly found address\n\ - " BX(ip) "\n\ -\n\ - .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\ -\n\ - .globl _dl_runtime_profile\n\ - .type _dl_runtime_profile, #function\n\ - .align 2\n\ -_dl_runtime_profile:\n\ - @ stack arguments\n\ - stmdb sp!, {r0-r3}\n\ -\n\ - @ get pointer to linker struct\n\ - ldr r0, [lr, #-4]\n\ -\n\ - @ prepare to call fixup()\n\ - @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\ - sub r1, ip, lr\n\ - sub r1, r1, #4\n\ - add r1, r1, r1\n\ -\n\ - @ call profiling fixup routine\n\ - bl profile_fixup\n\ -\n\ - @ save the return\n\ - mov ip, r0\n\ -\n\ - @ get arguments and return address back\n\ - ldmia sp!, {r0-r3,lr}\n\ -\n\ - @ jump to the newly found address\n\ - " BX(ip) "\n\ -\n\ - .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\ - .previous\n\ -"); -#else // PROF -# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ - .text\n\ - .globl _dl_runtime_resolve\n\ - .globl _dl_runtime_profile\n\ - .type _dl_runtime_resolve, #function\n\ - .type _dl_runtime_profile, #function\n\ - .align 2\n\ -_dl_runtime_resolve:\n\ -_dl_runtime_profile:\n\ - @ we get called with\n\ - @ stack[0] contains the return address from this call\n\ - @ ip contains &GOT[n+3] (pointer to function)\n\ - @ lr points to &GOT[2]\n\ -\n\ - @ stack arguments\n\ - stmdb sp!, {r0-r3}\n\ -\n\ - @ get pointer to linker struct\n\ - ldr r0, [lr, #-4]\n\ -\n\ - @ prepare to call fixup()\n\ - @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\ - sub r1, ip, lr\n\ - sub r1, r1, #4\n\ - add r1, r1, r1\n\ -\n\ - @ call profiling fixup routine\n\ - bl fixup\n\ -\n\ - @ save the return\n\ - mov ip, r0\n\ -\n\ - @ get arguments and return address back\n\ - ldmia sp!, {r0-r3,lr}\n\ -\n\ - @ jump to the newly found address\n\ - " BX(ip) "\n\ -\n\ - .size _dl_runtime_profile, .-_dl_runtime_profile\n\ - .previous\n\ -"); -#endif //PROF - -/* Mask identifying addresses reserved for the user program, - where the dynamic linker should not map anything. */ -#define ELF_MACHINE_USER_ADDRESS_MASK 0xf8000000UL - -/* Initial entry point code for the dynamic linker. - The C function `_dl_start' is the real entry point; - its return value is the user program's entry point. */ - -#define RTLD_START asm ("\ -.text\n\ -.globl _start\n\ -.globl _dl_start_user\n\ -_start:\n\ - @ we are PIC code, so get global offset table\n\ - ldr sl, .L_GET_GOT\n\ - @ See if we were run as a command with the executable file\n\ - @ name as an extra leading argument.\n\ - ldr r4, .L_SKIP_ARGS\n\ - @ at start time, all the args are on the stack\n\ - mov r0, sp\n\ - bl _dl_start\n\ - @ returns user entry point in r0\n\ -_dl_start_user:\n\ - add sl, pc, sl\n\ -.L_GOT_GOT:\n\ - ldr r4, [sl, r4]\n\ - @ get the original arg count\n\ - ldr r1, [sp]\n\ - @ save the entry point in another register\n\ - mov r6, r0\n\ - @ adjust the stack pointer to skip the extra args\n\ - add sp, sp, r4, lsl #2\n\ - @ subtract _dl_skip_args from original arg count\n\ - sub r1, r1, r4\n\ - @ get the argv address\n\ - add r2, sp, #4\n\ - @ store the new argc in the new stack location\n\ - str r1, [sp]\n\ - @ compute envp\n\ - add r3, r2, r1, lsl #2\n\ - add r3, r3, #4\n\ -\n\ - @ now we call _dl_init\n\ - ldr r0, .L_LOADED\n\ - ldr r0, [sl, r0]\n\ - @ call _dl_init\n\ - bl _dl_init_internal(PLT)\n\ - @ load the finalizer function\n\ - ldr r0, .L_FINI_PROC\n\ - add r0, sl, r0\n\ - @ jump to the user_s entry point\n\ - " BX(r6) "\n\ -.L_GET_GOT:\n\ - .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n\ -.L_SKIP_ARGS:\n\ - .word _dl_skip_args(GOTOFF)\n\ -.L_FINI_PROC:\n\ - .word _dl_fini(GOTOFF)\n\ -.L_LOADED:\n\ - .word _rtld_local(GOTOFF)\n\ -.previous\n\ -"); - -/* 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_ARM_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ - | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY)) - -/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ -#define ELF_MACHINE_JMP_SLOT R_ARM_JUMP_SLOT - -/* ARM never uses Elf32_Rela relocations for the dynamic linker. - Prelinked libraries may use Elf32_Rela though. */ -#define ELF_MACHINE_PLT_REL 1 - -/* We define an initialization functions. This is called very early in - _dl_sysdep_start. */ -#define DL_PLATFORM_INIT dl_platform_init () - -static inline void __attribute__ ((unused)) -dl_platform_init (void) -{ - if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') - /* Avoid an empty string which would disturb us. */ - GLRO(dl_platform) = NULL; -} - -static inline Elf32_Addr -elf_machine_fixup_plt (struct link_map *map, lookup_t t, - const Elf32_Rel *reloc, - Elf32_Addr *reloc_addr, Elf32_Addr value) -{ - return *reloc_addr = value; -} - -/* Return the final value of a plt relocation. */ -static inline Elf32_Addr -elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc, - Elf32_Addr value) -{ - return value; -} - -#endif /* !dl_machine_h */ - -#ifdef RESOLVE - -/* ARM never uses Elf32_Rela relocations for the dynamic linker. - Prelinked libraries may use Elf32_Rela though. */ -# ifdef RTLD_BOOTSTRAP -# define ELF_MACHINE_NO_RELA 1 -# endif - -/* Deal with an out-of-range PC24 reloc. */ -static Elf32_Addr -fix_bad_pc24 (Elf32_Addr *const reloc_addr, Elf32_Addr value) -{ - static void *fix_page; - static unsigned int fix_offset; - static size_t pagesize; - Elf32_Word *fix_address; - - if (! fix_page) - { - if (! pagesize) - pagesize = getpagesize (); - fix_page = mmap (NULL, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (! fix_page) - assert (! "could not map page for fixup"); - fix_offset = 0; - } - - fix_address = (Elf32_Word *)(fix_page + fix_offset); - fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */ - fix_address[1] = value; - - fix_offset += 8; - if (fix_offset >= pagesize) - fix_page = NULL; - - return (Elf32_Addr)fix_address; -} - -/* Perform the relocation specified by RELOC and SYM (which is fully resolved). - MAP is the object containing the reloc. */ - -static inline void -elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, - const Elf32_Sym *sym, const struct r_found_version *version, - void *const reloc_addr_arg) -{ - Elf32_Addr *const reloc_addr = reloc_addr_arg; - const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); - -#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC - if (__builtin_expect (r_type == R_ARM_RELATIVE, 0)) - { -# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC - /* This is defined in rtld.c, but nowhere in the static libc.a; - make the reference weak so static programs can still link. - This declaration cannot be done when compiling rtld.c - (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the - common defn for _dl_rtld_map, which is incompatible with a - weak decl in the same file. */ -# ifndef SHARED - weak_extern (_dl_rtld_map); -# endif - if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ -# endif - *reloc_addr += map->l_addr; - } -# ifndef RTLD_BOOTSTRAP - else if (__builtin_expect (r_type == R_ARM_NONE, 0)) - return; -# endif - else -#endif - { - const Elf32_Sym *const refsym = sym; - Elf32_Addr value = RESOLVE (&sym, version, r_type); - if (sym) - value += sym->st_value; - - switch (r_type) - { - case R_ARM_COPY: - if (sym == NULL) - /* This can happen in trace mode if an object could not be - found. */ - break; - if (sym->st_size > refsym->st_size - || (GLRO(dl_verbose) && sym->st_size < refsym->st_size)) - { - const char *strtab; - - strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); - _dl_error_printf ("\ -%s: Symbol `%s' has different size in shared object, consider re-linking\n", - rtld_progname ?: "<program name unknown>", - strtab + refsym->st_name); - } - memcpy (reloc_addr_arg, (void *) value, - MIN (sym->st_size, refsym->st_size)); - break; - case R_ARM_GLOB_DAT: - case R_ARM_JUMP_SLOT: -# ifdef RTLD_BOOTSTRAP - /* Fix weak undefined references. */ - if (sym != NULL && sym->st_value == 0) - *reloc_addr = 0; - else -# endif - *reloc_addr = value; - break; - case R_ARM_ABS32: - { -# ifndef RTLD_BOOTSTRAP - /* This is defined in rtld.c, but nowhere in the static - libc.a; make the reference weak so static programs can - still link. This declaration cannot be done when - compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP) because - rtld.c contains the common defn for _dl_rtld_map, which - is incompatible with a weak decl in the same file. */ -# ifndef SHARED - weak_extern (_dl_rtld_map); -# endif - if (map == &GL(dl_rtld_map)) - /* Undo the relocation done here during bootstrapping. - Now we will relocate it anew, possibly using a - binding found in the user program or a loaded library - rather than the dynamic linker's built-in definitions - used while loading those libraries. */ - value -= map->l_addr + refsym->st_value; -# endif - *reloc_addr += value; - break; - } - case R_ARM_PC24: - { - Elf32_Sword addend; - Elf32_Addr newvalue, topbits; - - addend = *reloc_addr & 0x00ffffff; - if (addend & 0x00800000) addend |= 0xff000000; - - newvalue = value - (Elf32_Addr)reloc_addr + (addend << 2); - topbits = newvalue & 0xfe000000; - if (topbits != 0xfe000000 && topbits != 0x00000000) - { - newvalue = fix_bad_pc24(reloc_addr, value) - - (Elf32_Addr)reloc_addr + (addend << 2); - topbits = newvalue & 0xfe000000; - if (topbits != 0xfe000000 && topbits != 0x00000000) - { - _dl_signal_error (0, map->l_name, NULL, - "R_ARM_PC24 relocation out of range"); - } - } - newvalue >>= 2; - value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff); - *reloc_addr = value; - } - break; - default: - _dl_reloc_bad_type (map, r_type, 0); - break; - } - } -} - -# ifndef RTLD_BOOTSTRAP -static inline void -elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, - const Elf32_Sym *sym, const struct r_found_version *version, - void *const reloc_addr_arg) -{ - Elf32_Addr *const reloc_addr = reloc_addr_arg; - const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); - - if (__builtin_expect (r_type == R_ARM_RELATIVE, 0)) - *reloc_addr = map->l_addr + reloc->r_addend; - else if (__builtin_expect (r_type == R_ARM_NONE, 0)) - return; - else - { -# ifndef RESOLVE_CONFLICT_FIND_MAP - const Elf32_Sym *const refsym = sym; -# endif - Elf32_Addr value = RESOLVE (&sym, version, r_type); - if (sym) - value += sym->st_value; - - switch (r_type) - { -# ifndef RESOLVE_CONFLICT_FIND_MAP - /* Not needed for dl-conflict.c. */ - case R_ARM_COPY: - if (sym == NULL) - /* This can happen in trace mode if an object could not be - found. */ - break; - if (sym->st_size > refsym->st_size - || (GLRO(dl_verbose) && sym->st_size < refsym->st_size)) - { - const char *strtab; - - strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); - _dl_error_printf ("\ -%s: Symbol `%s' has different size in shared object, consider re-linking\n", - rtld_progname ?: "<program name unknown>", - strtab + refsym->st_name); - } - memcpy (reloc_addr_arg, (void *) value, - MIN (sym->st_size, refsym->st_size)); - break; -# endif /* !RESOLVE_CONFLICT_FIND_MAP */ - case R_ARM_GLOB_DAT: - case R_ARM_JUMP_SLOT: - case R_ARM_ABS32: - *reloc_addr = value + reloc->r_addend; - break; - case R_ARM_PC24: - { - Elf32_Addr newvalue, topbits; - - newvalue = value + reloc->r_addend - (Elf32_Addr)reloc_addr; - topbits = newvalue & 0xfe000000; - if (topbits != 0xfe000000 && topbits != 0x00000000) - { - newvalue = fix_bad_pc24(reloc_addr, value) - - (Elf32_Addr)reloc_addr + (reloc->r_addend << 2); - topbits = newvalue & 0xfe000000; - if (topbits != 0xfe000000 && topbits != 0x00000000) - { - _dl_signal_error (0, map->l_name, NULL, - "R_ARM_PC24 relocation out of range"); - } - } - newvalue >>= 2; - value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff); - *reloc_addr = value; - } - break; - default: - _dl_reloc_bad_type (map, r_type, 0); - break; - } - } -} -# endif - -static inline void -elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc, - void *const reloc_addr_arg) -{ - Elf32_Addr *const reloc_addr = reloc_addr_arg; - *reloc_addr += l_addr; -} - -# ifndef RTLD_BOOTSTRAP -static inline void -elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc, - void *const reloc_addr_arg) -{ - Elf32_Addr *const reloc_addr = reloc_addr_arg; - *reloc_addr = l_addr + reloc->r_addend; -} -# endif - -static inline void -elf_machine_lazy_rel (struct link_map *map, - Elf32_Addr l_addr, const Elf32_Rel *reloc) -{ - Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset); - const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); - /* Check for unexpected PLT reloc type. */ - if (__builtin_expect (r_type == R_ARM_JUMP_SLOT, 1)) - { - if (__builtin_expect (map->l_mach.plt, 0) == 0) - *reloc_addr += l_addr; - else - *reloc_addr = map->l_mach.plt; - } - else - _dl_reloc_bad_type (map, r_type, 1); -} - -#endif /* RESOLVE */ |