time.h: Add CLOCK_TAI
[uclibc-ng.git] / ldso / include / dl-elf.h
blob2b99958d95cda305673bc955b4294dfbda7bca4e
1 /*
2 * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
4 * GNU Lesser General Public License version 2.1 or later.
5 */
7 #ifndef _DL_ELF_H
8 #define _DL_ELF_H
10 #include <features.h>
11 #include <bits/wordsize.h>
12 #include <dl-string.h> /* before elf.h to get ELF_USES_RELOCA right */
13 #include <elf.h>
14 #include <link.h>
15 #include <dl-defs.h>
16 #include <dlfcn.h>
18 /* Forward declarations for stuff defined in dl-hash.h */
19 struct dyn_elf;
20 struct elf_resolve;
21 struct r_scope_elem;
23 #ifdef __LDSO_CACHE_SUPPORT__
24 extern int _dl_map_cache(void);
25 extern int _dl_unmap_cache(void);
26 #else
27 static __inline__ void _dl_map_cache(void) { }
28 static __inline__ void _dl_unmap_cache(void) { }
29 #endif
31 /* Function prototypes for non-static stuff in elfinterp.c */
32 extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
33 unsigned long rel_addr, unsigned long rel_size);
34 extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
35 struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size);
36 extern struct elf_resolve * _dl_load_shared_library(unsigned int rflags,
37 struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
38 int trace_loaded_objects);
39 extern struct elf_resolve * _dl_load_elf_shared_library(unsigned int rflags,
40 struct dyn_elf **rpnt, const char *libname);
41 extern int _dl_linux_resolve(void);
42 extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int flag);
43 extern void _dl_protect_relro (struct elf_resolve *l);
46 * Bitsize related settings for things ElfW()
47 * does not handle already
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
68 * Datatype of a relocation on this platform
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
86 /* OS and/or GNU dynamic extensions */
88 #define OS_NUM_BASE 1 /* for DT_RELOCCOUNT */
90 #ifdef __LDSO_GNU_HASH_SUPPORT__
91 # define OS_NUM_GNU_HASH 1 /* for DT_GNU_HASH entry */
92 #else
93 # define OS_NUM_GNU_HASH 0
94 #endif
96 #ifdef __LDSO_PRELINK_SUPPORT__
97 # define OS_NUM_PRELINK 6 /* for DT_GNU_PRELINKED entry */
98 #else
99 # define OS_NUM_PRELINK 0
100 #endif
102 #define OS_NUM (OS_NUM_BASE + OS_NUM_GNU_HASH + OS_NUM_PRELINK)
104 #ifndef ARCH_DYNAMIC_INFO
105 /* define in arch specific code, if needed */
106 # define ARCH_NUM 0
107 #endif
109 #define DYNAMIC_SIZE (DT_NUM + OS_NUM + ARCH_NUM)
110 /* Keep ARCH specific entries into dynamic section at the end of the array */
111 #define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM)
113 #ifdef __LDSO_GNU_HASH_SUPPORT__
114 /* GNU hash comes just after the relocation count */
115 # define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1)
116 #else
117 # define DT_GNU_HASH_IDX DT_RELCONT_IDX
118 #endif
120 #ifdef __LDSO_PRELINK_SUPPORT__
121 /* GNU prelink comes just after the GNU hash if present */
122 #define DT_GNU_PRELINKED_IDX (DT_GNU_HASH_IDX + 1)
123 #define DT_GNU_CONFLICT_IDX (DT_GNU_HASH_IDX + 2)
124 #define DT_GNU_CONFLICTSZ_IDX (DT_GNU_HASH_IDX + 3)
125 #define DT_GNU_LIBLIST_IDX (DT_GNU_HASH_IDX + 4)
126 #define DT_GNU_LIBLISTSZ_IDX (DT_GNU_HASH_IDX + 5)
127 #define DT_CHECKSUM_IDX (DT_GNU_HASH_IDX + 6)
128 #endif
130 extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
131 void *debug_addr, DL_LOADADDR_TYPE load_off);
133 static __always_inline
134 unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
135 void *debug_addr, DL_LOADADDR_TYPE load_off)
137 unsigned int rtld_flags = 0;
139 for (; dpnt->d_tag; dpnt++) {
140 if (dpnt->d_tag < DT_NUM) {
141 dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
142 #ifndef __mips__
143 /* we disable for mips because normally this page is readonly
144 * and modifying the value here needlessly dirties a page.
145 * see this post for more info:
146 * http://uclibc.org/lists/uclibc/2006-April/015224.html */
147 if (dpnt->d_tag == DT_DEBUG)
148 dpnt->d_un.d_val = (unsigned long)debug_addr;
149 #endif
150 if (dpnt->d_tag == DT_BIND_NOW)
151 dynamic_info[DT_BIND_NOW] = 1;
152 if (dpnt->d_tag == DT_FLAGS &&
153 (dpnt->d_un.d_val & DF_BIND_NOW))
154 dynamic_info[DT_BIND_NOW] = 1;
155 if (dpnt->d_tag == DT_TEXTREL)
156 dynamic_info[DT_TEXTREL] = 1;
157 #ifdef __LDSO_RUNPATH__
158 if (dpnt->d_tag == DT_RUNPATH)
159 dynamic_info[DT_RPATH] = 0;
160 if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH])
161 dynamic_info[DT_RPATH] = 0;
162 #endif
163 } else if (dpnt->d_tag < DT_LOPROC) {
164 if (dpnt->d_tag == DT_RELOCCOUNT)
165 dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
166 if (dpnt->d_tag == DT_FLAGS_1) {
167 if (dpnt->d_un.d_val & DF_1_NOW)
168 dynamic_info[DT_BIND_NOW] = 1;
169 if (dpnt->d_un.d_val & DF_1_NODELETE)
170 rtld_flags |= RTLD_NODELETE;
172 #ifdef __LDSO_GNU_HASH_SUPPORT__
173 if (dpnt->d_tag == DT_GNU_HASH)
174 dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr;
175 #endif
176 #ifdef __LDSO_PRELINK_SUPPORT__
177 if (dpnt->d_tag == DT_GNU_PRELINKED)
178 dynamic_info[DT_GNU_PRELINKED_IDX] = dpnt->d_un.d_val;
179 if (dpnt->d_tag == DT_GNU_CONFLICT)
180 dynamic_info[DT_GNU_CONFLICT_IDX] = dpnt->d_un.d_ptr;
181 if (dpnt->d_tag == DT_GNU_CONFLICTSZ)
182 dynamic_info[DT_GNU_CONFLICTSZ_IDX] = dpnt->d_un.d_val;
183 if (dpnt->d_tag == DT_GNU_LIBLIST)
184 dynamic_info[DT_GNU_LIBLIST_IDX] = dpnt->d_un.d_ptr;
185 if (dpnt->d_tag == DT_GNU_LIBLISTSZ)
186 dynamic_info[DT_GNU_LIBLISTSZ_IDX] = dpnt->d_un.d_val;
187 if (dpnt->d_tag == DT_CHECKSUM)
188 dynamic_info[DT_CHECKSUM_IDX] = dpnt->d_un.d_val;
189 #endif
191 #ifdef ARCH_DYNAMIC_INFO
192 else {
193 ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr);
195 #endif
197 #define ADJUST_DYN_INFO(tag, load_off) \
198 do { \
199 if (dynamic_info[tag]) \
200 dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \
201 } while (0)
202 /* Don't adjust .dynamic unnecessarily. For FDPIC targets,
203 we'd have to walk all the loadsegs to find out if it was
204 actually unnecessary, so skip this optimization. */
205 #if !defined __FRV_FDPIC__ && !defined __BFIN_FDPIC__ && !defined __DSBT__ && !defined __FDPIC__
206 if (load_off != 0)
207 #endif
209 ADJUST_DYN_INFO(DT_HASH, load_off);
210 ADJUST_DYN_INFO(DT_PLTGOT, load_off);
211 ADJUST_DYN_INFO(DT_STRTAB, load_off);
212 ADJUST_DYN_INFO(DT_SYMTAB, load_off);
213 ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off);
214 ADJUST_DYN_INFO(DT_JMPREL, load_off);
215 #ifdef __LDSO_GNU_HASH_SUPPORT__
216 ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off);
217 #endif
219 #ifdef __DSBT__
220 /* Get the mapped address of the DSBT base. */
221 ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
222 #endif
223 #undef ADJUST_DYN_INFO
224 return rtld_flags;
227 /* Reloc type classes as returned by elf_machine_type_class().
228 ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
229 some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
230 satisfied by any symbol in the executable. Some architectures do
231 not support copy relocations. In this case we define the macro to
232 zero so that the code for handling them gets automatically optimized
233 out. */
234 #ifdef DL_NO_COPY_RELOCS
235 # define ELF_RTYPE_CLASS_COPY (0x0)
236 #else
237 # define ELF_RTYPE_CLASS_COPY (0x2)
238 #endif
239 #define ELF_RTYPE_CLASS_PLT (0x1)
241 /* dlsym() calls _dl_find_hash with this value, that enables
242 DL_FIND_HASH_VALUE to return something different than the symbol
243 itself, e.g., a function descriptor. */
244 #define ELF_RTYPE_CLASS_DLSYM 0x80000000
247 /* Convert between the Linux flags for page protections and the
248 ones specified in the ELF standard. */
249 #define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \
250 (((X) & PF_W) ? PROT_WRITE : 0) | \
251 (((X) & PF_X) ? PROT_EXEC : 0))
254 #endif /* _DL_ELF_H */