| @@ -1,453 +1,457 @@ | | | @@ -1,453 +1,457 @@ |
1 | /* $NetBSD: rtld.h,v 1.106 2011/06/25 05:45:12 nonaka Exp $ */ | | 1 | /* $NetBSD: rtld.h,v 1.107 2011/12/02 09:06:49 skrll Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright 1996 John D. Polstra. | | 4 | * Copyright 1996 John D. Polstra. |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. All advertising materials mentioning features or use of this software | | 16 | * 3. All advertising materials mentioning features or use of this software |
17 | * must display the following acknowledgement: | | 17 | * must display the following acknowledgement: |
18 | * This product includes software developed by John Polstra. | | 18 | * This product includes software developed by John Polstra. |
19 | * 4. The name of the author may not be used to endorse or promote products | | 19 | * 4. The name of the author may not be used to endorse or promote products |
20 | * derived from this software without specific prior written permission. | | 20 | * derived from this software without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #ifndef RTLD_H | | 34 | #ifndef RTLD_H |
35 | #define RTLD_H | | 35 | #define RTLD_H |
36 | | | 36 | |
37 | #include <dlfcn.h> | | 37 | #include <dlfcn.h> |
38 | #include <signal.h> | | 38 | #include <signal.h> |
39 | #include <stdbool.h> | | 39 | #include <stdbool.h> |
40 | #include <stddef.h> | | 40 | #include <stddef.h> |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/types.h> | | 42 | #include <sys/types.h> |
43 | #include <sys/queue.h> | | 43 | #include <sys/queue.h> |
44 | #include <sys/exec_elf.h> | | 44 | #include <sys/exec_elf.h> |
45 | #include <sys/tls.h> | | 45 | #include <sys/tls.h> |
46 | #include "rtldenv.h" | | 46 | #include "rtldenv.h" |
47 | #include "link.h" | | 47 | #include "link.h" |
48 | | | 48 | |
49 | #if defined(_RTLD_SOURCE) | | 49 | #if defined(_RTLD_SOURCE) |
50 | | | 50 | |
51 | #ifndef RTLD_DEFAULT_LIBRARY_PATH | | 51 | #ifndef RTLD_DEFAULT_LIBRARY_PATH |
52 | #define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib" | | 52 | #define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib" |
53 | #endif | | 53 | #endif |
54 | #define _PATH_LD_HINTS "/etc/ld.so.conf" | | 54 | #define _PATH_LD_HINTS "/etc/ld.so.conf" |
55 | | | 55 | |
56 | extern size_t _rtld_pagesz; | | 56 | extern size_t _rtld_pagesz; |
57 | | | 57 | |
58 | #define round_down(x) ((x) & ~(_rtld_pagesz - 1)) | | 58 | #define round_down(x) ((x) & ~(_rtld_pagesz - 1)) |
59 | #define round_up(x) round_down((x) + _rtld_pagesz - 1) | | 59 | #define round_up(x) round_down((x) + _rtld_pagesz - 1) |
60 | | | 60 | |
61 | #define NEW(type) ((type *) xmalloc(sizeof(type))) | | 61 | #define NEW(type) ((type *) xmalloc(sizeof(type))) |
62 | #define CNEW(type) ((type *) xcalloc(sizeof(type))) | | 62 | #define CNEW(type) ((type *) xcalloc(sizeof(type))) |
63 | | | 63 | |
64 | /* | | 64 | /* |
65 | * Fill in a DoneList with an allocation large enough to hold all of | | 65 | * Fill in a DoneList with an allocation large enough to hold all of |
66 | * the currently-loaded objects. Keep this in a macro since it calls | | 66 | * the currently-loaded objects. Keep this in a macro since it calls |
67 | * alloca and we want that to occur within the scope of the caller. | | 67 | * alloca and we want that to occur within the scope of the caller. |
68 | */ | | 68 | */ |
69 | #define _rtld_donelist_init(dlp) \ | | 69 | #define _rtld_donelist_init(dlp) \ |
70 | ((dlp)->num_alloc = _rtld_objcount, \ | | 70 | ((dlp)->num_alloc = _rtld_objcount, \ |
71 | (dlp)->objs = alloca((dlp)->num_alloc * sizeof((dlp)->objs[0])), \ | | 71 | (dlp)->objs = alloca((dlp)->num_alloc * sizeof((dlp)->objs[0])), \ |
72 | assert((dlp)->objs != NULL), \ | | 72 | assert((dlp)->objs != NULL), \ |
73 | (dlp)->num_used = 0) | | 73 | (dlp)->num_used = 0) |
74 | | | 74 | |
75 | #endif /* _RTLD_SOURCE */ | | 75 | #endif /* _RTLD_SOURCE */ |
76 | | | 76 | |
77 | /* | | 77 | /* |
78 | * C++ has mandated the use of the following keywords for its new boolean | | 78 | * C++ has mandated the use of the following keywords for its new boolean |
79 | * type. We might as well follow their lead. | | 79 | * type. We might as well follow their lead. |
80 | */ | | 80 | */ |
81 | struct Struct_Obj_Entry; | | 81 | struct Struct_Obj_Entry; |
82 | | | 82 | |
83 | typedef struct Struct_Objlist_Entry { | | 83 | typedef struct Struct_Objlist_Entry { |
84 | SIMPLEQ_ENTRY(Struct_Objlist_Entry) link; | | 84 | SIMPLEQ_ENTRY(Struct_Objlist_Entry) link; |
85 | struct Struct_Obj_Entry *obj; | | 85 | struct Struct_Obj_Entry *obj; |
86 | } Objlist_Entry; | | 86 | } Objlist_Entry; |
87 | | | 87 | |
88 | typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; | | 88 | typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; |
89 | | | 89 | |
90 | typedef struct Struct_Name_Entry { | | 90 | typedef struct Struct_Name_Entry { |
91 | STAILQ_ENTRY(Struct_Name_Entry) link; | | 91 | STAILQ_ENTRY(Struct_Name_Entry) link; |
92 | char name[1]; | | 92 | char name[1]; |
93 | } Name_Entry; | | 93 | } Name_Entry; |
94 | | | 94 | |
95 | typedef struct Struct_Needed_Entry { | | 95 | typedef struct Struct_Needed_Entry { |
96 | struct Struct_Needed_Entry *next; | | 96 | struct Struct_Needed_Entry *next; |
97 | struct Struct_Obj_Entry *obj; | | 97 | struct Struct_Obj_Entry *obj; |
98 | unsigned long name; /* Offset of name in string table */ | | 98 | unsigned long name; /* Offset of name in string table */ |
99 | } Needed_Entry; | | 99 | } Needed_Entry; |
100 | | | 100 | |
101 | typedef struct _rtld_search_path_t { | | 101 | typedef struct _rtld_search_path_t { |
102 | struct _rtld_search_path_t *sp_next; | | 102 | struct _rtld_search_path_t *sp_next; |
103 | const char *sp_path; | | 103 | const char *sp_path; |
104 | size_t sp_pathlen; | | 104 | size_t sp_pathlen; |
105 | } Search_Path; | | 105 | } Search_Path; |
106 | | | 106 | |
107 | typedef struct Struct_Ver_Entry { | | 107 | typedef struct Struct_Ver_Entry { |
108 | Elf_Word hash; | | 108 | Elf_Word hash; |
109 | u_int flags; | | 109 | u_int flags; |
110 | const char *name; | | 110 | const char *name; |
111 | const char *file; | | 111 | const char *file; |
112 | } Ver_Entry; | | 112 | } Ver_Entry; |
113 | | | 113 | |
114 | /* Ver_Entry.flags */ | | 114 | /* Ver_Entry.flags */ |
115 | #define VER_INFO_HIDDEN 0x01 | | 115 | #define VER_INFO_HIDDEN 0x01 |
116 | | | 116 | |
117 | | | 117 | |
118 | #define RTLD_MAX_ENTRY 10 | | 118 | #define RTLD_MAX_ENTRY 10 |
119 | #define RTLD_MAX_LIBRARY 4 | | 119 | #define RTLD_MAX_LIBRARY 4 |
120 | #define RTLD_MAX_CTL 2 | | 120 | #define RTLD_MAX_CTL 2 |
121 | typedef struct _rtld_library_xform_t { | | 121 | typedef struct _rtld_library_xform_t { |
122 | struct _rtld_library_xform_t *next; | | 122 | struct _rtld_library_xform_t *next; |
123 | char *name; | | 123 | char *name; |
124 | const char *ctlname; | | 124 | const char *ctlname; |
125 | struct { | | 125 | struct { |
126 | char *value; | | 126 | char *value; |
127 | char *library[RTLD_MAX_LIBRARY]; | | 127 | char *library[RTLD_MAX_LIBRARY]; |
128 | } entry[RTLD_MAX_ENTRY]; | | 128 | } entry[RTLD_MAX_ENTRY]; |
129 | } Library_Xform; | | 129 | } Library_Xform; |
130 | | | 130 | |
131 | /* | | 131 | /* |
132 | * Shared object descriptor. | | 132 | * Shared object descriptor. |
133 | * | | 133 | * |
134 | * Items marked with "(%)" are dynamically allocated, and must be freed | | 134 | * Items marked with "(%)" are dynamically allocated, and must be freed |
135 | * when the structure is destroyed. | | 135 | * when the structure is destroyed. |
136 | * | | 136 | * |
137 | * The layout of this structure needs to be preserved because pre-2.0 binaries | | 137 | * The layout of this structure needs to be preserved because pre-2.0 binaries |
138 | * hard-coded the location of dlopen() and friends. | | 138 | * hard-coded the location of dlopen() and friends. |
139 | */ | | 139 | */ |
140 | | | 140 | |
141 | #define RTLD_MAGIC 0xd550b87a | | 141 | #define RTLD_MAGIC 0xd550b87a |
142 | #define RTLD_VERSION 1 | | 142 | #define RTLD_VERSION 1 |
143 | | | 143 | |
144 | typedef struct Struct_Obj_Entry { | | 144 | typedef struct Struct_Obj_Entry { |
145 | Elf32_Word magic; /* Magic number (sanity check) */ | | 145 | Elf32_Word magic; /* Magic number (sanity check) */ |
146 | Elf32_Word version; /* Version number of struct format */ | | 146 | Elf32_Word version; /* Version number of struct format */ |
147 | | | 147 | |
148 | struct Struct_Obj_Entry *next; | | 148 | struct Struct_Obj_Entry *next; |
149 | char *path; /* Pathname of underlying file (%) */ | | 149 | char *path; /* Pathname of underlying file (%) */ |
150 | int refcount; | | 150 | int refcount; |
151 | int dl_refcount; /* Number of times loaded by dlopen */ | | 151 | int dl_refcount; /* Number of times loaded by dlopen */ |
152 | | | 152 | |
153 | /* These items are computed by map_object() or by digest_phdr(). */ | | 153 | /* These items are computed by map_object() or by digest_phdr(). */ |
154 | caddr_t mapbase; /* Base address of mapped region */ | | 154 | caddr_t mapbase; /* Base address of mapped region */ |
155 | size_t mapsize; /* Size of mapped region in bytes */ | | 155 | size_t mapsize; /* Size of mapped region in bytes */ |
156 | size_t textsize; /* Size of text segment in bytes */ | | 156 | size_t textsize; /* Size of text segment in bytes */ |
157 | Elf_Addr vaddrbase; /* Base address in shared object file */ | | 157 | Elf_Addr vaddrbase; /* Base address in shared object file */ |
158 | caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */ | | 158 | caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */ |
159 | Elf_Dyn *dynamic; /* Dynamic section */ | | 159 | Elf_Dyn *dynamic; /* Dynamic section */ |
160 | caddr_t entry; /* Entry point */ | | 160 | caddr_t entry; /* Entry point */ |
161 | const Elf_Phdr *phdr; /* Program header (may be xmalloc'ed) */ | | 161 | const Elf_Phdr *phdr; /* Program header (may be xmalloc'ed) */ |
162 | size_t phsize; /* Size of program header in bytes */ | | 162 | size_t phsize; /* Size of program header in bytes */ |
163 | | | 163 | |
164 | /* Items from the dynamic section. */ | | 164 | /* Items from the dynamic section. */ |
165 | Elf_Addr *pltgot; /* PLTGOT table */ | | 165 | Elf_Addr *pltgot; /* PLTGOT table */ |
166 | const Elf_Rel *rel; /* Relocation entries */ | | 166 | const Elf_Rel *rel; /* Relocation entries */ |
167 | const Elf_Rel *rellim; /* Limit of Relocation entries */ | | 167 | const Elf_Rel *rellim; /* Limit of Relocation entries */ |
168 | const Elf_Rela *rela; /* Relocation entries */ | | 168 | const Elf_Rela *rela; /* Relocation entries */ |
169 | const Elf_Rela *relalim; /* Limit of Relocation entries */ | | 169 | const Elf_Rela *relalim; /* Limit of Relocation entries */ |
170 | const Elf_Rel *pltrel; /* PLT relocation entries */ | | 170 | const Elf_Rel *pltrel; /* PLT relocation entries */ |
171 | const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */ | | 171 | const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */ |
172 | const Elf_Rela *pltrela; /* PLT relocation entries */ | | 172 | const Elf_Rela *pltrela; /* PLT relocation entries */ |
173 | const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */ | | 173 | const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */ |
174 | const Elf_Sym *symtab; /* Symbol table */ | | 174 | const Elf_Sym *symtab; /* Symbol table */ |
175 | const char *strtab; /* String table */ | | 175 | const char *strtab; /* String table */ |
176 | unsigned long strsize; /* Size in bytes of string table */ | | 176 | unsigned long strsize; /* Size in bytes of string table */ |
177 | #ifdef __mips__ | | 177 | #ifdef __mips__ |
178 | Elf_Word local_gotno; /* Number of local GOT entries */ | | 178 | Elf_Word local_gotno; /* Number of local GOT entries */ |
179 | Elf_Word symtabno; /* Number of dynamic symbols */ | | 179 | Elf_Word symtabno; /* Number of dynamic symbols */ |
180 | Elf_Word gotsym; /* First dynamic symbol in GOT */ | | 180 | Elf_Word gotsym; /* First dynamic symbol in GOT */ |
181 | #endif | | 181 | #endif |
182 | | | 182 | |
183 | const Elf_Symindx *buckets; /* Hash table buckets array */ | | 183 | const Elf_Symindx *buckets; /* Hash table buckets array */ |
184 | unsigned long unused1; /* Used to be nbuckets */ | | 184 | unsigned long unused1; /* Used to be nbuckets */ |
185 | const Elf_Symindx *chains; /* Hash table chain array */ | | 185 | const Elf_Symindx *chains; /* Hash table chain array */ |
186 | unsigned long nchains; /* Number of chains */ | | 186 | unsigned long nchains; /* Number of chains */ |
187 | | | 187 | |
188 | Search_Path *rpaths; /* Search path specified in object */ | | 188 | Search_Path *rpaths; /* Search path specified in object */ |
189 | Needed_Entry *needed; /* Shared objects needed by this (%) */ | | 189 | Needed_Entry *needed; /* Shared objects needed by this (%) */ |
190 | | | 190 | |
191 | void (*init)(void); /* Initialization function to call */ | | 191 | void (*init)(void); /* Initialization function to call */ |
192 | void (*fini)(void); /* Termination function to call */ | | 192 | void (*fini)(void); /* Termination function to call */ |
193 | | | 193 | |
194 | /* Entry points for dlopen() and friends. */ | | 194 | /* |
| | | 195 | * BACKWARDS COMPAT Entry points for dlopen() and friends. |
| | | 196 | * |
| | | 197 | * DO NOT MOVE OR ADD TO THE LIST |
| | | 198 | * |
| | | 199 | */ |
195 | void *(*dlopen)(const char *, int); | | 200 | void *(*dlopen)(const char *, int); |
196 | void *(*dlsym)(void *, const char *); | | 201 | void *(*dlsym)(void *, const char *); |
197 | void *(*dlvsym)(void *, const char *, const char *); | | | |
198 | char *(*dlerror)(void); | | 202 | char *(*dlerror)(void); |
199 | int (*dlclose)(void *); | | 203 | int (*dlclose)(void *); |
200 | int (*dladdr)(const void *, Dl_info *); | | 204 | int (*dladdr)(const void *, Dl_info *); |
201 | | | 205 | |
202 | u_int32_t mainprog:1, /* True if this is the main program */ | | 206 | u_int32_t mainprog:1, /* True if this is the main program */ |
203 | rtld:1, /* True if this is the dynamic linker */ | | 207 | rtld:1, /* True if this is the dynamic linker */ |
204 | textrel:1, /* True if there are relocations to | | 208 | textrel:1, /* True if there are relocations to |
205 | * text seg */ | | 209 | * text seg */ |
206 | symbolic:1, /* True if generated with | | 210 | symbolic:1, /* True if generated with |
207 | * "-Bsymbolic" */ | | 211 | * "-Bsymbolic" */ |
208 | printed:1, /* True if ldd has printed it */ | | 212 | printed:1, /* True if ldd has printed it */ |
209 | isdynamic:1, /* True if this is a pure PIC object */ | | 213 | isdynamic:1, /* True if this is a pure PIC object */ |
210 | mainref:1, /* True if on _rtld_list_main */ | | 214 | mainref:1, /* True if on _rtld_list_main */ |
211 | globalref:1, /* True if on _rtld_list_global */ | | 215 | globalref:1, /* True if on _rtld_list_global */ |
212 | init_done:1, /* True if .init has been added */ | | 216 | init_done:1, /* True if .init has been added */ |
213 | init_called:1, /* True if .init function has been | | 217 | init_called:1, /* True if .init function has been |
214 | * called */ | | 218 | * called */ |
215 | fini_called:1, /* True if .fini function has been | | 219 | fini_called:1, /* True if .fini function has been |
216 | * called */ | | 220 | * called */ |
217 | z_now:1, /* True if object's symbols should be | | 221 | z_now:1, /* True if object's symbols should be |
218 | bound immediately */ | | 222 | bound immediately */ |
219 | z_nodelete:1, /* True if object should never be | | 223 | z_nodelete:1, /* True if object should never be |
220 | unloaded */ | | 224 | unloaded */ |
221 | z_initfirst:1, /* True if object's .init/.fini take | | 225 | z_initfirst:1, /* True if object's .init/.fini take |
222 | * priority over others */ | | 226 | * priority over others */ |
223 | z_noopen:1, /* True if object should never be | | 227 | z_noopen:1, /* True if object should never be |
224 | dlopen'ed */ | | 228 | dlopen'ed */ |
225 | phdr_loaded:1, /* Phdr is loaded and doesn't need to | | 229 | phdr_loaded:1, /* Phdr is loaded and doesn't need to |
226 | * be freed. */ | | 230 | * be freed. */ |
227 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | | 231 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) |
228 | tls_done:1, /* True if static TLS offset | | 232 | tls_done:1, /* True if static TLS offset |
229 | * has been allocated */ | | 233 | * has been allocated */ |
230 | #endif | | 234 | #endif |
231 | ref_nodel:1; /* Refcount increased to prevent dlclose */ | | 235 | ref_nodel:1; /* Refcount increased to prevent dlclose */ |
232 | | | 236 | |
233 | struct link_map linkmap; /* for GDB */ | | 237 | struct link_map linkmap; /* for GDB */ |
234 | | | 238 | |
235 | /* These items are computed by map_object() or by digest_phdr(). */ | | 239 | /* These items are computed by map_object() or by digest_phdr(). */ |
236 | const char *interp; /* Pathname of the interpreter, if any */ | | 240 | const char *interp; /* Pathname of the interpreter, if any */ |
237 | Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ | | 241 | Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ |
238 | Objlist dagmembers; /* DAG has these members (%) */ | | 242 | Objlist dagmembers; /* DAG has these members (%) */ |
239 | dev_t dev; /* Object's filesystem's device */ | | 243 | dev_t dev; /* Object's filesystem's device */ |
240 | ino_t ino; /* Object's inode number */ | | 244 | ino_t ino; /* Object's inode number */ |
241 | | | 245 | |
242 | void *ehdr; | | 246 | void *ehdr; |
243 | | | 247 | |
244 | uint32_t nbuckets; /* Number of buckets */ | | 248 | uint32_t nbuckets; /* Number of buckets */ |
245 | uint32_t nbuckets_m; /* Precomputed for fast remainder */ | | 249 | uint32_t nbuckets_m; /* Precomputed for fast remainder */ |
246 | uint8_t nbuckets_s1; | | 250 | uint8_t nbuckets_s1; |
247 | uint8_t nbuckets_s2; | | 251 | uint8_t nbuckets_s2; |
248 | size_t pathlen; /* Pathname length */ | | 252 | size_t pathlen; /* Pathname length */ |
249 | STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we | | 253 | STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we |
250 | know about. */ | | 254 | know about. */ |
251 | | | 255 | |
252 | #ifdef __powerpc__ | | 256 | #ifdef __powerpc__ |
253 | Elf_Addr *gotptr; /* GOT table (secure-plt only) */ | | 257 | Elf_Addr *gotptr; /* GOT table (secure-plt only) */ |
254 | #endif | | 258 | #endif |
255 | | | 259 | |
256 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | | 260 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) |
257 | /* Thread Local Storage support for this module */ | | 261 | /* Thread Local Storage support for this module */ |
258 | size_t tlsindex; /* Index in DTV */ | | 262 | size_t tlsindex; /* Index in DTV */ |
259 | void *tlsinit; /* Base address of TLS init block */ | | 263 | void *tlsinit; /* Base address of TLS init block */ |
260 | size_t tlsinitsize; /* Size of TLS init block */ | | 264 | size_t tlsinitsize; /* Size of TLS init block */ |
261 | size_t tlssize; /* Size of TLS block */ | | 265 | size_t tlssize; /* Size of TLS block */ |
262 | size_t tlsoffset; /* Offset in the static TLS block */ | | 266 | size_t tlsoffset; /* Offset in the static TLS block */ |
263 | size_t tlsalign; /* Needed alignment for static TLS */ | | 267 | size_t tlsalign; /* Needed alignment for static TLS */ |
264 | #endif | | 268 | #endif |
265 | | | 269 | |
266 | /* symbol versioning */ | | 270 | /* symbol versioning */ |
267 | const Elf_Verneed *verneed; /* Required versions. */ | | 271 | const Elf_Verneed *verneed; /* Required versions. */ |
268 | Elf_Word verneednum; /* Number of entries in verneed table */ | | 272 | Elf_Word verneednum; /* Number of entries in verneed table */ |
269 | const Elf_Verdef *verdef; /* Provided versions. */ | | 273 | const Elf_Verdef *verdef; /* Provided versions. */ |
270 | Elf_Word verdefnum; /* Number of entries in verdef table */ | | 274 | Elf_Word verdefnum; /* Number of entries in verdef table */ |
271 | const Elf_Versym *versyms; /* Symbol versions table */ | | 275 | const Elf_Versym *versyms; /* Symbol versions table */ |
272 | | | 276 | |
273 | Ver_Entry *vertab; /* Versions required/defined by this | | 277 | Ver_Entry *vertab; /* Versions required/defined by this |
274 | * object */ | | 278 | * object */ |
275 | int vertabnum; /* Number of entries in vertab */ | | 279 | int vertabnum; /* Number of entries in vertab */ |
276 | } Obj_Entry; | | 280 | } Obj_Entry; |
277 | | | 281 | |
278 | typedef struct Struct_DoneList { | | 282 | typedef struct Struct_DoneList { |
279 | const Obj_Entry **objs; /* Array of object pointers */ | | 283 | const Obj_Entry **objs; /* Array of object pointers */ |
280 | unsigned int num_alloc; /* Allocated size of the array */ | | 284 | unsigned int num_alloc; /* Allocated size of the array */ |
281 | unsigned int num_used; /* Number of array slots used */ | | 285 | unsigned int num_used; /* Number of array slots used */ |
282 | } DoneList; | | 286 | } DoneList; |
283 | | | 287 | |
284 | | | 288 | |
285 | #if defined(_RTLD_SOURCE) | | 289 | #if defined(_RTLD_SOURCE) |
286 | | | 290 | |
287 | extern struct r_debug _rtld_debug; | | 291 | extern struct r_debug _rtld_debug; |
288 | extern Search_Path *_rtld_default_paths; | | 292 | extern Search_Path *_rtld_default_paths; |
289 | extern Obj_Entry *_rtld_objlist; | | 293 | extern Obj_Entry *_rtld_objlist; |
290 | extern Obj_Entry **_rtld_objtail; | | 294 | extern Obj_Entry **_rtld_objtail; |
291 | extern u_int _rtld_objcount; | | 295 | extern u_int _rtld_objcount; |
292 | extern u_int _rtld_objloads; | | 296 | extern u_int _rtld_objloads; |
293 | extern Obj_Entry *_rtld_objmain; | | 297 | extern Obj_Entry *_rtld_objmain; |
294 | extern Obj_Entry _rtld_objself; | | 298 | extern Obj_Entry _rtld_objself; |
295 | extern Search_Path *_rtld_paths; | | 299 | extern Search_Path *_rtld_paths; |
296 | extern Library_Xform *_rtld_xforms; | | 300 | extern Library_Xform *_rtld_xforms; |
297 | extern bool _rtld_trust; | | 301 | extern bool _rtld_trust; |
298 | extern Objlist _rtld_list_global; | | 302 | extern Objlist _rtld_list_global; |
299 | extern Objlist _rtld_list_main; | | 303 | extern Objlist _rtld_list_main; |
300 | extern Elf_Sym _rtld_sym_zero; | | 304 | extern Elf_Sym _rtld_sym_zero; |
301 | | | 305 | |
302 | #define RTLD_MODEMASK 0x3 | | 306 | #define RTLD_MODEMASK 0x3 |
303 | | | 307 | |
304 | /* Flags to be passed into _rtld_symlook_ family of functions. */ | | 308 | /* Flags to be passed into _rtld_symlook_ family of functions. */ |
305 | #define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ | | 309 | #define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ |
306 | #define SYMLOOK_DLSYM 0x02 /* Return newes versioned symbol. | | 310 | #define SYMLOOK_DLSYM 0x02 /* Return newes versioned symbol. |
307 | Used by dlsym. */ | | 311 | Used by dlsym. */ |
308 | | | 312 | |
309 | /* Flags for _rtld_load_object() and friends. */ | | 313 | /* Flags for _rtld_load_object() and friends. */ |
310 | #define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */ | | 314 | #define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */ |
311 | #define _RTLD_MAIN 0x02 | | 315 | #define _RTLD_MAIN 0x02 |
312 | #define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */ | | 316 | #define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */ |
313 | #define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen(). */ | | 317 | #define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen(). */ |
314 | | | 318 | |
315 | /* Preallocation for static TLS model */ | | 319 | /* Preallocation for static TLS model */ |
316 | #define RTLD_STATIC_TLS_RESERVATION 64 | | 320 | #define RTLD_STATIC_TLS_RESERVATION 64 |
317 | | | 321 | |
318 | /* rtld.c */ | | 322 | /* rtld.c */ |
319 | | | 323 | |
320 | /* We export these symbols using _rtld_symbol_lookup and is_exported. */ | | 324 | /* We export these symbols using _rtld_symbol_lookup and is_exported. */ |
321 | __dso_public char *dlerror(void); | | 325 | __dso_public char *dlerror(void); |
322 | __dso_public void *dlopen(const char *, int); | | 326 | __dso_public void *dlopen(const char *, int); |
323 | __dso_public void *dlsym(void *, const char *); | | 327 | __dso_public void *dlsym(void *, const char *); |
324 | __dso_public int dlclose(void *); | | 328 | __dso_public int dlclose(void *); |
325 | __dso_public int dladdr(const void *, Dl_info *); | | 329 | __dso_public int dladdr(const void *, Dl_info *); |
326 | __dso_public int dlinfo(void *, int, void *); | | 330 | __dso_public int dlinfo(void *, int, void *); |
327 | __dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), | | 331 | __dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), |
328 | void *); | | 332 | void *); |
329 | | | 333 | |
330 | /* These aren't exported */ | | 334 | /* These aren't exported */ |
331 | void _rtld_error(const char *, ...) | | 335 | void _rtld_error(const char *, ...) |
332 | __attribute__((__format__(__printf__,1,2))); | | 336 | __attribute__((__format__(__printf__,1,2))); |
333 | void _rtld_die(void) __attribute__((__noreturn__)); | | 337 | void _rtld_die(void) __attribute__((__noreturn__)); |
334 | void *_rtld_objmain_sym(const char *); | | 338 | void *_rtld_objmain_sym(const char *); |
335 | __dso_public void _rtld_debug_state(void); | | 339 | __dso_public void _rtld_debug_state(void); |
336 | void _rtld_linkmap_add(Obj_Entry *); | | 340 | void _rtld_linkmap_add(Obj_Entry *); |
337 | void _rtld_linkmap_delete(Obj_Entry *); | | 341 | void _rtld_linkmap_delete(Obj_Entry *); |
338 | void _rtld_objlist_push_head(Objlist *, Obj_Entry *); | | 342 | void _rtld_objlist_push_head(Objlist *, Obj_Entry *); |
339 | void _rtld_objlist_push_tail(Objlist *, Obj_Entry *); | | 343 | void _rtld_objlist_push_tail(Objlist *, Obj_Entry *); |
340 | Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *); | | 344 | Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *); |
341 | void _rtld_ref_dag(Obj_Entry *); | | 345 | void _rtld_ref_dag(Obj_Entry *); |
342 | | | 346 | |
343 | void _rtld_shared_enter(void); | | 347 | void _rtld_shared_enter(void); |
344 | void _rtld_shared_exit(void); | | 348 | void _rtld_shared_exit(void); |
345 | void _rtld_exclusive_enter(sigset_t *); | | 349 | void _rtld_exclusive_enter(sigset_t *); |
346 | void _rtld_exclusive_exit(sigset_t *); | | 350 | void _rtld_exclusive_exit(sigset_t *); |
347 | | | 351 | |
348 | /* expand.c */ | | 352 | /* expand.c */ |
349 | size_t _rtld_expand_path(char *, size_t, const char *, const char *,\ | | 353 | size_t _rtld_expand_path(char *, size_t, const char *, const char *,\ |
350 | const char *); | | 354 | const char *); |
351 | | | 355 | |
352 | /* headers.c */ | | 356 | /* headers.c */ |
353 | void _rtld_digest_dynamic(const char *, Obj_Entry *); | | 357 | void _rtld_digest_dynamic(const char *, Obj_Entry *); |
354 | Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); | | 358 | Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); |
355 | | | 359 | |
356 | /* load.c */ | | 360 | /* load.c */ |
357 | Obj_Entry *_rtld_load_object(const char *, int); | | 361 | Obj_Entry *_rtld_load_object(const char *, int); |
358 | int _rtld_load_needed_objects(Obj_Entry *, int); | | 362 | int _rtld_load_needed_objects(Obj_Entry *, int); |
359 | int _rtld_preload(const char *); | | 363 | int _rtld_preload(const char *); |
360 | | | 364 | |
361 | #define OBJ_ERR (Obj_Entry *)(-1) | | 365 | #define OBJ_ERR (Obj_Entry *)(-1) |
362 | /* path.c */ | | 366 | /* path.c */ |
363 | void _rtld_add_paths(const char *, Search_Path **, const char *); | | 367 | void _rtld_add_paths(const char *, Search_Path **, const char *); |
364 | void _rtld_process_hints(const char *, Search_Path **, Library_Xform **, | | 368 | void _rtld_process_hints(const char *, Search_Path **, Library_Xform **, |
365 | const char *); | | 369 | const char *); |
366 | int _rtld_sysctl(const char *, void *, size_t *); | | 370 | int _rtld_sysctl(const char *, void *, size_t *); |
367 | | | 371 | |
368 | /* reloc.c */ | | 372 | /* reloc.c */ |
369 | int _rtld_do_copy_relocations(const Obj_Entry *); | | 373 | int _rtld_do_copy_relocations(const Obj_Entry *); |
370 | int _rtld_relocate_objects(Obj_Entry *, bool); | | 374 | int _rtld_relocate_objects(Obj_Entry *, bool); |
371 | int _rtld_relocate_nonplt_objects(Obj_Entry *); | | 375 | int _rtld_relocate_nonplt_objects(Obj_Entry *); |
372 | int _rtld_relocate_plt_lazy(const Obj_Entry *); | | 376 | int _rtld_relocate_plt_lazy(const Obj_Entry *); |
373 | int _rtld_relocate_plt_objects(const Obj_Entry *); | | 377 | int _rtld_relocate_plt_objects(const Obj_Entry *); |
374 | void _rtld_setup_pltgot(const Obj_Entry *); | | 378 | void _rtld_setup_pltgot(const Obj_Entry *); |
375 | | | 379 | |
376 | /* search.c */ | | 380 | /* search.c */ |
377 | Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); | | 381 | Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); |
378 | | | 382 | |
379 | /* symbol.c */ | | 383 | /* symbol.c */ |
380 | unsigned long _rtld_elf_hash(const char *); | | 384 | unsigned long _rtld_elf_hash(const char *); |
381 | const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, | | 385 | const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, |
382 | const Obj_Entry *, u_int, const Ver_Entry *); | | 386 | const Obj_Entry *, u_int, const Ver_Entry *); |
383 | const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, | | 387 | const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, |
384 | const Obj_Entry **, u_int); | | 388 | const Obj_Entry **, u_int); |
385 | const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *, | | 389 | const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *, |
386 | const Obj_Entry **, bool); | | 390 | const Obj_Entry **, bool); |
387 | | | 391 | |
388 | const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, | | 392 | const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, |
389 | const Objlist *, const Obj_Entry **, u_int, const Ver_Entry *, DoneList *); | | 393 | const Objlist *, const Obj_Entry **, u_int, const Ver_Entry *, DoneList *); |
390 | const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, | | 394 | const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, |
391 | const Obj_Entry *, const Obj_Entry **, u_int, const Ver_Entry *); | | 395 | const Obj_Entry *, const Obj_Entry **, u_int, const Ver_Entry *); |
392 | const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long, | | 396 | const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long, |
393 | const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *, | | 397 | const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *, |
394 | DoneList *, DoneList *); | | 398 | DoneList *, DoneList *); |
395 | #ifdef COMBRELOC | | 399 | #ifdef COMBRELOC |
396 | void _rtld_combreloc_reset(const Obj_Entry *); | | 400 | void _rtld_combreloc_reset(const Obj_Entry *); |
397 | #endif | | 401 | #endif |
398 | | | 402 | |
399 | /* symver.c */ | | 403 | /* symver.c */ |
400 | int _rtld_object_match_name(const Obj_Entry *, const char *); | | 404 | int _rtld_object_match_name(const Obj_Entry *, const char *); |
401 | int _rtld_verify_object_versions(Obj_Entry *); | | 405 | int _rtld_verify_object_versions(Obj_Entry *); |
402 | | | 406 | |
403 | static __inline const Ver_Entry * | | 407 | static __inline const Ver_Entry * |
404 | _rtld_fetch_ventry(const Obj_Entry *obj, unsigned long symnum) | | 408 | _rtld_fetch_ventry(const Obj_Entry *obj, unsigned long symnum) |
405 | { | | 409 | { |
406 | Elf_Half vernum; | | 410 | Elf_Half vernum; |
407 | | | 411 | |
408 | if (obj->vertab) { | | 412 | if (obj->vertab) { |
409 | vernum = VER_NDX(obj->versyms[symnum].vs_vers); | | 413 | vernum = VER_NDX(obj->versyms[symnum].vs_vers); |
410 | if (vernum >= obj->vertabnum) { | | 414 | if (vernum >= obj->vertabnum) { |
411 | _rtld_error("%s: symbol %s has wrong verneed value %d", | | 415 | _rtld_error("%s: symbol %s has wrong verneed value %d", |
412 | obj->path, &obj->strtab[symnum], vernum); | | 416 | obj->path, &obj->strtab[symnum], vernum); |
413 | } else if (obj->vertab[vernum].hash) { | | 417 | } else if (obj->vertab[vernum].hash) { |
414 | return &obj->vertab[vernum]; | | 418 | return &obj->vertab[vernum]; |
415 | } | | 419 | } |
416 | } | | 420 | } |
417 | return NULL; | | 421 | return NULL; |
418 | } | | 422 | } |
419 | | | 423 | |
420 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | | 424 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) |
421 | /* tls.c */ | | 425 | /* tls.c */ |
422 | void *_rtld_tls_get_addr(void *, size_t, size_t); | | 426 | void *_rtld_tls_get_addr(void *, size_t, size_t); |
423 | void _rtld_tls_initial_allocation(void); | | 427 | void _rtld_tls_initial_allocation(void); |
424 | void *_rtld_tls_module_allocate(size_t index); | | 428 | void *_rtld_tls_module_allocate(size_t index); |
425 | int _rtld_tls_offset_allocate(Obj_Entry *); | | 429 | int _rtld_tls_offset_allocate(Obj_Entry *); |
426 | void _rtld_tls_offset_free(Obj_Entry *); | | 430 | void _rtld_tls_offset_free(Obj_Entry *); |
427 | | | 431 | |
428 | extern size_t _rtld_tls_dtv_generation; | | 432 | extern size_t _rtld_tls_dtv_generation; |
429 | extern size_t _rtld_tls_max_index; | | 433 | extern size_t _rtld_tls_max_index; |
430 | | | 434 | |
431 | __dso_public extern void *__tls_get_addr(void *); | | 435 | __dso_public extern void *__tls_get_addr(void *); |
432 | #ifdef __i386__ | | 436 | #ifdef __i386__ |
433 | __dso_public extern void *___tls_get_addr(void *) | | 437 | __dso_public extern void *___tls_get_addr(void *) |
434 | __attribute__((__regparm__(1))); | | 438 | __attribute__((__regparm__(1))); |
435 | #endif | | 439 | #endif |
436 | #endif | | 440 | #endif |
437 | | | 441 | |
438 | /* map_object.c */ | | 442 | /* map_object.c */ |
439 | struct stat; | | 443 | struct stat; |
440 | Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); | | 444 | Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); |
441 | void _rtld_obj_free(Obj_Entry *); | | 445 | void _rtld_obj_free(Obj_Entry *); |
442 | Obj_Entry *_rtld_obj_new(void); | | 446 | Obj_Entry *_rtld_obj_new(void); |
443 | | | 447 | |
444 | /* function descriptors */ | | 448 | /* function descriptors */ |
445 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | | 449 | #ifdef __HAVE_FUNCTION_DESCRIPTORS |
446 | Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, | | 450 | Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, |
447 | const Elf_Sym *, Elf_Addr); | | 451 | const Elf_Sym *, Elf_Addr); |
448 | const void *_rtld_function_descriptor_function(const void *); | | 452 | const void *_rtld_function_descriptor_function(const void *); |
449 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | | 453 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ |
450 | | | 454 | |
451 | #endif /* _RTLD_SOURCE */ | | 455 | #endif /* _RTLD_SOURCE */ |
452 | | | 456 | |
453 | #endif /* RTLD_H */ | | 457 | #endif /* RTLD_H */ |