ltrace-elf.c revision e67635d6dcecb0f44448a5329d69fd0de74ebaba
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#include "proc.h"
17#include "library.h"
18
19#ifdef PLT_REINITALISATION_BP
20extern char *PLTs_initialized_by_here;
21#endif
22
23#ifndef DT_PPC_GOT
24# define DT_PPC_GOT		(DT_LOPROC + 0)
25#endif
26
27
28#ifndef ARCH_HAVE_LTELF_DATA
29int
30arch_elf_dynamic_tag(struct ltelf *lte, GElf_Dyn dyn)
31{
32	return 0;
33}
34
35int
36arch_elf_init(struct ltelf *lte)
37{
38	return 0;
39}
40#endif
41
42Elf_Data *
43elf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr)
44{
45	Elf_Data *data = elf_getdata(scn, NULL);
46	if (data == NULL || elf_getdata(scn, data) != NULL
47	    || data->d_off || data->d_size != shdr->sh_size)
48		return NULL;
49	return data;
50}
51
52static int
53inside(GElf_Addr addr, GElf_Shdr *shdr)
54{
55	return addr >= shdr->sh_addr
56		&& addr < shdr->sh_addr + shdr->sh_size;
57}
58
59static int
60section_covers(GElf_Addr addr,
61	       Elf_Scn *in_sec, GElf_Shdr *in_shdr,
62	       Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
63{
64	if (inside(addr, in_shdr)) {
65		*tgt_sec = in_sec;
66		*tgt_shdr = *in_shdr;
67		return 1;
68	}
69	return 0;
70}
71
72int
73elf_get_section_covering(struct ltelf *lte, GElf_Addr addr,
74			 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
75{
76	int i;
77	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
78		Elf_Scn *scn;
79		GElf_Shdr shdr;
80
81		scn = elf_getscn(lte->elf, i);
82		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
83			debug(1, "Couldn't read section or header.");
84			return -1;
85		}
86
87		if (section_covers(addr, scn, &shdr, tgt_sec, tgt_shdr))
88			return 0;
89	}
90
91	return -1;
92}
93
94static int
95need_data(Elf_Data *data, size_t offset, size_t size)
96{
97	assert(data != NULL);
98	if (data->d_size < size || offset > data->d_size - size) {
99		debug(1, "Not enough data to read %zd-byte value"
100		      " at offset %zd.", size, offset);
101		return -1;
102	}
103	return 0;
104}
105
106#define DEF_READER(NAME, SIZE)						\
107	int								\
108	NAME(Elf_Data *data, size_t offset, uint##SIZE##_t *retp)	\
109	{								\
110		if (!need_data(data, offset, SIZE / 8) < 0)		\
111			return -1;					\
112									\
113		union {							\
114			uint##SIZE##_t dst;				\
115			char buf[0];					\
116		} u;							\
117		memcpy(u.buf, data->d_buf + offset, sizeof(u.dst));	\
118		*retp = u.dst;						\
119		return 0;						\
120	}
121
122DEF_READER(elf_read_u16, 16)
123DEF_READER(elf_read_u32, 32)
124DEF_READER(elf_read_u64, 64)
125
126#undef DEF_READER
127
128int
129open_elf(struct ltelf *lte, const char *filename)
130{
131	lte->fd = open(filename, O_RDONLY);
132	if (lte->fd == -1)
133		return 1;
134
135	elf_version(EV_CURRENT);
136
137#ifdef HAVE_ELF_C_READ_MMAP
138	lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL);
139#else
140	lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL);
141#endif
142
143	if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF)
144		error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename);
145
146	if (gelf_getehdr(lte->elf, &lte->ehdr) == NULL)
147		error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"",
148		      filename);
149
150	if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN)
151		error(EXIT_FAILURE, 0,
152		      "\"%s\" is not an ELF executable nor shared library",
153		      filename);
154
155	if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
156	     || lte->ehdr.e_machine != LT_ELF_MACHINE)
157#ifdef LT_ELF_MACHINE2
158	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2
159		|| lte->ehdr.e_machine != LT_ELF_MACHINE2)
160#endif
161#ifdef LT_ELF_MACHINE3
162	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3
163		|| lte->ehdr.e_machine != LT_ELF_MACHINE3)
164#endif
165	    )
166		error(EXIT_FAILURE, 0,
167		      "\"%s\" is ELF from incompatible architecture", filename);
168
169	return 0;
170}
171
172static int
173do_init_elf(struct ltelf *lte, const char *filename, GElf_Addr bias)
174{
175	int i;
176	GElf_Addr relplt_addr = 0;
177	GElf_Addr soname_offset = 0;
178
179	debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename);
180	debug(1, "Reading ELF from %s...", filename);
181
182	if (open_elf(lte, filename) < 0)
183		return -1;
184
185	Elf_Data *plt_data = NULL;
186	GElf_Addr ppcgot = 0;
187
188	/* Find out the bias.  For DSOs, this will be just BASE,
189	 * unless the DSO is pre-linked.  For ET_EXEC files, this will
190	 * turn out to be 0.  */
191	{
192		GElf_Phdr phdr;
193		for (i = 0; gelf_getphdr (lte->elf, i, &phdr) != NULL; ++i) {
194			if (phdr.p_type == PT_LOAD) {
195				if (base == 0)
196					base = phdr.p_vaddr;
197				lte->base_addr = base;
198				lte->bias = lte->base_addr - phdr.p_vaddr;
199				fprintf(stderr,
200					" + vaddr=%#lx, base=%#lx, bias=%#lx\n",
201					lte->base_addr, base, lte->bias);
202				break;
203			}
204		}
205	}
206
207	lte->entry_addr = lte->ehdr.e_entry + lte->bias;
208
209	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
210		Elf_Scn *scn;
211		GElf_Shdr shdr;
212		const char *name;
213
214		scn = elf_getscn(lte->elf, i);
215		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
216			error(EXIT_FAILURE, 0,
217			      "Couldn't get section header from \"%s\"",
218			      filename);
219
220		name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
221		if (name == NULL)
222			error(EXIT_FAILURE, 0,
223			      "Couldn't get section header from \"%s\"",
224			      filename);
225
226		if (shdr.sh_type == SHT_SYMTAB) {
227			Elf_Data *data;
228
229			lte->symtab = elf_getdata(scn, NULL);
230			lte->symtab_count = shdr.sh_size / shdr.sh_entsize;
231			if ((lte->symtab == NULL
232			     || elf_getdata(scn, lte->symtab) != NULL)
233			    && opt_x != NULL)
234				error(EXIT_FAILURE, 0,
235				      "Couldn't get .symtab 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 .strtab data from \"%s\"",
249				      filename);
250
251			lte->strtab = data->d_buf;
252		} else if (shdr.sh_type == SHT_DYNSYM) {
253			Elf_Data *data;
254
255			lte->dynsym = elf_getdata(scn, NULL);
256			lte->dynsym_count = shdr.sh_size / shdr.sh_entsize;
257			if (lte->dynsym == NULL
258			    || elf_getdata(scn, lte->dynsym) != NULL)
259				error(EXIT_FAILURE, 0,
260				      "Couldn't get .dynsym data from \"%s\"",
261				      filename);
262
263			scn = elf_getscn(lte->elf, shdr.sh_link);
264			if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
265				error(EXIT_FAILURE, 0,
266				      "Couldn't get section header from \"%s\"",
267				      filename);
268
269			data = elf_getdata(scn, NULL);
270			if (data == NULL || elf_getdata(scn, data) != NULL
271			    || shdr.sh_size != data->d_size || data->d_off)
272				error(EXIT_FAILURE, 0,
273				      "Couldn't get .dynstr data from \"%s\"",
274				      filename);
275
276			lte->dynstr = data->d_buf;
277		} else if (shdr.sh_type == SHT_DYNAMIC) {
278			Elf_Data *data;
279			size_t j;
280
281			lte->dyn_addr = shdr.sh_addr;
282			fprintf(stderr, "dyn_addr = %#lx\n", lte->dyn_addr);
283			extern void *dyn_addr;
284			dyn_addr = (void *)lte->dyn_addr;
285			lte->dyn_sz = shdr.sh_size;
286
287			data = elf_getdata(scn, NULL);
288			if (data == NULL || elf_getdata(scn, data) != NULL)
289				error(EXIT_FAILURE, 0,
290				      "Couldn't get .dynamic data from \"%s\"",
291				      filename);
292
293			for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
294				GElf_Dyn dyn;
295
296				if (gelf_getdyn(data, j, &dyn) == NULL)
297					error(EXIT_FAILURE, 0,
298					      "Couldn't get .dynamic data from \"%s\"",
299					      filename);
300				if (dyn.d_tag == DT_JMPREL)
301					relplt_addr = dyn.d_un.d_ptr;
302				else if (dyn.d_tag == DT_PLTRELSZ)
303					lte->relplt_size = dyn.d_un.d_val;
304				else if (dyn.d_tag == DT_SONAME)
305					soname_offset = dyn.d_un.d_val;
306				else if (arch_elf_dynamic_tag(lte, dyn) < 0)
307					goto backend_fail;
308			}
309		} else if (shdr.sh_type == SHT_PROGBITS
310			   || shdr.sh_type == SHT_NOBITS) {
311			if (strcmp(name, ".plt") == 0) {
312				lte->plt_addr = shdr.sh_addr;
313				lte->plt_size = shdr.sh_size;
314				lte->plt_data = elf_loaddata(scn, &shdr);
315				if (lte->plt_data == NULL)
316					fprintf(stderr,
317						"Can't load .plt data\n");
318				if (shdr.sh_flags & SHF_EXECINSTR)
319					lte->lte_flags |= LTE_PLT_EXECUTABLE;
320			}
321#ifdef ARCH_SUPPORTS_OPD
322			else if (strcmp(name, ".opd") == 0) {
323				lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr;
324				lte->opd_size = shdr.sh_size;
325				lte->opd = elf_rawdata(scn, NULL);
326			}
327#endif
328		}
329	}
330
331	if (lte->dynsym == NULL || lte->dynstr == NULL)
332		error(EXIT_FAILURE, 0,
333		      "Couldn't find .dynsym or .dynstr in \"%s\"", filename);
334
335	if (arch_elf_init(lte) < 0) {
336	backend_fail:
337		fprintf(stderr, "Backend initialization failed.\n");
338		return -1;
339	}
340
341	if (!relplt_addr || !lte->plt_addr) {
342		debug(1, "%s has no PLT relocations", filename);
343		lte->relplt = NULL;
344		lte->relplt_count = 0;
345	} else if (lte->relplt_size == 0) {
346		debug(1, "%s has unknown PLT size", filename);
347		lte->relplt = NULL;
348		lte->relplt_count = 0;
349	} else {
350
351		for (i = 1; i < lte->ehdr.e_shnum; ++i) {
352			Elf_Scn *scn;
353			GElf_Shdr shdr;
354
355			scn = elf_getscn(lte->elf, i);
356			if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
357				error(EXIT_FAILURE, 0,
358				      "Couldn't get section header from \"%s\"",
359				      filename);
360			if (shdr.sh_addr == relplt_addr
361			    && shdr.sh_size == lte->relplt_size) {
362				lte->relplt = elf_getdata(scn, NULL);
363				lte->relplt_count =
364				    shdr.sh_size / shdr.sh_entsize;
365				if (lte->relplt == NULL
366				    || elf_getdata(scn, lte->relplt) != NULL)
367					error(EXIT_FAILURE, 0,
368					      "Couldn't get .rel*.plt data from \"%s\"",
369					      filename);
370				break;
371			}
372		}
373
374		if (i == lte->ehdr.e_shnum)
375			error(EXIT_FAILURE, 0,
376			      "Couldn't find .rel*.plt section in \"%s\"",
377			      filename);
378
379		debug(1, "%s %zd PLT relocations", filename, lte->relplt_count);
380	}
381
382	if (soname_offset != 0)
383		lte->soname = lte->dynstr + soname_offset;
384
385	return 0;
386}
387
388/* XXX temporarily non-static */
389void
390do_close_elf(struct ltelf *lte) {
391	debug(DEBUG_FUNCTION, "do_close_elf()");
392	elf_end(lte->elf);
393	close(lte->fd);
394}
395
396/* XXX non-static for now, as it's not called anywhere.  But we want
397 * this code around.  */
398GElf_Addr
399opd2addr(struct ltelf *lte, GElf_Addr addr) {
400#ifdef ARCH_SUPPORTS_OPD
401	unsigned long base, offset;
402
403	if (!lte->opd)
404		return addr;
405
406	base = (unsigned long)lte->opd->d_buf;
407	offset = (unsigned long)addr - (unsigned long)lte->opd_addr;
408	if (offset > lte->opd_size)
409		error(EXIT_FAILURE, 0, "static plt not in .opd");
410
411	return *(GElf_Addr*)(base + offset);
412#else //!ARCH_SUPPORTS_OPD
413	return addr;
414#endif
415}
416
417struct library *
418ltelf_read_library(const char *filename, GElf_Addr base)
419{
420	 // XXX we leak LTE contents
421	struct ltelf lte = {};
422	if (do_init_elf(&lte, filename, base) < 0)
423		return NULL;
424	proc->e_machine = lte.ehdr.e_machine;
425
426	struct library *lib = malloc(sizeof(*lib));
427	char *soname = NULL;
428	if (lib == NULL) {
429	fail:
430		free(soname);
431		library_destroy(lib);
432		free(lib);
433		lib = NULL;
434		goto done;
435	}
436
437	if (lte.soname != NULL) {
438		soname = strdup(lte.soname);
439		if (soname == NULL)
440			goto fail;
441	}
442
443	library_init(lib, soname, soname != NULL);
444	lib->entry = (target_address_t)lte.entry_addr;
445	lib->base = (target_address_t)lte.base_addr;
446
447	size_t i;
448	for (i = 0; i < lte.relplt_count; ++i) {
449		GElf_Rel rel;
450		GElf_Rela rela;
451		GElf_Sym sym;
452		void *ret;
453
454		if (lte.relplt->d_type == ELF_T_REL) {
455			ret = gelf_getrel(lte.relplt, i, &rel);
456			rela.r_offset = rel.r_offset;
457			rela.r_info = rel.r_info;
458			rela.r_addend = 0;
459		} else {
460			ret = gelf_getrela(lte.relplt, i, &rela);
461		}
462
463		if (ret == NULL
464		    || ELF64_R_SYM(rela.r_info) >= lte.dynsym_count
465		    || gelf_getsym(lte.dynsym, ELF64_R_SYM(rela.r_info),
466				   &sym) == NULL)
467			error(EXIT_FAILURE, 0,
468			      "Couldn't get relocation from \"%s\"",
469			      filename);
470
471		/* We will destroy the ELF object at the end of the
472		 * scope.  We need to copy the name for our purposes.
473		 * XXX consider just keeping the ELF around.  */
474		char *name = strdup(lte.dynstr + sym.st_name);
475		if (name == NULL) {
476		fail2:
477			free(name);
478			goto fail;
479		}
480
481		enum toplt pltt = PLTS_ARE_EXECUTABLE(&lte)
482			?  LS_TOPLT_EXEC : LS_TOPLT_POINT;
483		GElf_Addr addr = arch_plt_sym_val(&lte, i, &rela);
484
485		struct library_symbol *libsym = malloc(sizeof(*libsym));
486		if (libsym == NULL)
487			goto fail2;
488		library_symbol_init(libsym, lib, addr + lte.bias, name, 1, pltt,
489				    ELF64_ST_BIND(sym.st_info) == STB_WEAK);
490		library_add_symbol(lib, libsym);
491	}
492
493done:
494	do_close_elf(&lte);
495	return lib;
496}
497
498struct library *
499ltelf_read_main_binary(struct Process *proc, const char *path)
500{
501	fprintf(stderr, "ltelf_read_main_binary %d %s\n", proc->pid, path);
502	char *fname = pid2name(proc->pid);
503	struct library *lib = ltelf_read_library(fname, 0);
504	library_set_name(lib, path, 0);
505	return lib;
506}
507