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