ltrace-elf.c revision a7db59c355cef464073496221ad27519a48466f9
1#include "config.h"
2
3#include <endian.h>
4#include <errno.h>
5#include <error.h>
6#include <fcntl.h>
7#include <gelf.h>
8#include <inttypes.h>
9#include <stdint.h>
10#include <stdlib.h>
11#include <string.h>
12#include <unistd.h>
13#include <assert.h>
14
15#include "common.h"
16#include "proc.h"
17
18void do_close_elf(struct ltelf *lte);
19void add_library_symbol(GElf_Addr addr, const char *name,
20		struct library_symbol **library_symbolspp,
21		enum toplt type_of_plt, int is_weak);
22int in_load_libraries(const char *name, struct ltelf *lte, size_t count, GElf_Sym *sym);
23static GElf_Addr opd2addr(struct ltelf *ltc, GElf_Addr addr);
24
25struct library_symbol *library_symbols = NULL;
26struct ltelf main_lte;
27
28#ifdef PLT_REINITALISATION_BP
29extern char *PLTs_initialized_by_here;
30#endif
31
32#ifndef DT_PPC_GOT
33# define DT_PPC_GOT		(DT_LOPROC + 0)
34#endif
35
36#define PPC_PLT_STUB_SIZE 16
37
38static Elf_Data *loaddata(Elf_Scn *scn, GElf_Shdr *shdr)
39{
40	Elf_Data *data = elf_getdata(scn, NULL);
41	if (data == NULL || elf_getdata(scn, data) != NULL
42	    || data->d_off || data->d_size != shdr->sh_size)
43		return NULL;
44	return data;
45}
46
47static int inside(GElf_Addr addr, GElf_Shdr *shdr)
48{
49	return addr >= shdr->sh_addr
50		&& addr < shdr->sh_addr + shdr->sh_size;
51}
52
53static int maybe_pick_section(GElf_Addr addr,
54			      Elf_Scn *in_sec, GElf_Shdr *in_shdr,
55			      Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
56{
57	if (inside (addr, in_shdr)) {
58		*tgt_sec = in_sec;
59		*tgt_shdr = *in_shdr;
60		return 1;
61	}
62	return 0;
63}
64
65static int get_section_covering(struct ltelf *lte, GElf_Addr addr,
66				Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
67{
68	int i;
69	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
70		Elf_Scn *scn;
71		GElf_Shdr shdr;
72
73		scn = elf_getscn(lte->elf, i);
74		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
75			debug(1, "Couldn't read section or header.");
76			return 0;
77		}
78
79		if (maybe_pick_section(addr, scn, &shdr, tgt_sec, tgt_shdr))
80			return 1;
81	}
82
83	return 0;
84}
85
86static GElf_Addr read32be(Elf_Data *data, size_t offset)
87{
88	if (data->d_size < offset + 4) {
89		debug(1, "Not enough data to read 32bit value at offset %zd.",
90		      offset);
91		return 0;
92	}
93
94	unsigned char const *buf = data->d_buf + offset;
95	return ((Elf32_Word)buf[0] << 24)
96		| ((Elf32_Word)buf[1] << 16)
97		| ((Elf32_Word)buf[2] << 8)
98		| ((Elf32_Word)buf[3]);
99}
100
101static GElf_Addr get_glink_vma(struct ltelf *lte, GElf_Addr ppcgot,
102			       Elf_Data *plt_data)
103{
104	Elf_Scn *ppcgot_sec = NULL;
105	GElf_Shdr ppcgot_shdr;
106	if (ppcgot != 0
107	    && !get_section_covering(lte, ppcgot, &ppcgot_sec, &ppcgot_shdr))
108		// xxx should be the log out
109		fprintf(stderr,
110			"DT_PPC_GOT=%#" PRIx64 ", but no such section found.\n",
111			ppcgot);
112
113	if (ppcgot_sec != NULL) {
114		Elf_Data *data = loaddata(ppcgot_sec, &ppcgot_shdr);
115		if (data == NULL
116		    || data->d_size < 8 )
117			debug(1, "Couldn't read GOT data.");
118		else {
119			// where PPCGOT begins in .got
120			size_t offset = ppcgot - ppcgot_shdr.sh_addr;
121			GElf_Addr glink_vma = read32be(data, offset + 4);
122			if (glink_vma != 0) {
123				debug(1, "PPC GOT glink_vma address: %#" PRIx64,
124				      glink_vma);
125				return glink_vma;
126			}
127		}
128	}
129
130	if (plt_data != NULL) {
131		GElf_Addr glink_vma = read32be(plt_data, 0);
132		debug(1, ".plt glink_vma address: %#" PRIx64, glink_vma);
133		return glink_vma;
134	}
135
136	return 0;
137}
138
139int
140open_elf(struct ltelf *lte, const char *filename)
141{
142	lte->fd = open(filename, O_RDONLY);
143	if (lte->fd == -1)
144		return 1;
145
146	elf_version(EV_CURRENT);
147
148#ifdef HAVE_ELF_C_READ_MMAP
149	lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL);
150#else
151	lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL);
152#endif
153
154	if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF)
155		error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename);
156
157	if (gelf_getehdr(lte->elf, &lte->ehdr) == NULL)
158		error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"",
159		      filename);
160
161	if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN)
162		error(EXIT_FAILURE, 0,
163		      "\"%s\" is not an ELF executable nor shared library",
164		      filename);
165
166	if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
167	     || lte->ehdr.e_machine != LT_ELF_MACHINE)
168#ifdef LT_ELF_MACHINE2
169	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2
170		|| lte->ehdr.e_machine != LT_ELF_MACHINE2)
171#endif
172#ifdef LT_ELF_MACHINE3
173	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3
174		|| lte->ehdr.e_machine != LT_ELF_MACHINE3)
175#endif
176	    )
177		error(EXIT_FAILURE, 0,
178		      "\"%s\" is ELF from incompatible architecture", filename);
179
180	return 0;
181}
182
183int
184do_init_elf(struct ltelf *lte, const char *filename) {
185	int i;
186	GElf_Addr relplt_addr = 0;
187	size_t relplt_size = 0;
188
189	debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename);
190	debug(1, "Reading ELF from %s...", filename);
191
192	if (open_elf(lte, filename) < 0)
193		return -1;
194
195	Elf_Data *plt_data = NULL;
196	GElf_Addr ppcgot = 0;
197
198	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
199		Elf_Scn *scn;
200		GElf_Shdr shdr;
201		const char *name;
202
203		scn = elf_getscn(lte->elf, i);
204		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
205			error(EXIT_FAILURE, 0,
206			      "Couldn't get section header from \"%s\"",
207			      filename);
208
209		name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
210		if (name == NULL)
211			error(EXIT_FAILURE, 0,
212			      "Couldn't get section header from \"%s\"",
213			      filename);
214
215		if (shdr.sh_type == SHT_SYMTAB) {
216			Elf_Data *data;
217
218			lte->symtab = elf_getdata(scn, NULL);
219			lte->symtab_count = shdr.sh_size / shdr.sh_entsize;
220			if ((lte->symtab == NULL
221			     || elf_getdata(scn, lte->symtab) != NULL)
222			    && opt_x != NULL)
223				error(EXIT_FAILURE, 0,
224				      "Couldn't get .symtab data from \"%s\"",
225				      filename);
226
227			scn = elf_getscn(lte->elf, shdr.sh_link);
228			if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
229				error(EXIT_FAILURE, 0,
230				      "Couldn't get section header from \"%s\"",
231				      filename);
232
233			data = elf_getdata(scn, NULL);
234			if (data == NULL || elf_getdata(scn, data) != NULL
235			    || shdr.sh_size != data->d_size || data->d_off)
236				error(EXIT_FAILURE, 0,
237				      "Couldn't get .strtab data from \"%s\"",
238				      filename);
239
240			lte->strtab = data->d_buf;
241		} else if (shdr.sh_type == SHT_DYNSYM) {
242			Elf_Data *data;
243
244			lte->dynsym = elf_getdata(scn, NULL);
245			lte->dynsym_count = shdr.sh_size / shdr.sh_entsize;
246			if (lte->dynsym == NULL
247			    || elf_getdata(scn, lte->dynsym) != NULL)
248				error(EXIT_FAILURE, 0,
249				      "Couldn't get .dynsym data from \"%s\"",
250				      filename);
251
252			scn = elf_getscn(lte->elf, shdr.sh_link);
253			if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
254				error(EXIT_FAILURE, 0,
255				      "Couldn't get section header from \"%s\"",
256				      filename);
257
258			data = elf_getdata(scn, NULL);
259			if (data == NULL || elf_getdata(scn, data) != NULL
260			    || shdr.sh_size != data->d_size || data->d_off)
261				error(EXIT_FAILURE, 0,
262				      "Couldn't get .dynstr data from \"%s\"",
263				      filename);
264
265			lte->dynstr = data->d_buf;
266		} else if (shdr.sh_type == SHT_DYNAMIC) {
267			Elf_Data *data;
268			size_t j;
269
270			lte->dyn_addr = shdr.sh_addr;
271			lte->dyn_sz = shdr.sh_size;
272
273			data = elf_getdata(scn, NULL);
274			if (data == NULL || elf_getdata(scn, data) != NULL)
275				error(EXIT_FAILURE, 0,
276				      "Couldn't get .dynamic data from \"%s\"",
277				      filename);
278
279			for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
280				GElf_Dyn dyn;
281
282				if (gelf_getdyn(data, j, &dyn) == NULL)
283					error(EXIT_FAILURE, 0,
284					      "Couldn't get .dynamic data from \"%s\"",
285					      filename);
286#ifdef __mips__
287/**
288  MIPS ABI Supplement:
289
290  DT_PLTGOT This member holds the address of the .got section.
291
292  DT_MIPS_SYMTABNO This member holds the number of entries in the
293  .dynsym section.
294
295  DT_MIPS_LOCAL_GOTNO This member holds the number of local global
296  offset table entries.
297
298  DT_MIPS_GOTSYM This member holds the index of the first dyamic
299  symbol table entry that corresponds to an entry in the gobal offset
300  table.
301
302 */
303				if(dyn.d_tag==DT_PLTGOT){
304					lte->pltgot_addr=dyn.d_un.d_ptr;
305				}
306				if(dyn.d_tag==DT_MIPS_LOCAL_GOTNO){
307					lte->mips_local_gotno=dyn.d_un.d_val;
308				}
309				if(dyn.d_tag==DT_MIPS_GOTSYM){
310					lte->mips_gotsym=dyn.d_un.d_val;
311				}
312#endif // __mips__
313				if (dyn.d_tag == DT_JMPREL)
314					relplt_addr = dyn.d_un.d_ptr;
315				else if (dyn.d_tag == DT_PLTRELSZ)
316					relplt_size = dyn.d_un.d_val;
317				else if (dyn.d_tag == DT_PPC_GOT) {
318					ppcgot = dyn.d_un.d_val;
319					debug(1, "ppcgot %#" PRIx64, ppcgot);
320				}
321			}
322		} else if (shdr.sh_type == SHT_HASH) {
323			Elf_Data *data;
324			size_t j;
325
326			lte->hash_type = SHT_HASH;
327
328			data = elf_getdata(scn, NULL);
329			if (data == NULL || elf_getdata(scn, data) != NULL
330			    || data->d_off || data->d_size != shdr.sh_size)
331				error(EXIT_FAILURE, 0,
332				      "Couldn't get .hash data from \"%s\"",
333				      filename);
334
335			if (shdr.sh_entsize == 4) {
336				/* Standard conforming ELF.  */
337				if (data->d_type != ELF_T_WORD)
338					error(EXIT_FAILURE, 0,
339					      "Couldn't get .hash data from \"%s\"",
340					      filename);
341				lte->hash = (Elf32_Word *) data->d_buf;
342			} else if (shdr.sh_entsize == 8) {
343				/* Alpha or s390x.  */
344				Elf32_Word *dst, *src;
345				size_t hash_count = data->d_size / 8;
346
347				lte->hash = (Elf32_Word *)
348				    malloc(hash_count * sizeof(Elf32_Word));
349				if (lte->hash == NULL)
350					error(EXIT_FAILURE, 0,
351					      "Couldn't convert .hash section from \"%s\"",
352					      filename);
353				lte->lte_flags |= LTE_HASH_MALLOCED;
354				dst = lte->hash;
355				src = (Elf32_Word *) data->d_buf;
356				if ((data->d_type == ELF_T_WORD
357				     && __BYTE_ORDER == __BIG_ENDIAN)
358				    || (data->d_type == ELF_T_XWORD
359					&& lte->ehdr.e_ident[EI_DATA] ==
360					ELFDATA2MSB))
361					++src;
362				for (j = 0; j < hash_count; ++j, src += 2)
363					*dst++ = *src;
364			} else
365				error(EXIT_FAILURE, 0,
366				      "Unknown .hash sh_entsize in \"%s\"",
367				      filename);
368		} else if (shdr.sh_type == SHT_GNU_HASH
369			   && lte->hash == NULL) {
370			Elf_Data *data;
371
372			lte->hash_type = SHT_GNU_HASH;
373
374			if (shdr.sh_entsize != 0
375			    && shdr.sh_entsize != 4) {
376				error(EXIT_FAILURE, 0,
377				      ".gnu.hash sh_entsize in \"%s\" "
378					"should be 4, but is %#" PRIx64,
379					filename, shdr.sh_entsize);
380			}
381
382			data = loaddata(scn, &shdr);
383			if (data == NULL)
384				error(EXIT_FAILURE, 0,
385				      "Couldn't get .gnu.hash data from \"%s\"",
386				      filename);
387
388			lte->hash = (Elf32_Word *) data->d_buf;
389		} else if (shdr.sh_type == SHT_PROGBITS
390			   || shdr.sh_type == SHT_NOBITS) {
391			if (strcmp(name, ".plt") == 0) {
392				lte->plt_addr = shdr.sh_addr;
393				lte->plt_size = shdr.sh_size;
394				if (shdr.sh_flags & SHF_EXECINSTR) {
395					lte->lte_flags |= LTE_PLT_EXECUTABLE;
396				}
397				if (lte->ehdr.e_machine == EM_PPC) {
398					plt_data = loaddata(scn, &shdr);
399					if (plt_data == NULL)
400						fprintf(stderr,
401							"Can't load .plt data\n");
402				}
403			}
404#ifdef ARCH_SUPPORTS_OPD
405			else if (strcmp(name, ".opd") == 0) {
406				lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr;
407				lte->opd_size = shdr.sh_size;
408				lte->opd = elf_rawdata(scn, NULL);
409			}
410#endif
411		}
412	}
413
414	if (lte->dynsym == NULL || lte->dynstr == NULL)
415		error(EXIT_FAILURE, 0,
416		      "Couldn't find .dynsym or .dynstr in \"%s\"", filename);
417
418	if (!relplt_addr || !lte->plt_addr) {
419		debug(1, "%s has no PLT relocations", filename);
420		lte->relplt = NULL;
421		lte->relplt_count = 0;
422	} else if (relplt_size == 0) {
423		debug(1, "%s has unknown PLT size", filename);
424		lte->relplt = NULL;
425		lte->relplt_count = 0;
426	} else {
427		if (lte->ehdr.e_machine == EM_PPC) {
428			GElf_Addr glink_vma
429				= get_glink_vma(lte, ppcgot, plt_data);
430
431			assert (relplt_size % 12 == 0);
432			size_t count = relplt_size / 12; // size of RELA entry
433			lte->plt_stub_vma = glink_vma
434				- (GElf_Addr)count * PPC_PLT_STUB_SIZE;
435			debug(1, "stub_vma is %#" PRIx64, lte->plt_stub_vma);
436		}
437
438		for (i = 1; i < lte->ehdr.e_shnum; ++i) {
439			Elf_Scn *scn;
440			GElf_Shdr shdr;
441
442			scn = elf_getscn(lte->elf, i);
443			if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
444				error(EXIT_FAILURE, 0,
445				      "Couldn't get section header from \"%s\"",
446				      filename);
447			if (shdr.sh_addr == relplt_addr
448			    && shdr.sh_size == relplt_size) {
449				lte->relplt = elf_getdata(scn, NULL);
450				lte->relplt_count =
451				    shdr.sh_size / shdr.sh_entsize;
452				if (lte->relplt == NULL
453				    || elf_getdata(scn, lte->relplt) != NULL)
454					error(EXIT_FAILURE, 0,
455					      "Couldn't get .rel*.plt data from \"%s\"",
456					      filename);
457				break;
458			}
459		}
460
461		if (i == lte->ehdr.e_shnum)
462			error(EXIT_FAILURE, 0,
463			      "Couldn't find .rel*.plt section in \"%s\"",
464			      filename);
465
466		debug(1, "%s %zd PLT relocations", filename, lte->relplt_count);
467	}
468	return 0;
469}
470
471void
472do_close_elf(struct ltelf *lte) {
473	debug(DEBUG_FUNCTION, "do_close_elf()");
474	if (lte->lte_flags & LTE_HASH_MALLOCED)
475		free((char *)lte->hash);
476	elf_end(lte->elf);
477	close(lte->fd);
478}
479
480void
481library_symbol_init(struct library_symbol *libsym,
482		    GElf_Addr addr, const char *name,
483		    enum toplt type_of_plt, int is_weak)
484{
485	libsym->needs_init = 0;
486	libsym->is_weak = is_weak;
487	libsym->plt_type = type_of_plt;
488	libsym->name = name;
489	libsym->enter_addr = (void *)(uintptr_t)addr;
490	libsym->next = NULL;
491}
492
493static struct library_symbol *
494create_library_symbol(const char *name, GElf_Addr addr,
495		      enum toplt type_of_plt, int is_weak)
496{
497	size_t namel = strlen(name) + 1;
498	struct library_symbol * libsym = calloc(sizeof(*libsym) + namel, 1);
499	if (libsym == NULL) {
500		perror("create_library_symbol");
501		return NULL;
502	}
503	memcpy(libsym + 1, name, namel);
504	library_symbol_init(libsym, addr,
505			    (char *)(libsym + 1), type_of_plt, is_weak);
506
507	return libsym;
508}
509
510void
511add_library_symbol(GElf_Addr addr, const char *name,
512		   struct library_symbol **library_symbolspp,
513		   enum toplt type_of_plt, int is_weak)
514{
515	debug(DEBUG_FUNCTION, "add_library_symbol()");
516
517	struct library_symbol *s = create_library_symbol(name, addr,
518							 type_of_plt, is_weak);
519	if (s == NULL)
520		error(EXIT_FAILURE, errno, "add_library_symbol failed");
521
522	s->needs_init = 1;
523	s->next = *library_symbolspp;
524	*library_symbolspp = s;
525
526	debug(2, "addr: %p, symbol: \"%s\"", (void *)(uintptr_t) addr, name);
527}
528
529struct library_symbol *
530clone_library_symbol(struct library_symbol *libsym)
531{
532	GElf_Addr addr = (uintptr_t)libsym->enter_addr;
533	struct library_symbol *copy
534		= create_library_symbol(libsym->name, addr,
535					libsym->plt_type, libsym->is_weak);
536	if (copy != NULL)
537		copy->needs_init = libsym->needs_init;
538
539	return copy;
540}
541
542void
543destroy_library_symbol(struct library_symbol * sym)
544{
545	free(sym);
546}
547
548void
549destroy_library_symbol_chain(struct library_symbol * sym)
550{
551	while (sym != NULL) {
552		struct library_symbol * next = sym->next;
553		destroy_library_symbol(sym);
554		sym = next;
555	}
556}
557
558/* stolen from elfutils-0.123 */
559static unsigned long
560private_elf_gnu_hash(const char *name) {
561	unsigned long h = 5381;
562	const unsigned char *string = (const unsigned char *)name;
563	unsigned char c;
564	for (c = *string; c; c = *++string)
565		h = h * 33 + c;
566	return h & 0xffffffff;
567}
568
569static int
570symbol_matches(struct ltelf *lte, size_t lte_i, GElf_Sym *sym,
571	       size_t symidx, const char *name)
572{
573	GElf_Sym tmp_sym;
574	GElf_Sym *tmp;
575
576	tmp = (sym) ? (sym) : (&tmp_sym);
577
578	if (gelf_getsym(lte[lte_i].dynsym, symidx, tmp) == NULL)
579		error(EXIT_FAILURE, 0, "Couldn't get symbol from .dynsym");
580	else {
581		tmp->st_value += lte[lte_i].base_addr;
582		debug(2, "symbol found: %s, %zd, %#" PRIx64,
583		      name, lte_i, tmp->st_value);
584	}
585	return tmp->st_value != 0
586		&& tmp->st_shndx != SHN_UNDEF
587		&& strcmp(name, lte[lte_i].dynstr + tmp->st_name) == 0;
588}
589
590int
591in_load_libraries(const char *name, struct ltelf *lte, size_t count, GElf_Sym *sym) {
592	size_t i;
593	unsigned long hash;
594	unsigned long gnu_hash;
595
596	if (!count)
597		return 1;
598
599#ifdef ELF_HASH_TAKES_CHARP
600	hash = elf_hash(name);
601#else
602	hash = elf_hash((const unsigned char *)name);
603#endif
604	gnu_hash = private_elf_gnu_hash(name);
605
606	for (i = 0; i < count; ++i) {
607		if (lte[i].hash == NULL)
608			continue;
609
610		if (lte[i].hash_type == SHT_GNU_HASH) {
611			Elf32_Word * hashbase = lte[i].hash;
612			Elf32_Word nbuckets = *hashbase++;
613			Elf32_Word symbias = *hashbase++;
614			Elf32_Word bitmask_nwords = *hashbase++;
615			Elf32_Word * buckets;
616			Elf32_Word * chain_zero;
617			Elf32_Word bucket;
618
619			// +1 for skipped `shift'
620			hashbase += lte[i].ehdr.e_ident[EI_CLASS] * bitmask_nwords + 1;
621			buckets = hashbase;
622			hashbase += nbuckets;
623			chain_zero = hashbase - symbias;
624			bucket = buckets[gnu_hash % nbuckets];
625
626			if (bucket != 0) {
627				const Elf32_Word *hasharr = &chain_zero[bucket];
628				do
629					if ((*hasharr & ~1u) == (gnu_hash & ~1u)) {
630						int symidx = hasharr - chain_zero;
631						if (symbol_matches(lte, i,
632								   sym, symidx,
633								   name))
634							return 1;
635					}
636				while ((*hasharr++ & 1u) == 0);
637			}
638		} else {
639			Elf32_Word nbuckets, symndx;
640			Elf32_Word *buckets, *chain;
641			nbuckets = lte[i].hash[0];
642			buckets = &lte[i].hash[2];
643			chain = &lte[i].hash[2 + nbuckets];
644
645			for (symndx = buckets[hash % nbuckets];
646			     symndx != STN_UNDEF; symndx = chain[symndx])
647				if (symbol_matches(lte, i, sym, symndx, name))
648					return 1;
649		}
650	}
651	return 0;
652}
653
654static GElf_Addr
655opd2addr(struct ltelf *lte, GElf_Addr addr) {
656#ifdef ARCH_SUPPORTS_OPD
657	unsigned long base, offset;
658
659	if (!lte->opd)
660		return addr;
661
662	base = (unsigned long)lte->opd->d_buf;
663	offset = (unsigned long)addr - (unsigned long)lte->opd_addr;
664	if (offset > lte->opd_size)
665		error(EXIT_FAILURE, 0, "static plt not in .opd");
666
667	return *(GElf_Addr*)(base + offset);
668#else //!ARCH_SUPPORTS_OPD
669	return addr;
670#endif
671}
672
673struct library_symbol *
674read_elf(Process *proc, GElf_Addr *entryp)
675{
676	struct ltelf lte[MAX_LIBRARIES + 1];
677	size_t i;
678	struct opt_x_t *xptr;
679	struct opt_x_t *opt_x_loc = opt_x;
680	struct library_symbol **lib_tail = NULL;
681	int exit_out = 0;
682	int count = 0;
683
684	debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename);
685
686	memset(lte, 0, sizeof(lte));
687	library_symbols = NULL;
688	library_num = 0;
689	proc->libdl_hooked = 0;
690
691	if (do_init_elf(lte, proc->filename))
692		return NULL;
693
694	memcpy(&main_lte, lte, sizeof(struct ltelf));
695
696	if (opt_p && opt_p->pid > 0) {
697		linkmap_init(proc, lte);
698		proc->libdl_hooked = 1;
699	}
700
701	proc->e_machine = lte->ehdr.e_machine;
702
703	for (i = 0; i < library_num; ++i) {
704		if (do_init_elf(&lte[i + 1], library[i]))
705			error(EXIT_FAILURE, errno, "Can't open \"%s\"",
706			      library[i]);
707	}
708
709	if (!options.no_plt) {
710#ifdef __mips__
711		// MIPS doesn't use the PLT and the GOT entries get changed
712		// on startup.
713		for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){
714			GElf_Sym sym;
715			const char *name;
716			GElf_Addr addr = arch_plt_sym_val(lte, i, 0);
717			if (gelf_getsym(lte->dynsym, i, &sym) == NULL){
718				error(EXIT_FAILURE, 0,
719						"Couldn't get relocation from \"%s\"",
720						proc->filename);
721			}
722			name=lte->dynstr+sym.st_name;
723			if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){
724				debug(2,"sym %s not a function",name);
725				continue;
726			}
727			add_library_symbol(addr, name, &library_symbols, 0,
728					ELF64_ST_BIND(sym.st_info) != 0);
729			if (!lib_tail)
730				lib_tail = &(library_symbols->next);
731		}
732#else
733		for (i = 0; i < lte->relplt_count; ++i) {
734			GElf_Rel rel;
735			GElf_Rela rela;
736			GElf_Sym sym;
737			GElf_Addr addr;
738			void *ret;
739			const char *name;
740
741			if (lte->relplt->d_type == ELF_T_REL) {
742				ret = gelf_getrel(lte->relplt, i, &rel);
743				rela.r_offset = rel.r_offset;
744				rela.r_info = rel.r_info;
745				rela.r_addend = 0;
746			} else
747				ret = gelf_getrela(lte->relplt, i, &rela);
748
749			if (ret == NULL
750					|| ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
751					|| gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
752						&sym) == NULL)
753				error(EXIT_FAILURE, 0,
754						"Couldn't get relocation from \"%s\"",
755						proc->filename);
756
757			name = lte->dynstr + sym.st_name;
758			count = library_num ? library_num+1 : 0;
759
760			if (in_load_libraries(name, lte, count, NULL)) {
761				enum toplt pltt;
762				if (sym.st_value == 0 && lte->plt_stub_vma != 0) {
763					pltt = LS_TOPLT_EXEC;
764					addr = lte->plt_stub_vma + PPC_PLT_STUB_SIZE * i;
765				}
766				else {
767					pltt = PLTS_ARE_EXECUTABLE(lte)
768						?  LS_TOPLT_EXEC : LS_TOPLT_POINT;
769					addr = arch_plt_sym_val(lte, i, &rela);
770				}
771
772				add_library_symbol(addr, name, &library_symbols, pltt,
773						ELF64_ST_BIND(sym.st_info) == STB_WEAK);
774				if (!lib_tail)
775					lib_tail = &(library_symbols->next);
776			}
777		}
778#endif // !__mips__
779	} else {
780		lib_tail = &library_symbols;
781	}
782
783	for (i = 0; i < lte->symtab_count; ++i) {
784		GElf_Sym sym;
785		GElf_Addr addr;
786		const char *name;
787
788		if (gelf_getsym(lte->symtab, i, &sym) == NULL)
789			error(EXIT_FAILURE, 0,
790			      "Couldn't get symbol from \"%s\"",
791			      proc->filename);
792
793		name = lte->strtab + sym.st_name;
794		addr = sym.st_value;
795		if (!addr)
796			continue;
797
798		for (xptr = opt_x_loc; xptr; xptr = xptr->next)
799			if (xptr->name && strcmp(xptr->name, name) == 0) {
800				/* FIXME: Should be able to use &library_symbols as above.  But
801				   when you do, none of the real library symbols cause breaks. */
802				add_library_symbol(opd2addr(lte, addr),
803						   name, lib_tail, LS_TOPLT_NONE, 0);
804				xptr->found = 1;
805				break;
806			}
807	}
808
809	unsigned found_count = 0;
810
811	for (xptr = opt_x_loc; xptr; xptr = xptr->next) {
812		if (xptr->found)
813			continue;
814
815		GElf_Sym sym;
816		GElf_Addr addr;
817		if (in_load_libraries(xptr->name, lte, library_num+1, &sym)) {
818			debug(2, "found symbol %s @ %#" PRIx64 ", adding it.",
819					xptr->name, sym.st_value);
820			addr = sym.st_value;
821			if (ELF32_ST_TYPE (sym.st_info) == STT_FUNC) {
822				add_library_symbol(addr, xptr->name, lib_tail, LS_TOPLT_NONE, 0);
823				xptr->found = 1;
824				found_count++;
825			}
826		}
827		if (found_count == opt_x_cnt){
828			debug(2, "done, found everything: %d\n", found_count);
829			break;
830		}
831	}
832
833	if (lte->ehdr.e_entry != 0) {
834		*entryp = opd2addr(lte, lte->ehdr.e_entry);
835	} else {
836	}
837
838	for (xptr = opt_x_loc; xptr; xptr = xptr->next)
839		if ( ! xptr->found) {
840			char *badthing = "WARNING";
841#ifdef PLT_REINITALISATION_BP
842			if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) {
843				if (lte->ehdr.e_entry) {
844					fprintf (stderr, "WARNING: Using e_ent"
845						 "ry from elf header (%p) for "
846						 "address of \"%s\"\n", (void*)
847						 (long) lte->ehdr.e_entry,
848						 PLTs_initialized_by_here);
849					continue;
850				}
851				badthing = "ERROR";
852				exit_out = 1;
853			}
854#endif
855			fprintf (stderr,
856				 "%s: Couldn't find symbol \"%s\" in file \"%s\" assuming it will be loaded by libdl!"
857				 "\n", badthing, xptr->name, proc->filename);
858		}
859	if (exit_out) {
860		exit (1);
861	}
862
863	for (i = 0; i < library_num + 1; ++i)
864		do_close_elf(&lte[i]);
865
866	return library_symbols;
867}
868