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