ltrace-elf.c revision 87f4f58320226cd20d317f488c7e6a92a3efa2dd
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			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
500in_load_libraries(const char *name, struct ltelf *lte) {
501	size_t i;
502	unsigned long hash;
503	unsigned long gnu_hash;
504
505	if (!library_num)
506		return 1;
507
508	hash = elf_hash((const unsigned char *)name);
509	gnu_hash = private_elf_gnu_hash(name);
510	for (i = 1; i <= library_num; ++i) {
511		if (lte[i].hash == NULL)
512			continue;
513
514		if (lte[i].hash_type == SHT_GNU_HASH) {
515			Elf32_Word * hashbase = lte[i].hash;
516			Elf32_Word nbuckets = *hashbase++;
517			Elf32_Word symbias = *hashbase++;
518			Elf32_Word bitmask_nwords = *hashbase++;
519			Elf32_Word * buckets;
520			Elf32_Word * chain_zero;
521			Elf32_Word bucket;
522
523			// +1 for skipped `shift'
524			hashbase += lte[i].ehdr.e_ident[EI_CLASS] * bitmask_nwords + 1;
525			buckets = hashbase;
526			hashbase += nbuckets;
527			chain_zero = hashbase - symbias;
528			bucket = buckets[gnu_hash % nbuckets];
529
530			if (bucket != 0) {
531				const Elf32_Word *hasharr = &chain_zero[bucket];
532				do
533					if ((*hasharr & ~1u) == (gnu_hash & ~1u)) {
534						int symidx = hasharr - chain_zero;
535						GElf_Sym sym;
536
537						if (gelf_getsym(lte[i].dynsym, symidx, &sym) == NULL)
538							error(EXIT_FAILURE, 0,
539							      "Couldn't get symbol from .dynsym");
540
541						if (sym.st_value != 0
542						    && sym.st_shndx != SHN_UNDEF
543						    && strcmp(name, lte[i].dynstr + sym.st_name) == 0)
544							return 1;
545					}
546				while ((*hasharr++ & 1u) == 0);
547			}
548		} else {
549			Elf32_Word nbuckets, symndx;
550			Elf32_Word *buckets, *chain;
551			nbuckets = lte[i].hash[0];
552			buckets = &lte[i].hash[2];
553			chain = &lte[i].hash[2 + nbuckets];
554
555			for (symndx = buckets[hash % nbuckets];
556			     symndx != STN_UNDEF; symndx = chain[symndx]) {
557				GElf_Sym sym;
558
559				if (gelf_getsym(lte[i].dynsym, symndx, &sym) == NULL)
560					error(EXIT_FAILURE, 0,
561					      "Couldn't get symbol from .dynsym");
562
563				if (sym.st_value != 0
564				    && sym.st_shndx != SHN_UNDEF
565				    && strcmp(name, lte[i].dynstr + sym.st_name) == 0)
566					return 1;
567			}
568		}
569	}
570	return 0;
571}
572
573static GElf_Addr
574opd2addr(struct ltelf *lte, GElf_Addr addr) {
575#ifdef ARCH_SUPPORTS_OPD
576	unsigned long base, offset;
577
578	if (!lte->opd)
579		return addr;
580
581	base = (unsigned long)lte->opd->d_buf;
582	offset = (unsigned long)addr - (unsigned long)lte->opd_addr;
583	if (offset > lte->opd_size)
584		error(EXIT_FAILURE, 0, "static plt not in .opd");
585
586	return *(GElf_Addr*)(base + offset);
587#else //!ARCH_SUPPORTS_OPD
588	return addr;
589#endif
590}
591
592struct library_symbol *
593read_elf(Process *proc) {
594	struct library_symbol *library_symbols = NULL;
595	struct ltelf lte[MAX_LIBRARIES + 1];
596	size_t i;
597	struct opt_x_t *xptr;
598	struct library_symbol **lib_tail = NULL;
599	int exit_out = 0;
600
601	debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename);
602
603	elf_version(EV_CURRENT);
604
605	do_init_elf(lte, proc->filename);
606	proc->e_machine = lte->ehdr.e_machine;
607	for (i = 0; i < library_num; ++i)
608		do_init_elf(&lte[i + 1], library[i]);
609
610	if (!options.no_plt) {
611#ifdef __mips__
612		// MIPS doesn't use the PLT and the GOT entries get changed
613		// on startup.
614		proc->need_to_reinitialize_breakpoints = 1;
615		for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){
616			GElf_Sym sym;
617			const char *name;
618			GElf_Addr addr = arch_plt_sym_val(lte, i, 0);
619			if (gelf_getsym(lte->dynsym, i, &sym) == NULL){
620				error(EXIT_FAILURE, 0,
621						"Couldn't get relocation from \"%s\"",
622						proc->filename);
623			}
624			name=lte->dynstr+sym.st_name;
625			if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){
626				debug(2,"sym %s not a function",name);
627				continue;
628			}
629			add_library_symbol(addr, name, &library_symbols, 0,
630					ELF64_ST_BIND(sym.st_info) != 0);
631			if (!lib_tail)
632				lib_tail = &(library_symbols->next);
633		}
634#else
635		for (i = 0; i < lte->relplt_count; ++i) {
636			GElf_Rel rel;
637			GElf_Rela rela;
638			GElf_Sym sym;
639			GElf_Addr addr;
640			void *ret;
641			const char *name;
642
643			if (lte->relplt->d_type == ELF_T_REL) {
644				ret = gelf_getrel(lte->relplt, i, &rel);
645				rela.r_offset = rel.r_offset;
646				rela.r_info = rel.r_info;
647				rela.r_addend = 0;
648			} else
649				ret = gelf_getrela(lte->relplt, i, &rela);
650
651			if (ret == NULL
652					|| ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
653					|| gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
654						&sym) == NULL)
655				error(EXIT_FAILURE, 0,
656						"Couldn't get relocation from \"%s\"",
657						proc->filename);
658
659#ifdef PLT_REINITALISATION_BP
660			if (!sym.st_value && PLTs_initialized_by_here)
661				proc->need_to_reinitialize_breakpoints = 1;
662#endif
663
664		name = lte->dynstr + sym.st_name;
665		if (in_load_libraries(name, lte)) {
666			enum toplt pltt;
667			if (sym.st_value == 0 && lte->plt_stub_vma != 0) {
668				pltt = LS_TOPLT_EXEC;
669				addr = lte->plt_stub_vma + PPC_PLT_STUB_SIZE * i;
670			}
671			else {
672				pltt = PLTS_ARE_EXECUTABLE(lte)
673					?  LS_TOPLT_EXEC : LS_TOPLT_POINT;
674				addr = arch_plt_sym_val(lte, i, &rela);
675			}
676
677			add_library_symbol(addr, name, &library_symbols, pltt,
678					   ELF64_ST_BIND(sym.st_info) == STB_WEAK);
679			if (!lib_tail)
680				lib_tail = &(library_symbols->next);
681			}
682		}
683#endif // !__mips__
684#ifdef PLT_REINITALISATION_BP
685		struct opt_x_t *main_cheat;
686
687		if (proc->need_to_reinitialize_breakpoints) {
688			/* Add "PLTs_initialized_by_here" to opt_x list, if not
689				 already there. */
690			main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t));
691			if (main_cheat == NULL)
692				error(EXIT_FAILURE, 0, "Couldn't allocate memory");
693			main_cheat->next = opt_x;
694			main_cheat->found = 0;
695			main_cheat->name = PLTs_initialized_by_here;
696
697			for (xptr = opt_x; xptr; xptr = xptr->next)
698				if (strcmp(xptr->name, PLTs_initialized_by_here) == 0
699						&& main_cheat) {
700					free(main_cheat);
701					main_cheat = NULL;
702					break;
703				}
704			if (main_cheat)
705				opt_x = main_cheat;
706		}
707#endif
708	} else {
709		lib_tail = &library_symbols;
710	}
711
712	for (i = 0; i < lte->symtab_count; ++i) {
713		GElf_Sym sym;
714		GElf_Addr addr;
715		const char *name;
716
717		if (gelf_getsym(lte->symtab, i, &sym) == NULL)
718			error(EXIT_FAILURE, 0,
719			      "Couldn't get symbol from \"%s\"",
720			      proc->filename);
721
722		name = lte->strtab + sym.st_name;
723		addr = sym.st_value;
724		if (!addr)
725			continue;
726
727		for (xptr = opt_x; xptr; xptr = xptr->next)
728			if (xptr->name && strcmp(xptr->name, name) == 0) {
729				/* FIXME: Should be able to use &library_symbols as above.  But
730				   when you do, none of the real library symbols cause breaks. */
731				add_library_symbol(opd2addr(lte, addr),
732						   name, lib_tail, LS_TOPLT_NONE, 0);
733				xptr->found = 1;
734				break;
735			}
736	}
737	for (xptr = opt_x; xptr; xptr = xptr->next)
738		if ( ! xptr->found) {
739			char *badthing = "WARNING";
740#ifdef PLT_REINITALISATION_BP
741			if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) {
742				if (lte->ehdr.e_entry) {
743					add_library_symbol (
744						opd2addr (lte, lte->ehdr.e_entry),
745						PLTs_initialized_by_here,
746						lib_tail, 1, 0);
747					fprintf (stderr, "WARNING: Using e_ent"
748						 "ry from elf header (%p) for "
749						 "address of \"%s\"\n", (void*)
750						 (long) lte->ehdr.e_entry,
751						 PLTs_initialized_by_here);
752					continue;
753				}
754				badthing = "ERROR";
755				exit_out = 1;
756			}
757#endif
758			fprintf (stderr,
759				 "%s: Couldn't find symbol \"%s\" in file \"%s"
760			         "\"\n", badthing, xptr->name, proc->filename);
761		}
762	if (exit_out) {
763		exit (1);
764	}
765
766	for (i = 0; i < library_num + 1; ++i)
767		do_close_elf(&lte[i]);
768
769	return library_symbols;
770}
771