1 /* vi: set sw=4 ts=4: */
3 * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
5 * GNU Lesser General Public License version 2.1 or later.
11 #include <dl-string.h> /* before elf.h to get ELF_USES_RELOCA right */
15 /* Forward declarations for stuff defined in ld_hash.h */
20 #ifdef __LDSO_CACHE_SUPPORT__
21 extern int _dl_map_cache(void);
22 extern int _dl_unmap_cache(void);
24 static __inline__ void _dl_map_cache(void) { }
25 static __inline__ void _dl_unmap_cache(void) { }
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);
46 * Bitsize related settings for things ElfW()
47 * does not handle already
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)
55 # define ELF_CLASS ELFCLASS64
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)
63 # define ELF_CLASS ELFCLASS32
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"
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"
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 */
90 # define OS_NUM 1 /* for DT_RELOCCOUNT entry */
93 #ifndef ARCH_DYNAMIC_INFO
94 /* define in arch specific code, if needed */
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)
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)
107 extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
108 void *debug_addr, DL_LOADADDR_TYPE load_off);
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)
114 unsigned int rtld_flags = 0;
116 for (; dpnt->d_tag; dpnt++) {
117 if (dpnt->d_tag < DT_NUM) {
118 dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
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;
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;
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;
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;
154 #ifdef ARCH_DYNAMIC_INFO
156 ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr);
160 #define ADJUST_DYN_INFO(tag, load_off) \
162 if (dynamic_info[tag]) \
163 dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \
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__
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);
183 /* Get the mapped address of the DSBT base. */
184 ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
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];
191 #undef ADJUST_DYN_INFO
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
202 #ifdef DL_NO_COPY_RELOCS
203 # define ELF_RTYPE_CLASS_COPY (0x0)
205 # define ELF_RTYPE_CLASS_COPY (0x2)
207 #define ELF_RTYPE_CLASS_PLT (0x1)
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
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))
222 #endif /* LINUXELF_H */