diff options
author | Christophe Lyon <christophe.lyon@st.com> | 2013-01-18 15:08:04 +0100 |
---|---|---|
committer | Waldemar Brodkorb <wbrodkorb@conet.de> | 2018-08-10 16:01:58 +0200 |
commit | 5ec586eb37f61e57f19ac60b58af61f167ca054a (patch) | |
tree | 6c72d03d43e76a33eb5d6360d9bdb2573a048c42 /libc/sysdeps/linux/arm/bits | |
parent | f88bb681ba22d77a19abfb4c1617c826298ed473 (diff) |
rtld: Add FDPIC code for arm
Add FDPIC dynamic relocations support, similar to what other FDPIC
targets do.
Lazy binding is implemented in a folllow-up patch.
Disable the SEND* macros because they involve relocations to
access constant strings that are unsupported by the existing
arm version.
Define DL_START, START, ARCH_NEEDS_BOOTSTRAP_RELOCS,
DL_CHECK_LIB_TYPE similarly to what other FDPIC targets do.
Define raise() because _dl_find_hash references __aeabi_uidivmod,
which uses __aeabi_idiv0 which in turn references raise.
* include/elf.h (R_ARM_FUNCDESC): Define.
(R_ARM_FUNCDESC_VALUE): Define.
* ldso/include/dl-string.h (SEND_STDERR, SEND_ADDRESS_STDERR)
(SEND_NUMBER_STDERR): Define empty for __FDPIC__.
* ldso/ldso/arm/dl-inlines.h: New file.
* ldso/ldso/arm/dl-startup.h (PERFORM_BOOTSTRAP_RELOC): Fix type
of load_addr. Fix handling of R_ARM_RELATIVE, add support for
R_ARM_FUNCDESC_VALUE.
(DL_START, START): Define for __FDPIC__.
(raise): Define.
* ldso/ldso/arm/dl-sysdep.h (ARCH_NEEDS_BOOTSTRAP_RELOCS): Define.
(DL_CHECK_LIB_TYPE): Define.
(elf_machine_type_class): Take into account FDPIC related
relocations.
(elf_machine_load_address): Support __FDPIC__.
(elf_machine_relative): Likewise.
* ldso/ldso/arm/elfinterp.c (_dl_linux_resolver): Dummy support
for __FDPIC__, implemented in a later patch.
(_dl_do_reloc): Fix reloc_adr computation for __FDPIC__, fix
handling of local symbols. Fix handling of R_ARM_RELATIVE, add
support for R_ARM_FUNCDESC_VALUE, R_ARM_FUNCDESC.
* ldso/ldso/arm/resolve.S: Make _dl_linux_resolve hidden.
* ldso/ldso/fdpic/dl-inlines.h (htab_delete): Declare.
* libc/sysdeps/linux/arm/bits/elf-fdpic.h: New file, similar to bfin's.
* libc/sysdeps/linux/arm/crtreloc.c: Likewise.
* libc/sysdeps/linux/arm/find_exidx.c (__dl_addr_in_loadaddr) Define.
(find_exidx_callback): Support __FDPIC__.
Signed-off-by: Mickaël Guêné <mickael.guene@st.com>
Signed-off-by: Christophe Lyon <christophe.lyon@st.com>
Diffstat (limited to 'libc/sysdeps/linux/arm/bits')
-rw-r--r-- | libc/sysdeps/linux/arm/bits/elf-fdpic.h | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/arm/bits/elf-fdpic.h b/libc/sysdeps/linux/arm/bits/elf-fdpic.h new file mode 100644 index 000000000..3d6db54af --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/elf-fdpic.h @@ -0,0 +1,114 @@ +/* Copyright 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. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +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 +Library 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; see the file COPYING.LIB. If +not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _BITS_ELF_FDPIC_H +#define _BITS_ELF_FDPIC_H + +/* These data structures are described in the FDPIC ABI extension. + The kernel passes a process a memory map, such that for every LOAD + segment there is an elf32_fdpic_loadseg entry. A pointer to an + elf32_fdpic_loadmap is passed in r7 at start-up, and a pointer to + an additional such map is passed in r8 for the interpreter, when + there is one. */ + +#include <elf.h> + +/* This data structure represents a PT_LOAD segment. */ +struct elf32_fdpic_loadseg +{ + /* Core address to which the segment is mapped. */ + Elf32_Addr addr; + /* VMA recorded in the program header. */ + Elf32_Addr p_vaddr; + /* Size of this segment in memory. */ + Elf32_Word p_memsz; +}; + +struct elf32_fdpic_loadmap { + /* Protocol version number, must be zero. */ + Elf32_Half version; + /* Number of segments in this map. */ + Elf32_Half nsegs; + /* The actual memory map. */ + struct elf32_fdpic_loadseg segs[/*nsegs*/]; +}; + +struct elf32_fdpic_loadaddr { + struct elf32_fdpic_loadmap *map; + void *got_value; +}; + +/* Map a pointer's VMA to its corresponding address according to the + load map. */ +static __always_inline void * +__reloc_pointer (void *p, + const struct elf32_fdpic_loadmap *map) +{ + int c; + +#if 0 + if (map->version != 0) + /* Crash. */ + ((void(*)())0)(); +#endif + + /* No special provision is made for NULL. We don't want NULL + addresses to go through relocation, so they shouldn't be in + .rofixup sections, and, if they're present in dynamic + relocations, they shall be mapped to the NULL address without + undergoing relocations. */ + + for (c = 0; + /* Take advantage of the fact that the loadmap is ordered by + virtual addresses. In general there will only be 2 entries, + so it's not profitable to do a binary search. */ + c < map->nsegs && p >= (void*)map->segs[c].p_vaddr; + c++) + { + /* This should be computed as part of the pointer comparison + above, but we want to use the carry in the comparison, so we + can't convert it to an integer type beforehand. */ + unsigned long offset = p - (void*)map->segs[c].p_vaddr; + /* We only check for one-past-the-end for the last segment, + assumed to be the data segment, because other cases are + ambiguous in the absence of padding between segments, and + rofixup already serves as padding between text and data. + Unfortunately, unless we special-case the last segment, we + fail to relocate the _end symbol. */ + if (offset < map->segs[c].p_memsz + || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs)) + return (char*)map->segs[c].addr + offset; + } + + /* We might want to crash instead. */ + return (void*)-1; +} + +# define __RELOC_POINTER(ptr, loadaddr) \ + (__reloc_pointer ((void*)(ptr), \ + (loadaddr).map)) + +#endif /* _BITS_ELF_FDPIC_H */ |