OSDN Git Service

38ed51300351256a86a71cb9e0dc8f63990c3ef9
[uclinux-h8/uClibc.git] / ldso / ldso / bfin / dl-sysdep.h
1      /* Copyright (C) 2003, 2004 Red Hat, Inc.
2         Contributed by Alexandre Oliva <aoliva@redhat.com>
3         Based on ../i386/dl-sysdep.h
4
5 This file is part of uClibc.
6
7 uClibc is free software; you can redistribute it and/or modify it
8 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 uClibc is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with uClibc; see the file COPYING.LIB.  If not, write to
19 the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
20 USA.  */
21
22 /*
23  * Various assembly language/system dependent  hacks that are required
24  * so that we can minimize the amount of platform specific code.
25  */
26
27 /*
28  * Define this if the system uses RELOCA.
29  */
30 #undef ELF_USES_RELOCA
31
32 /* JMPREL relocs are inside the DT_RELA table.  */
33 #define ELF_MACHINE_PLTREL_OVERLAP
34
35 #define DL_NO_COPY_RELOCS
36
37 #define HAVE_DL_INLINES_H
38
39 /*
40  * Initialization sequence for a GOT.  Copy the resolver function
41  * descriptor and the pointer to the elf_resolve/link_map data
42  * structure.  Initialize the got_value in the module while at that.
43  */
44 #define INIT_GOT(GOT_BASE,MODULE) \
45 {                               \
46   (MODULE)->loadaddr.got_value = (GOT_BASE); \
47   GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \
48   GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \
49   GOT_BASE[2] = (unsigned long) MODULE; \
50 }
51
52 /* Here we define the magic numbers that this dynamic loader should accept */
53 #define MAGIC1 EM_BLACKFIN
54 #undef  MAGIC2
55
56 /* Used for error messages */
57 #define ELF_TARGET "BFIN"
58
59 struct elf_resolve;
60
61 struct funcdesc_value
62 {
63   void *entry_point;
64   void *got_value;
65 } __attribute__((__aligned__(8)));
66
67
68 extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
69
70 /* 4KiB page alignment.  Should perhaps be made dynamic using
71    getpagesize(), based on AT_PAGESZ from auxvt?  */
72 #define PAGE_ALIGN 0xfffff000
73 #define ADDR_ALIGN 0xfff
74 #define OFFS_ALIGN 0x7ffff000
75
76 struct funcdesc_ht;
77
78 #undef SEND_EARLY_STDERR
79 #define SEND_EARLY_STDERR(S)                    \
80     do {                                                                \
81         static const char __attribute__((section(".text"))) __s[] = (S); \
82       const char *__p, *__scratch;                                      \
83       asm ("call 1f;\n1:\n\t"                                           \
84            "%1 = RETS;\n\t"                                             \
85            "%0 = [%3 + 1b@GOT17M4];\n\t"                                \
86            "%1 = %1 - %0;\n\t"                                          \
87            "%1 = %1 + %2;\n\t"                                          \
88            : "=&d" (__scratch), "=&d" (__p)                             \
89            : "d" (__s), "a" (dl_boot_got_pointer) : "RETS");                            \
90       SEND_STDERR (__p);                                                \
91       { int __t;                                                        \
92           for (__t = 0; __t < 0x1000000; __t++) asm volatile ("");      } \
93   } while (0)
94
95 #define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr
96
97 #define DL_RELOC_ADDR(LOADADDR, ADDR) \
98     ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
99
100 #define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) \
101   ((void(*)(void)) _dl_funcdesc_for ((void*)(ADDR), (LOADADDR).got_value))
102
103 #define _dl_stabilize_funcdesc(val) \
104   ({ asm ("" : "+m" (*(val))); (val); })
105
106 #define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \
107   ({ struct funcdesc_value fd = { (void*)(ADDR), (LOADADDR).got_value }; \
108      void (*pf)(void) = (void*) _dl_stabilize_funcdesc (&fd); \
109      (* SIGNATURE pf)(__VA_ARGS__); })
110
111 #define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
112   (__dl_init_loadaddr_map (&(LOADADDR), dl_boot_got_pointer, \
113                            dl_boot_ldsomap ?: dl_boot_progmap))
114
115 #define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
116   (__dl_init_loadaddr_map (&(LOADADDR), 0, dl_boot_progmap))
117
118 #define DL_INIT_LOADADDR_EXTRA_DECLS \
119   int dl_init_loadaddr_load_count;
120 #define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
121   (dl_init_loadaddr_load_count = \
122      __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT)))
123 #define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
124   (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
125                            dl_init_loadaddr_load_count))
126 #define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
127   (__dl_loadaddr_unmap ((LOADADDR), (NULL)))
128 #define DL_LIB_UNMAP(LIB, LEN) \
129   (__dl_loadaddr_unmap ((LIB)->loadaddr, (LIB)->funcdesc_ht))
130 #define DL_LOADADDR_BASE(LOADADDR) \
131   ((LOADADDR).got_value)
132
133 /* This is called from dladdr(), such that we map a function
134    descriptor's address to the function's entry point before trying to
135    find in which library it's defined.  */
136 #define DL_LOOKUP_ADDRESS(ADDRESS) (_dl_lookup_address (ADDRESS))
137
138 #define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
139   (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr))
140
141 /*
142  * Compute the GOT address.  On several platforms, we use assembly
143  * here.  on FR-V FDPIC, there's no way to compute the GOT address,
144  * since the offset between text and data is not fixed, so we arrange
145  * for the assembly _dl_boot to pass this value as an argument to
146  * _dl_boot.  */
147 #define DL_BOOT_COMPUTE_GOT(got) ((got) = dl_boot_got_pointer)
148
149 #define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
150   ((dpnt) = dl_boot_ldso_dyn_pointer)
151
152 /* We only support loading FDPIC independently-relocatable shared
153    libraries.  It probably wouldn't be too hard to support loading
154    shared libraries that require relocation by the same amount, but we
155    don't know that they exist or would be useful, and the dynamic
156    loader code could leak the whole-library map unless we keeping a
157    bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's
158    keep things simple for now.  */
159 #define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
160 do \
161 { \
162   if (((epnt)->e_flags & EF_BFIN_FDPIC) && ! ((epnt)->e_flags & EF_BFIN_PIC)) \
163     (piclib) = 2; \
164   else \
165     { \
166       _dl_internal_error_number = LD_ERROR_NOTDYN; \
167       _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \
168                   "\n", (_dl_progname), (libname)); \
169       _dl_close(infile); \
170       return NULL; \
171     } \
172 \
173 } \
174 while (0)  
175
176 /* We want want to apply all relocations in the interpreter during
177    bootstrap.  Because of this, we have to skip the interpreter
178    relocations in _dl_parse_relocation_information(), see
179    elfinterp.c.  */
180 #define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0
181
182 #ifdef __NR_pread
183 #define _DL_PREAD(FD, BUF, SIZE, OFFSET) \
184   (_dl_pread((FD), (BUF), (SIZE), (OFFSET)))
185 #endif
186
187 /* We want to return to dlsym() a function descriptor if the symbol
188    turns out to be a function.  */
189 #define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \
190   (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \
191    && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \
192    ? _dl_funcdesc_for ((void *)DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value), \
193                        (TPNT)->loadaddr.got_value)                           \
194    : DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value))
195
196 #define DL_IS_SPECIAL_SEGMENT(EPNT, PPNT) \
197   __dl_is_special_segment(EPNT, PPNT)
198 #define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) \
199   __dl_map_segment (EPNT, PPNT, INFILE, FLAGS)
200
201 #define DL_GET_READY_TO_RUN_EXTRA_PARMS \
202     , struct elf32_fdpic_loadmap *dl_boot_progmap, Elf32_Addr dl_boot_got_pointer
203 #define DL_GET_READY_TO_RUN_EXTRA_ARGS \
204     , dl_boot_progmap, dl_boot_got_pointer
205
206
207 #ifdef __USE_GNU
208 # include <link.h>
209 #else
210 # define __USE_GNU
211 # include <link.h>
212 # undef __USE_GNU
213 #endif
214
215 #include <elf.h>
216 static inline void
217 elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
218                       Elf32_Word relative_count)
219 {
220 #if 0
221          Elf32_Rel * rpnt = (void *) rel_addr;
222         --rpnt;
223         do {
224                 Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
225
226                 *reloc_addr = DL_RELOC_ADDR (load_off, *reloc_addr);
227         } while (--relative_count);
228 #endif
229 }