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