ltrace-elf.c revision 3268c5aa2704162d3b4a8904d84b1a77807c1557
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, size_t count, GElf_Sym *sym);
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			lte->dyn_addr = shdr.sh_addr;
257			lte->dyn_sz = shdr.sh_size;
258
259			data = elf_getdata(scn, NULL);
260			if (data == NULL || elf_getdata(scn, data) != NULL)
261				error(EXIT_FAILURE, 0,
262				      "Couldn't get .dynamic data from \"%s\"",
263				      filename);
264
265			for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
266				GElf_Dyn dyn;
267
268				if (gelf_getdyn(data, j, &dyn) == NULL)
269					error(EXIT_FAILURE, 0,
270					      "Couldn't get .dynamic data from \"%s\"",
271					      filename);
272#ifdef __mips__
273/**
274  MIPS ABI Supplement:
275
276  DT_PLTGOT This member holds the address of the .got section.
277
278  DT_MIPS_SYMTABNO This member holds the number of entries in the
279  .dynsym section.
280
281  DT_MIPS_LOCAL_GOTNO This member holds the number of local global
282  offset table entries.
283
284  DT_MIPS_GOTSYM This member holds the index of the first dyamic
285  symbol table entry that corresponds to an entry in the gobal offset
286  table.
287
288 */
289				if(dyn.d_tag==DT_PLTGOT){
290					lte->pltgot_addr=dyn.d_un.d_ptr;
291				}
292				if(dyn.d_tag==DT_MIPS_LOCAL_GOTNO){
293					lte->mips_local_gotno=dyn.d_un.d_val;
294				}
295				if(dyn.d_tag==DT_MIPS_GOTSYM){
296					lte->mips_gotsym=dyn.d_un.d_val;
297				}
298#endif // __mips__
299				if (dyn.d_tag == DT_JMPREL)
300					relplt_addr = dyn.d_un.d_ptr;
301				else if (dyn.d_tag == DT_PLTRELSZ)
302					relplt_size = dyn.d_un.d_val;
303				else if (dyn.d_tag == DT_PPC_GOT) {
304					ppcgot = dyn.d_un.d_val;
305					debug(1, "ppcgot %#lx", ppcgot);
306				}
307			}
308		} else if (shdr.sh_type == SHT_HASH) {
309			Elf_Data *data;
310			size_t j;
311
312			lte->hash_type = SHT_HASH;
313
314			data = elf_getdata(scn, NULL);
315			if (data == NULL || elf_getdata(scn, data) != NULL
316			    || data->d_off || data->d_size != shdr.sh_size)
317				error(EXIT_FAILURE, 0,
318				      "Couldn't get .hash data from \"%s\"",
319				      filename);
320
321			if (shdr.sh_entsize == 4) {
322				/* Standard conforming ELF.  */
323				if (data->d_type != ELF_T_WORD)
324					error(EXIT_FAILURE, 0,
325					      "Couldn't get .hash data from \"%s\"",
326					      filename);
327				lte->hash = (Elf32_Word *) data->d_buf;
328			} else if (shdr.sh_entsize == 8) {
329				/* Alpha or s390x.  */
330				Elf32_Word *dst, *src;
331				size_t hash_count = data->d_size / 8;
332
333				lte->hash = (Elf32_Word *)
334				    malloc(hash_count * sizeof(Elf32_Word));
335				if (lte->hash == NULL)
336					error(EXIT_FAILURE, 0,
337					      "Couldn't convert .hash section from \"%s\"",
338					      filename);
339				lte->lte_flags |= LTE_HASH_MALLOCED;
340				dst = lte->hash;
341				src = (Elf32_Word *) data->d_buf;
342				if ((data->d_type == ELF_T_WORD
343				     && __BYTE_ORDER == __BIG_ENDIAN)
344				    || (data->d_type == ELF_T_XWORD
345					&& lte->ehdr.e_ident[EI_DATA] ==
346					ELFDATA2MSB))
347					++src;
348				for (j = 0; j < hash_count; ++j, src += 2)
349					*dst++ = *src;
350			} else
351				error(EXIT_FAILURE, 0,
352				      "Unknown .hash sh_entsize in \"%s\"",
353				      filename);
354		} else if (shdr.sh_type == SHT_GNU_HASH
355			   && lte->hash == NULL) {
356			Elf_Data *data;
357
358			lte->hash_type = SHT_GNU_HASH;
359
360			if (shdr.sh_entsize != 0
361			    && shdr.sh_entsize != 4) {
362				error(EXIT_FAILURE, 0,
363				      ".gnu.hash sh_entsize in \"%s\" should be 4, but is %llu",
364				      filename, shdr.sh_entsize);
365			}
366
367			data = loaddata(scn, &shdr);
368			if (data == NULL)
369				error(EXIT_FAILURE, 0,
370				      "Couldn't get .gnu.hash data from \"%s\"",
371				      filename);
372
373			lte->hash = (Elf32_Word *) data->d_buf;
374		} else if (shdr.sh_type == SHT_PROGBITS
375			   || shdr.sh_type == SHT_NOBITS) {
376			if (strcmp(name, ".plt") == 0) {
377				lte->plt_addr = shdr.sh_addr;
378				lte->plt_size = shdr.sh_size;
379				if (shdr.sh_flags & SHF_EXECINSTR) {
380					lte->lte_flags |= LTE_PLT_EXECUTABLE;
381				}
382				if (lte->ehdr.e_machine == EM_PPC) {
383					plt_data = loaddata(scn, &shdr);
384					if (plt_data == NULL)
385						fprintf(stderr,
386							"Can't load .plt data\n");
387				}
388			}
389#ifdef ARCH_SUPPORTS_OPD
390			else if (strcmp(name, ".opd") == 0) {
391				lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr;
392				lte->opd_size = shdr.sh_size;
393				lte->opd = elf_rawdata(scn, NULL);
394			}
395#endif
396		}
397	}
398
399	if (lte->dynsym == NULL || lte->dynstr == NULL)
400		error(EXIT_FAILURE, 0,
401		      "Couldn't find .dynsym or .dynstr in \"%s\"", filename);
402
403	if (!relplt_addr || !lte->plt_addr) {
404		debug(1, "%s has no PLT relocations", filename);
405		lte->relplt = NULL;
406		lte->relplt_count = 0;
407	} else if (relplt_size == 0) {
408		debug(1, "%s has unknown PLT size", filename);
409		lte->relplt = NULL;
410		lte->relplt_count = 0;
411	} else {
412		if (lte->ehdr.e_machine == EM_PPC) {
413			GElf_Addr glink_vma
414				= get_glink_vma(lte, ppcgot, plt_data);
415
416			assert (relplt_size % 12 == 0);
417			size_t count = relplt_size / 12; // size of RELA entry
418			lte->plt_stub_vma = glink_vma
419				- (GElf_Addr)count * PPC_PLT_STUB_SIZE;
420			debug(1, "stub_vma is %#lx", lte->plt_stub_vma);
421		}
422
423		for (i = 1; i < lte->ehdr.e_shnum; ++i) {
424			Elf_Scn *scn;
425			GElf_Shdr shdr;
426
427			scn = elf_getscn(lte->elf, i);
428			if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
429				error(EXIT_FAILURE, 0,
430				      "Couldn't get section header from \"%s\"",
431				      filename);
432			if (shdr.sh_addr == relplt_addr
433			    && shdr.sh_size == relplt_size) {
434				lte->relplt = elf_getdata(scn, NULL);
435				lte->relplt_count =
436				    shdr.sh_size / shdr.sh_entsize;
437				if (lte->relplt == NULL
438				    || elf_getdata(scn, lte->relplt) != NULL)
439					error(EXIT_FAILURE, 0,
440					      "Couldn't get .rel*.plt data from \"%s\"",
441					      filename);
442				break;
443			}
444		}
445
446		if (i == lte->ehdr.e_shnum)
447			error(EXIT_FAILURE, 0,
448			      "Couldn't find .rel*.plt section in \"%s\"",
449			      filename);
450
451		debug(1, "%s %zd PLT relocations", filename, lte->relplt_count);
452	}
453}
454
455static void
456do_close_elf(struct ltelf *lte) {
457	debug(DEBUG_FUNCTION, "do_close_elf()");
458	if (lte->lte_flags & LTE_HASH_MALLOCED)
459		free((char *)lte->hash);
460	elf_end(lte->elf);
461	close(lte->fd);
462}
463
464static void
465add_library_symbol(GElf_Addr addr, const char *name,
466		   struct library_symbol **library_symbolspp,
467		   enum toplt type_of_plt, int is_weak) {
468	struct library_symbol *s;
469
470	debug(DEBUG_FUNCTION, "add_library_symbol()");
471
472	s = malloc(sizeof(struct library_symbol) + strlen(name) + 1);
473	if (s == NULL)
474		error(EXIT_FAILURE, errno, "add_library_symbol failed");
475
476	s->needs_init = 1;
477	s->is_weak = is_weak;
478	s->plt_type = type_of_plt;
479	s->next = *library_symbolspp;
480	s->enter_addr = (void *)(uintptr_t) addr;
481	s->name = (char *)(s + 1);
482	strcpy(s->name, name);
483	*library_symbolspp = s;
484
485	debug(2, "addr: %p, symbol: \"%s\"", (void *)(uintptr_t) addr, name);
486}
487
488/* stolen from elfutils-0.123 */
489static unsigned long
490private_elf_gnu_hash(const char *name) {
491	unsigned long h = 5381;
492	const unsigned char *string = (const unsigned char *)name;
493	unsigned char c;
494	for (c = *string; c; c = *++string)
495		h = h * 33 + c;
496	return h & 0xffffffff;
497}
498
499static int
500symbol_matches(struct ltelf *lte, size_t lte_i, GElf_Sym *sym,
501	       size_t symidx, const char *name)
502{
503	GElf_Sym tmp_sym;
504	GElf_Sym *tmp;
505
506	tmp = (sym) ? (sym) : (&tmp_sym);
507
508	if (gelf_getsym(lte[lte_i].dynsym, symidx, tmp) == NULL)
509		error(EXIT_FAILURE, 0, "Couldn't get symbol from .dynsym");
510	else {
511		tmp->st_value += lte[lte_i].base_addr;
512		debug(2, "symbol found: %s, %zd, %lx",
513		      name, lte_i, tmp->st_value);
514	}
515	return tmp->st_value != 0
516		&& tmp->st_shndx != SHN_UNDEF
517		&& strcmp(name, lte[lte_i].dynstr + tmp->st_name) == 0;
518}
519
520static int
521in_load_libraries(const char *name, struct ltelf *lte, size_t count, GElf_Sym *sym) {
522	size_t i;
523	unsigned long hash;
524	unsigned long gnu_hash;
525
526	if (!count)
527		return 1;
528
529	hash = elf_hash((const unsigned char *)name);
530	gnu_hash = private_elf_gnu_hash(name);
531
532	for (i = 0; i < count; ++i) {
533		if (lte[i].hash == NULL)
534			continue;
535
536		if (lte[i].hash_type == SHT_GNU_HASH) {
537			Elf32_Word * hashbase = lte[i].hash;
538			Elf32_Word nbuckets = *hashbase++;
539			Elf32_Word symbias = *hashbase++;
540			Elf32_Word bitmask_nwords = *hashbase++;
541			Elf32_Word * buckets;
542			Elf32_Word * chain_zero;
543			Elf32_Word bucket;
544
545			// +1 for skipped `shift'
546			hashbase += lte[i].ehdr.e_ident[EI_CLASS] * bitmask_nwords + 1;
547			buckets = hashbase;
548			hashbase += nbuckets;
549			chain_zero = hashbase - symbias;
550			bucket = buckets[gnu_hash % nbuckets];
551
552			if (bucket != 0) {
553				const Elf32_Word *hasharr = &chain_zero[bucket];
554				do
555					if ((*hasharr & ~1u) == (gnu_hash & ~1u)) {
556						int symidx = hasharr - chain_zero;
557						if (symbol_matches(lte, i,
558								   sym, symidx,
559								   name))
560							return 1;
561					}
562				while ((*hasharr++ & 1u) == 0);
563			}
564		} else {
565			Elf32_Word nbuckets, symndx;
566			Elf32_Word *buckets, *chain;
567			nbuckets = lte[i].hash[0];
568			buckets = &lte[i].hash[2];
569			chain = &lte[i].hash[2 + nbuckets];
570
571			for (symndx = buckets[hash % nbuckets];
572			     symndx != STN_UNDEF; symndx = chain[symndx])
573				if (symbol_matches(lte, i, sym, symndx, name))
574					return 1;
575		}
576	}
577	return 0;
578}
579
580static GElf_Addr
581opd2addr(struct ltelf *lte, GElf_Addr addr) {
582#ifdef ARCH_SUPPORTS_OPD
583	unsigned long base, offset;
584
585	if (!lte->opd)
586		return addr;
587
588	base = (unsigned long)lte->opd->d_buf;
589	offset = (unsigned long)addr - (unsigned long)lte->opd_addr;
590	if (offset > lte->opd_size)
591		error(EXIT_FAILURE, 0, "static plt not in .opd");
592
593	return *(GElf_Addr*)(base + offset);
594#else //!ARCH_SUPPORTS_OPD
595	return addr;
596#endif
597}
598
599struct library_symbol *
600read_elf(Process *proc) {
601	struct library_symbol *library_symbols = NULL;
602	struct ltelf lte[MAX_LIBRARIES + 1];
603	size_t i;
604	struct opt_x_t *xptr;
605	struct library_symbol **lib_tail = NULL;
606	int exit_out = 0;
607	int count = 0;
608
609	debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename);
610
611	elf_version(EV_CURRENT);
612
613	do_init_elf(lte, proc->filename);
614	proc->e_machine = lte->ehdr.e_machine;
615	for (i = 0; i < library_num; ++i)
616		do_init_elf(&lte[i + 1], library[i]);
617
618	if (!options.no_plt) {
619#ifdef __mips__
620		// MIPS doesn't use the PLT and the GOT entries get changed
621		// on startup.
622		proc->need_to_reinitialize_breakpoints = 1;
623		for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){
624			GElf_Sym sym;
625			const char *name;
626			GElf_Addr addr = arch_plt_sym_val(lte, i, 0);
627			if (gelf_getsym(lte->dynsym, i, &sym) == NULL){
628				error(EXIT_FAILURE, 0,
629						"Couldn't get relocation from \"%s\"",
630						proc->filename);
631			}
632			name=lte->dynstr+sym.st_name;
633			if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){
634				debug(2,"sym %s not a function",name);
635				continue;
636			}
637			add_library_symbol(addr, name, &library_symbols, 0,
638					ELF64_ST_BIND(sym.st_info) != 0);
639			if (!lib_tail)
640				lib_tail = &(library_symbols->next);
641		}
642#else
643		for (i = 0; i < lte->relplt_count; ++i) {
644			GElf_Rel rel;
645			GElf_Rela rela;
646			GElf_Sym sym;
647			GElf_Addr addr;
648			void *ret;
649			const char *name;
650
651			if (lte->relplt->d_type == ELF_T_REL) {
652				ret = gelf_getrel(lte->relplt, i, &rel);
653				rela.r_offset = rel.r_offset;
654				rela.r_info = rel.r_info;
655				rela.r_addend = 0;
656			} else
657				ret = gelf_getrela(lte->relplt, i, &rela);
658
659			if (ret == NULL
660					|| ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
661					|| gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
662						&sym) == NULL)
663				error(EXIT_FAILURE, 0,
664						"Couldn't get relocation from \"%s\"",
665						proc->filename);
666
667#ifdef PLT_REINITALISATION_BP
668			if (!sym.st_value && PLTs_initialized_by_here)
669				proc->need_to_reinitialize_breakpoints = 1;
670#endif
671
672			name = lte->dynstr + sym.st_name;
673			count = library_num ? library_num+1 : 0;
674
675			if (in_load_libraries(name, lte, count, NULL)) {
676				enum toplt pltt;
677				if (sym.st_value == 0 && lte->plt_stub_vma != 0) {
678					pltt = LS_TOPLT_EXEC;
679					addr = lte->plt_stub_vma + PPC_PLT_STUB_SIZE * i;
680				}
681				else {
682					pltt = PLTS_ARE_EXECUTABLE(lte)
683						?  LS_TOPLT_EXEC : LS_TOPLT_POINT;
684					addr = arch_plt_sym_val(lte, i, &rela);
685				}
686
687				add_library_symbol(addr, name, &library_symbols, pltt,
688						ELF64_ST_BIND(sym.st_info) == STB_WEAK);
689				if (!lib_tail)
690					lib_tail = &(library_symbols->next);
691			}
692		}
693#endif // !__mips__
694#ifdef PLT_REINITALISATION_BP
695		struct opt_x_t *main_cheat;
696
697		if (proc->need_to_reinitialize_breakpoints) {
698			/* Add "PLTs_initialized_by_here" to opt_x list, if not
699				 already there. */
700			main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t));
701			if (main_cheat == NULL)
702				error(EXIT_FAILURE, 0, "Couldn't allocate memory");
703			main_cheat->next = opt_x;
704			main_cheat->found = 0;
705			main_cheat->name = PLTs_initialized_by_here;
706
707			for (xptr = opt_x; xptr; xptr = xptr->next)
708				if (strcmp(xptr->name, PLTs_initialized_by_here) == 0
709						&& main_cheat) {
710					free(main_cheat);
711					main_cheat = NULL;
712					break;
713				}
714			if (main_cheat)
715				opt_x = main_cheat;
716		}
717#endif
718	} else {
719		lib_tail = &library_symbols;
720	}
721
722	for (i = 0; i < lte->symtab_count; ++i) {
723		GElf_Sym sym;
724		GElf_Addr addr;
725		const char *name;
726
727		if (gelf_getsym(lte->symtab, i, &sym) == NULL)
728			error(EXIT_FAILURE, 0,
729			      "Couldn't get symbol from \"%s\"",
730			      proc->filename);
731
732		name = lte->strtab + sym.st_name;
733		addr = sym.st_value;
734		if (!addr)
735			continue;
736
737		for (xptr = opt_x; xptr; xptr = xptr->next)
738			if (xptr->name && strcmp(xptr->name, name) == 0) {
739				/* FIXME: Should be able to use &library_symbols as above.  But
740				   when you do, none of the real library symbols cause breaks. */
741				add_library_symbol(opd2addr(lte, addr),
742						   name, lib_tail, LS_TOPLT_NONE, 0);
743				xptr->found = 1;
744				break;
745			}
746	}
747	for (xptr = opt_x; xptr; xptr = xptr->next)
748		if ( ! xptr->found) {
749			char *badthing = "WARNING";
750#ifdef PLT_REINITALISATION_BP
751			if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) {
752				if (lte->ehdr.e_entry) {
753					add_library_symbol (
754						opd2addr (lte, lte->ehdr.e_entry),
755						PLTs_initialized_by_here,
756						lib_tail, 1, 0);
757					fprintf (stderr, "WARNING: Using e_ent"
758						 "ry from elf header (%p) for "
759						 "address of \"%s\"\n", (void*)
760						 (long) lte->ehdr.e_entry,
761						 PLTs_initialized_by_here);
762					continue;
763				}
764				badthing = "ERROR";
765				exit_out = 1;
766			}
767#endif
768			fprintf (stderr,
769				 "%s: Couldn't find symbol \"%s\" in file \"%s"
770			         "\"\n", badthing, xptr->name, proc->filename);
771		}
772	if (exit_out) {
773		exit (1);
774	}
775
776	for (i = 0; i < library_num + 1; ++i)
777		do_close_elf(&lte[i]);
778
779	return library_symbols;
780}
781