]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/elf-fdpic.h
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / libc / sysdeps / linux / bfin / bits / elf-fdpic.h
1 /* Copyright 2003, 2004 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file.  (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 The GNU C Library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 Library General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with the GNU C Library; see the file COPYING.LIB.  If
25 not, see <http://www.gnu.org/licenses/>.  */
26
27 #ifndef _BITS_ELF_FDPIC_H
28 #define _BITS_ELF_FDPIC_H
29
30 /* These data structures are described in the FDPIC ABI extension.
31    The kernel passes a process a memory map, such that for every LOAD
32    segment there is an elf32_fdpic_loadseg entry.  A pointer to an
33    elf32_fdpic_loadmap is passed in GR8 at start-up, and a pointer to
34    an additional such map is passed in GR9 for the interpreter, when
35    there is one.  */
36
37 #include <elf.h>
38
39 /* This data structure represents a PT_LOAD segment.  */
40 struct elf32_fdpic_loadseg
41 {
42   /* Core address to which the segment is mapped.  */
43   Elf32_Addr addr;
44   /* VMA recorded in the program header.  */
45   Elf32_Addr p_vaddr;
46   /* Size of this segment in memory.  */
47   Elf32_Word p_memsz;
48 };
49
50 struct elf32_fdpic_loadmap {
51   /* Protocol version number, must be zero.  */
52   Elf32_Half version;
53   /* Number of segments in this map.  */
54   Elf32_Half nsegs;
55   /* The actual memory map.  */
56   struct elf32_fdpic_loadseg segs[/*nsegs*/];
57 };
58
59 struct elf32_fdpic_loadaddr {
60   struct elf32_fdpic_loadmap *map;
61   void *got_value;
62 };
63
64 /* Map a pointer's VMA to its corresponding address according to the
65    load map.  */
66 static __always_inline void *
67 __reloc_pointer (void *p,
68                  const struct elf32_fdpic_loadmap *map)
69 {
70   int c;
71
72 #if 0
73   if (map->version != 0)
74     /* Crash.  */
75     ((void(*)())0)();
76 #endif
77
78   /* No special provision is made for NULL.  We don't want NULL
79      addresses to go through relocation, so they shouldn't be in
80      .rofixup sections, and, if they're present in dynamic
81      relocations, they shall be mapped to the NULL address without
82      undergoing relocations.  */
83
84   for (c = 0;
85        /* Take advantage of the fact that the loadmap is ordered by
86           virtual addresses.  In general there will only be 2 entries,
87           so it's not profitable to do a binary search.  */
88        c < map->nsegs && p >= (void*)map->segs[c].p_vaddr;
89        c++)
90     {
91       /* This should be computed as part of the pointer comparison
92          above, but we want to use the carry in the comparison, so we
93          can't convert it to an integer type beforehand.  */
94       unsigned long offset = p - (void*)map->segs[c].p_vaddr;
95       /* We only check for one-past-the-end for the last segment,
96          assumed to be the data segment, because other cases are
97          ambiguous in the absence of padding between segments, and
98          rofixup already serves as padding between text and data.
99          Unfortunately, unless we special-case the last segment, we
100          fail to relocate the _end symbol.  */
101       if (offset < map->segs[c].p_memsz
102           || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs))
103         return (char*)map->segs[c].addr + offset;
104     }
105
106   /* We might want to crash instead.  */
107   return (void*)-1;
108 }
109
110 # define __RELOC_POINTER(ptr, loadaddr) \
111   (__reloc_pointer ((void*)(ptr), \
112                     (loadaddr).map))
113
114 #endif /* _BITS_ELF_FDPIC_H */