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