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