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