1 |
1325 |
phoenix |
/* vi: set sw=4 ts=4: */
|
2 |
|
|
/* Program to load an ELF binary on a linux system, and run it
|
3 |
|
|
* after resolving ELF shared library symbols
|
4 |
|
|
*
|
5 |
|
|
* Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
|
6 |
|
|
* David Engel, Hongjiu Lu and Mitch D'Souza
|
7 |
|
|
* Copyright (C) 2001-2002, Erik Andersen
|
8 |
|
|
*
|
9 |
|
|
* All rights reserved.
|
10 |
|
|
*
|
11 |
|
|
* Redistribution and use in source and binary forms, with or without
|
12 |
|
|
* modification, are permitted provided that the following conditions
|
13 |
|
|
* are met:
|
14 |
|
|
* 1. Redistributions of source code must retain the above copyright
|
15 |
|
|
* notice, this list of conditions and the following disclaimer.
|
16 |
|
|
* 2. The name of the above contributors may not be
|
17 |
|
|
* used to endorse or promote products derived from this software
|
18 |
|
|
* without specific prior written permission.
|
19 |
|
|
*
|
20 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
|
21 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
|
24 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
26 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
27 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
28 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
29 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
30 |
|
|
* SUCH DAMAGE.
|
31 |
|
|
*/
|
32 |
|
|
|
33 |
|
|
|
34 |
|
|
/* Various symbol table handling functions, including symbol lookup */
|
35 |
|
|
|
36 |
|
|
/*
|
37 |
|
|
* This is the start of the linked list that describes all of the files present
|
38 |
|
|
* in the system with pointers to all of the symbol, string, and hash tables,
|
39 |
|
|
* as well as all of the other good stuff in the binary.
|
40 |
|
|
*/
|
41 |
|
|
|
42 |
|
|
struct elf_resolve *_dl_loaded_modules = NULL;
|
43 |
|
|
|
44 |
|
|
/*
|
45 |
|
|
* This is the list of modules that are loaded when the image is first
|
46 |
|
|
* started. As we add more via dlopen, they get added into other
|
47 |
|
|
* chains.
|
48 |
|
|
*/
|
49 |
|
|
struct dyn_elf *_dl_symbol_tables = NULL;
|
50 |
|
|
|
51 |
|
|
/*
|
52 |
|
|
* This is the list of modules that are loaded via dlopen. We may need
|
53 |
|
|
* to search these for RTLD_GLOBAL files.
|
54 |
|
|
*/
|
55 |
|
|
struct dyn_elf *_dl_handles = NULL;
|
56 |
|
|
|
57 |
|
|
|
58 |
|
|
/*
|
59 |
|
|
* This is the hash function that is used by the ELF linker to generate
|
60 |
|
|
* the hash table that each executable and library is required to
|
61 |
|
|
* have. We need it to decode the hash table.
|
62 |
|
|
*/
|
63 |
|
|
|
64 |
|
|
unsigned long _dl_elf_hash(const char *name)
|
65 |
|
|
{
|
66 |
|
|
unsigned long hash = 0;
|
67 |
|
|
unsigned long tmp;
|
68 |
|
|
|
69 |
|
|
while (*name) {
|
70 |
|
|
hash = (hash << 4) + *name++;
|
71 |
|
|
if ((tmp = hash & 0xf0000000))
|
72 |
|
|
hash ^= tmp >> 24;
|
73 |
|
|
hash &= ~tmp;
|
74 |
|
|
};
|
75 |
|
|
return hash;
|
76 |
|
|
}
|
77 |
|
|
|
78 |
|
|
/*
|
79 |
|
|
* Check to see if a library has already been added to the hash chain.
|
80 |
|
|
*/
|
81 |
|
|
struct elf_resolve *_dl_check_hashed_files(const char *libname)
|
82 |
|
|
{
|
83 |
|
|
struct elf_resolve *tpnt;
|
84 |
|
|
int len = _dl_strlen(libname);
|
85 |
|
|
|
86 |
|
|
for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
|
87 |
|
|
if (_dl_strncmp(tpnt->libname, libname, len) == 0 &&
|
88 |
|
|
(tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
|
89 |
|
|
return tpnt;
|
90 |
|
|
}
|
91 |
|
|
|
92 |
|
|
return NULL;
|
93 |
|
|
}
|
94 |
|
|
|
95 |
|
|
/*
|
96 |
|
|
* We call this function when we have just read an ELF library or executable.
|
97 |
|
|
* We add the relevant info to the symbol chain, so that we can resolve all
|
98 |
|
|
* externals properly.
|
99 |
|
|
*/
|
100 |
|
|
|
101 |
|
|
struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
|
102 |
|
|
char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
|
103 |
|
|
unsigned long dynamic_size)
|
104 |
|
|
{
|
105 |
|
|
unsigned long *hash_addr;
|
106 |
|
|
struct elf_resolve *tpnt;
|
107 |
|
|
int i;
|
108 |
|
|
|
109 |
|
|
if (!_dl_loaded_modules) {
|
110 |
|
|
tpnt = _dl_loaded_modules =
|
111 |
|
|
(struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
|
112 |
|
|
_dl_memset(tpnt, 0, sizeof(struct elf_resolve));
|
113 |
|
|
} else {
|
114 |
|
|
tpnt = _dl_loaded_modules;
|
115 |
|
|
while (tpnt->next)
|
116 |
|
|
tpnt = tpnt->next;
|
117 |
|
|
tpnt->next = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
|
118 |
|
|
_dl_memset(tpnt->next, 0, sizeof(struct elf_resolve));
|
119 |
|
|
tpnt->next->prev = tpnt;
|
120 |
|
|
tpnt = tpnt->next;
|
121 |
|
|
};
|
122 |
|
|
|
123 |
|
|
tpnt->next = NULL;
|
124 |
|
|
tpnt->init_flag = 0;
|
125 |
|
|
tpnt->libname = _dl_strdup(libname);
|
126 |
|
|
tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr;
|
127 |
|
|
tpnt->dynamic_size = dynamic_size;
|
128 |
|
|
tpnt->libtype = loaded_file;
|
129 |
|
|
|
130 |
|
|
if (dynamic_info[DT_HASH] != 0) {
|
131 |
|
|
hash_addr = (unsigned long *) (intptr_t)(dynamic_info[DT_HASH] + loadaddr);
|
132 |
|
|
tpnt->nbucket = *hash_addr++;
|
133 |
|
|
tpnt->nchain = *hash_addr++;
|
134 |
|
|
tpnt->elf_buckets = hash_addr;
|
135 |
|
|
hash_addr += tpnt->nbucket;
|
136 |
|
|
tpnt->chains = hash_addr;
|
137 |
|
|
}
|
138 |
|
|
tpnt->loadaddr = (ElfW(Addr))loadaddr;
|
139 |
|
|
for (i = 0; i < 24; i++)
|
140 |
|
|
tpnt->dynamic_info[i] = dynamic_info[i];
|
141 |
|
|
#ifdef __mips__
|
142 |
|
|
{
|
143 |
|
|
Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
|
144 |
|
|
|
145 |
|
|
while(dpnt->d_tag) {
|
146 |
|
|
if (dpnt->d_tag == DT_MIPS_GOTSYM)
|
147 |
|
|
tpnt->mips_gotsym = dpnt->d_un.d_val;
|
148 |
|
|
if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
|
149 |
|
|
tpnt->mips_local_gotno = dpnt->d_un.d_val;
|
150 |
|
|
if (dpnt->d_tag == DT_MIPS_SYMTABNO)
|
151 |
|
|
tpnt->mips_symtabno = dpnt->d_un.d_val;
|
152 |
|
|
dpnt++;
|
153 |
|
|
}
|
154 |
|
|
}
|
155 |
|
|
#endif
|
156 |
|
|
return tpnt;
|
157 |
|
|
}
|
158 |
|
|
|
159 |
|
|
|
160 |
|
|
/*
|
161 |
|
|
* This function resolves externals, and this is either called when we process
|
162 |
|
|
* relocations or when we call an entry in the PLT table for the first time.
|
163 |
|
|
*/
|
164 |
|
|
|
165 |
|
|
char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
|
166 |
|
|
struct elf_resolve *f_tpnt, enum caller_type caller_type)
|
167 |
|
|
{
|
168 |
|
|
struct elf_resolve *tpnt;
|
169 |
|
|
int si;
|
170 |
|
|
char *pnt;
|
171 |
|
|
int pass;
|
172 |
|
|
char *strtab;
|
173 |
|
|
Elf32_Sym *symtab;
|
174 |
|
|
unsigned long elf_hash_number, hn;
|
175 |
|
|
char *weak_result;
|
176 |
|
|
struct elf_resolve *first_def;
|
177 |
|
|
struct dyn_elf *rpnt, first;
|
178 |
|
|
char *data_result = 0; /* nakao */
|
179 |
|
|
|
180 |
|
|
weak_result = 0;
|
181 |
|
|
elf_hash_number = _dl_elf_hash(name);
|
182 |
|
|
|
183 |
|
|
/* A quick little hack to make sure that any symbol in the executable
|
184 |
|
|
will be preferred to one in a shared library. This is necessary so
|
185 |
|
|
that any shared library data symbols referenced in the executable
|
186 |
|
|
will be seen at the same address by the executable, shared libraries
|
187 |
|
|
and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
|
188 |
|
|
if (_dl_symbol_tables && !caller_type && rpnt1) {
|
189 |
|
|
first = (*_dl_symbol_tables);
|
190 |
|
|
first.next = rpnt1;
|
191 |
|
|
rpnt1 = (&first);
|
192 |
|
|
}
|
193 |
|
|
|
194 |
|
|
/*
|
195 |
|
|
* The passes are so that we can first search the regular symbols
|
196 |
|
|
* for whatever module was specified, and then search anything
|
197 |
|
|
* loaded with RTLD_GLOBAL. When pass is 1, it means we are just
|
198 |
|
|
* starting the first dlopened module, and anything above that
|
199 |
|
|
* is just the next one in the chain.
|
200 |
|
|
*/
|
201 |
|
|
for (pass = 0; (1 == 1); pass++) {
|
202 |
|
|
|
203 |
|
|
/*
|
204 |
|
|
* If we are just starting to search for RTLD_GLOBAL, setup
|
205 |
|
|
* the pointer for the start of the search.
|
206 |
|
|
*/
|
207 |
|
|
if (pass == 1) {
|
208 |
|
|
rpnt1 = _dl_handles;
|
209 |
|
|
}
|
210 |
|
|
|
211 |
|
|
/*
|
212 |
|
|
* Anything after this, we need to skip to the next module.
|
213 |
|
|
*/
|
214 |
|
|
else if (pass >= 2) {
|
215 |
|
|
rpnt1 = rpnt1->next_handle;
|
216 |
|
|
}
|
217 |
|
|
|
218 |
|
|
/*
|
219 |
|
|
* Make sure we still have a module, and make sure that this
|
220 |
|
|
* module was loaded with RTLD_GLOBAL.
|
221 |
|
|
*/
|
222 |
|
|
if (pass != 0) {
|
223 |
|
|
if (rpnt1 == NULL)
|
224 |
|
|
break;
|
225 |
|
|
if ((rpnt1->flags & RTLD_GLOBAL) == 0)
|
226 |
|
|
continue;
|
227 |
|
|
}
|
228 |
|
|
|
229 |
|
|
for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
|
230 |
|
|
tpnt = rpnt->dyn;
|
231 |
|
|
|
232 |
|
|
/*
|
233 |
|
|
* The idea here is that if we are using dlsym, we want to
|
234 |
|
|
* first search the entire chain loaded from dlopen, and
|
235 |
|
|
* return a result from that if we found anything. If this
|
236 |
|
|
* fails, then we continue the search into the stuff loaded
|
237 |
|
|
* when the image was activated. For normal lookups, we start
|
238 |
|
|
* with rpnt == NULL, so we should never hit this.
|
239 |
|
|
*/
|
240 |
|
|
if (tpnt->libtype == elf_executable && weak_result != 0) {
|
241 |
|
|
break;
|
242 |
|
|
}
|
243 |
|
|
|
244 |
|
|
/*
|
245 |
|
|
* Avoid calling .urem here.
|
246 |
|
|
*/
|
247 |
|
|
do_rem(hn, elf_hash_number, tpnt->nbucket);
|
248 |
|
|
symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
|
249 |
|
|
strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
|
250 |
|
|
/*
|
251 |
|
|
* This crap is required because the first instance of a
|
252 |
|
|
* symbol on the chain will be used for all symbol references.
|
253 |
|
|
* Thus this instance must be resolved to an address that
|
254 |
|
|
* contains the actual function,
|
255 |
|
|
*/
|
256 |
|
|
|
257 |
|
|
first_def = NULL;
|
258 |
|
|
|
259 |
|
|
for (si = tpnt->elf_buckets[hn]; si; si = tpnt->chains[si]) {
|
260 |
|
|
pnt = strtab + symtab[si].st_name;
|
261 |
|
|
|
262 |
|
|
if (_dl_strcmp(pnt, name) == 0 &&
|
263 |
|
|
symtab[si].st_value != 0)
|
264 |
|
|
{
|
265 |
|
|
if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
|
266 |
|
|
ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
|
267 |
|
|
ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
|
268 |
|
|
symtab[si].st_shndx != SHN_UNDEF) {
|
269 |
|
|
|
270 |
|
|
/* Here we make sure that we find a module where the symbol is
|
271 |
|
|
* actually defined.
|
272 |
|
|
*/
|
273 |
|
|
|
274 |
|
|
if (f_tpnt) {
|
275 |
|
|
if (!first_def)
|
276 |
|
|
first_def = tpnt;
|
277 |
|
|
if (first_def == f_tpnt
|
278 |
|
|
&& symtab[si].st_shndx == 0)
|
279 |
|
|
continue;
|
280 |
|
|
}
|
281 |
|
|
|
282 |
|
|
switch (ELF32_ST_BIND(symtab[si].st_info)) {
|
283 |
|
|
case STB_GLOBAL:
|
284 |
|
|
if (tpnt->libtype != elf_executable &&
|
285 |
|
|
ELF32_ST_TYPE(symtab[si].st_info)
|
286 |
|
|
== STT_NOTYPE)
|
287 |
|
|
{ /* nakao */
|
288 |
|
|
data_result = (char *)tpnt->loadaddr +
|
289 |
|
|
symtab[si].st_value; /* nakao */
|
290 |
|
|
break; /* nakao */
|
291 |
|
|
} else /* nakao */
|
292 |
|
|
return (char*)tpnt->loadaddr + symtab[si].st_value;
|
293 |
|
|
case STB_WEAK:
|
294 |
|
|
if (!weak_result)
|
295 |
|
|
weak_result = (char *)tpnt->loadaddr + symtab[si].st_value;
|
296 |
|
|
break;
|
297 |
|
|
default: /* Do local symbols need to be examined? */
|
298 |
|
|
break;
|
299 |
|
|
}
|
300 |
|
|
}
|
301 |
|
|
#ifndef __mips__
|
302 |
|
|
/*
|
303 |
|
|
* References to the address of a function from an executable file and
|
304 |
|
|
* the shared objects associated with it might not resolve to the same
|
305 |
|
|
* value. To allow comparisons of function addresses we must resolve
|
306 |
|
|
* to the address of the plt entry of the executable instead of the
|
307 |
|
|
* real function address.
|
308 |
|
|
* see "TIS ELF Specification Version 1.2, Book 3, A-11 (Function
|
309 |
|
|
* Adresses)
|
310 |
|
|
*/
|
311 |
|
|
if (resolver != caller_type &&
|
312 |
|
|
NULL==f_tpnt && /*trick: don't handle R_??_JMP_SLOT reloc type*/
|
313 |
|
|
tpnt->libtype == elf_executable &&
|
314 |
|
|
ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC &&
|
315 |
|
|
symtab[si].st_shndx == SHN_UNDEF)
|
316 |
|
|
{
|
317 |
|
|
return (char*)symtab[si].st_value;
|
318 |
|
|
}
|
319 |
|
|
#endif
|
320 |
|
|
}
|
321 |
|
|
}
|
322 |
|
|
}
|
323 |
|
|
}
|
324 |
|
|
if (data_result)
|
325 |
|
|
return data_result; /* nakao */
|
326 |
|
|
return weak_result;
|
327 |
|
|
}
|