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