]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-elf.h
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / ldso / include / dl-elf.h
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
4  *
5  * GNU Lesser General Public License version 2.1 or later.
6  */
7
8 #ifndef LINUXELF_H
9 #define LINUXELF_H
10
11 #include <dl-string.h> /* before elf.h to get ELF_USES_RELOCA right */
12 #include <elf.h>
13 #include <link.h>
14
15 /* Forward declarations for stuff defined in ld_hash.h */
16 struct dyn_elf;
17 struct elf_resolve;
18
19 #include <dl-defs.h>
20 #ifdef __LDSO_CACHE_SUPPORT__
21 extern int _dl_map_cache(void);
22 extern int _dl_unmap_cache(void);
23 #else
24 static __inline__ void _dl_map_cache(void) { }
25 static __inline__ void _dl_unmap_cache(void) { }
26 #endif
27
28
29 /* Function prototypes for non-static stuff in readelflib1.c */
30 extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
31         unsigned long rel_addr, unsigned long rel_size);
32 extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
33         unsigned long rel_addr, unsigned long rel_size);
34 extern struct elf_resolve * _dl_load_shared_library(int secure,
35         struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
36         int trace_loaded_objects);
37 extern struct elf_resolve * _dl_load_elf_shared_library(int secure,
38         struct dyn_elf **rpnt, char *libname);
39 extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
40         int trace_loaded_objects);
41 extern int _dl_linux_resolve(void);
42 extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
43 extern void _dl_protect_relro (struct elf_resolve *l);
44
45 /*
46  * Bitsize related settings for things ElfW()
47  * does not handle already
48  */
49 #if __WORDSIZE == 64
50 # define ELF_ST_BIND(val) ELF64_ST_BIND(val)
51 # define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
52 # define ELF_R_SYM(i)     ELF64_R_SYM(i)
53 # define ELF_R_TYPE(i)    ELF64_R_TYPE(i)
54 # ifndef ELF_CLASS
55 #  define ELF_CLASS ELFCLASS64
56 # endif
57 #else
58 # define ELF_ST_BIND(val) ELF32_ST_BIND(val)
59 # define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
60 # define ELF_R_SYM(i)     ELF32_R_SYM(i)
61 # define ELF_R_TYPE(i)    ELF32_R_TYPE(i)
62 # ifndef ELF_CLASS
63 #  define ELF_CLASS ELFCLASS32
64 # endif
65 #endif
66
67 /*
68  * Datatype of a relocation on this platform
69  */
70 #ifdef ELF_USES_RELOCA
71 # define ELF_RELOC      ElfW(Rela)
72 # define DT_RELOC_TABLE_ADDR    DT_RELA
73 # define DT_RELOC_TABLE_SIZE    DT_RELASZ
74 # define DT_RELOCCOUNT          DT_RELACOUNT
75 # define UNSUPPORTED_RELOC_TYPE DT_REL
76 # define UNSUPPORTED_RELOC_STR  "REL"
77 #else
78 # define ELF_RELOC      ElfW(Rel)
79 # define DT_RELOC_TABLE_ADDR    DT_REL
80 # define DT_RELOC_TABLE_SIZE    DT_RELSZ
81 # define DT_RELOCCOUNT          DT_RELCOUNT
82 # define UNSUPPORTED_RELOC_TYPE DT_RELA
83 # define UNSUPPORTED_RELOC_STR  "RELA"
84 #endif
85
86 /* OS and/or GNU dynamic extensions */
87 #ifdef __LDSO_GNU_HASH_SUPPORT__
88 # define OS_NUM 2 /* for DT_RELOCCOUNT and DT_GNU_HASH entries */
89 #else
90 # define OS_NUM 1 /* for DT_RELOCCOUNT entry */
91 #endif
92
93 #ifndef ARCH_DYNAMIC_INFO
94   /* define in arch specific code, if needed */
95 # define ARCH_NUM 0
96 #endif
97
98 #define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
99 /* Keep ARCH specific entries into dynamic section at the end of the array */
100 #define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM)
101
102 #ifdef __LDSO_GNU_HASH_SUPPORT__
103 /* GNU hash comes just after the relocation count */
104 # define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1)
105 #endif
106
107 extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
108                                            void *debug_addr, DL_LOADADDR_TYPE load_off);
109
110 static __always_inline
111 unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
112                                      void *debug_addr, DL_LOADADDR_TYPE load_off)
113 {
114         unsigned int rtld_flags = 0;
115
116         for (; dpnt->d_tag; dpnt++) {
117                 if (dpnt->d_tag < DT_NUM) {
118                         dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
119 #ifndef __mips__
120                         /* we disable for mips because normally this page is readonly
121                          * and modifying the value here needlessly dirties a page.
122                          * see this post for more info:
123                          * http://uclibc.org/lists/uclibc/2006-April/015224.html */
124                         if (dpnt->d_tag == DT_DEBUG)
125                                 dpnt->d_un.d_val = (unsigned long)debug_addr;
126 #endif
127                         if (dpnt->d_tag == DT_BIND_NOW)
128                                 dynamic_info[DT_BIND_NOW] = 1;
129                         if (dpnt->d_tag == DT_FLAGS &&
130                             (dpnt->d_un.d_val & DF_BIND_NOW))
131                                 dynamic_info[DT_BIND_NOW] = 1;
132                         if (dpnt->d_tag == DT_TEXTREL)
133                                 dynamic_info[DT_TEXTREL] = 1;
134 #ifdef __LDSO_RUNPATH__
135                         if (dpnt->d_tag == DT_RUNPATH)
136                                 dynamic_info[DT_RPATH] = 0;
137                         if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH])
138                                 dynamic_info[DT_RPATH] = 0;
139 #endif
140                 } else if (dpnt->d_tag < DT_LOPROC) {
141                         if (dpnt->d_tag == DT_RELOCCOUNT)
142                                 dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
143                         if (dpnt->d_tag == DT_FLAGS_1) {
144                                 if (dpnt->d_un.d_val & DF_1_NOW)
145                                         dynamic_info[DT_BIND_NOW] = 1;
146                                 if (dpnt->d_un.d_val & DF_1_NODELETE)
147                                         rtld_flags |= RTLD_NODELETE;
148                         }
149 #ifdef __LDSO_GNU_HASH_SUPPORT__
150                         if (dpnt->d_tag == DT_GNU_HASH)
151                                 dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr;
152 #endif
153                 }
154 #ifdef ARCH_DYNAMIC_INFO
155                 else {
156                         ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr);
157                 }
158 #endif
159         }
160 #define ADJUST_DYN_INFO(tag, load_off) \
161         do { \
162                 if (dynamic_info[tag]) \
163                         dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \
164         } while (0)
165         /* Don't adjust .dynamic unnecessarily.  For FDPIC targets,
166            we'd have to walk all the loadsegs to find out if it was
167            actually unnecessary, so skip this optimization.  */
168 #if !defined __FDPIC__ && !defined __DSBT__
169         if (load_off != 0)
170 #endif
171         {
172                 ADJUST_DYN_INFO(DT_HASH, load_off);
173                 ADJUST_DYN_INFO(DT_PLTGOT, load_off);
174                 ADJUST_DYN_INFO(DT_STRTAB, load_off);
175                 ADJUST_DYN_INFO(DT_SYMTAB, load_off);
176                 ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off);
177                 ADJUST_DYN_INFO(DT_JMPREL, load_off);
178 #ifdef __LDSO_GNU_HASH_SUPPORT__
179                 ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off);
180 #endif
181         }
182 #ifdef __DSBT__
183         /* Get the mapped address of the DSBT base.  */
184         ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
185
186         /* Initialize loadmap dsbt info.  */
187         load_off.map->dsbt_table = dynamic_info[DT_DSBT_BASE_IDX];
188         load_off.map->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX];
189         load_off.map->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX];
190 #endif
191 #undef ADJUST_DYN_INFO
192         return rtld_flags;
193 }
194
195 /* Reloc type classes as returned by elf_machine_type_class().
196    ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
197    some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
198    satisfied by any symbol in the executable.  Some architectures do
199    not support copy relocations.  In this case we define the macro to
200    zero so that the code for handling them gets automatically optimized
201    out.  */
202 #ifdef DL_NO_COPY_RELOCS
203 # define ELF_RTYPE_CLASS_COPY   (0x0)
204 #else
205 # define ELF_RTYPE_CLASS_COPY   (0x2)
206 #endif
207 #define ELF_RTYPE_CLASS_PLT     (0x1)
208
209 /* dlsym() calls _dl_find_hash with this value, that enables
210    DL_FIND_HASH_VALUE to return something different than the symbol
211    itself, e.g., a function descriptor.  */
212 #define ELF_RTYPE_CLASS_DLSYM 0x80000000
213
214
215 /* Convert between the Linux flags for page protections and the
216    ones specified in the ELF standard. */
217 #define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \
218                     (((X) & PF_W) ? PROT_WRITE : 0) | \
219                     (((X) & PF_X) ? PROT_EXEC : 0))
220
221
222 #endif  /* LINUXELF_H */