OSDN Git Service

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