Example #1
0
enum plt_status
arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
                       const char *a_name, GElf_Rela *rela, size_t ndx,
                       struct library_symbol **ret)
{
	char *name = NULL;
	int sym_index = ndx + lte->arch.mips_gotsym;

	struct library_symbol *libsym = malloc(sizeof(*libsym));
	if (libsym == NULL)
		return plt_fail;

	GElf_Addr addr = arch_plt_sym_val(lte, sym_index, 0);

	name = strdup(a_name);
	if (name == NULL) {
		fprintf(stderr, "%s: failed %s(%#llx): %s\n", __func__,
			name, addr, strerror(errno));
		goto fail;
	}

	/* XXX The double cast should be removed when
	 * arch_addr_t becomes integral type.  */
	if (library_symbol_init(libsym,
				(arch_addr_t) (uintptr_t) addr,
				name, 1, LS_TOPLT_EXEC) < 0) {
		fprintf(stderr, "%s: failed %s : %llx\n", __func__, name, addr);
		goto fail;
	}

	arch_addr_t bp_addr = sym2addr(proc, libsym);
	/* XXX This cast should be removed when
	 * arch_addr_t becomes integral type.  keywords: double cast. */
	libsym->arch.stub_addr = (uintptr_t) bp_addr;

	if (bp_addr == 0) {
		/* Function pointers without PLT entries.  */
		libsym->plt_type = LS_TOPLT_NONE;
		libsym->arch.gotonly = 1;
		libsym->arch.type = MIPS_PLT_UNRESOLVED;

		/* Delay breakpoint activation until the symbol gets
		 * resolved.  */
		libsym->delayed = 1;
	} else if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
		libsym->arch.pltalways = 1;
	}

	*ret = libsym;
	return plt_ok;

fail:
	free(name);
	free(libsym);
	return plt_fail;
}
Example #2
0
struct library_symbol *
read_elf(Process *proc) {
	struct ltelf lte[MAX_LIBRARIES + 1];
	size_t i;
	struct opt_x_t *xptr;
	struct opt_x_t *opt_x_loc = opt_x;
	struct library_symbol **lib_tail = NULL;
	int exit_out = 0;
	int count = 0;

	debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename);

	memset(lte, 0, sizeof(lte));
	library_symbols = NULL;
	library_num = 0;
	proc->libdl_hooked = 0;

	if (do_init_elf(lte, proc->filename))
		return NULL;

	memcpy(&main_lte, lte, sizeof(struct ltelf));

	if (opt_p && opt_p->pid > 0) {
		linkmap_init(proc, lte);
		proc->libdl_hooked = 1;
	}

	proc->e_machine = lte->ehdr.e_machine;

	for (i = 0; i < library_num; ++i) {
		if (do_init_elf(&lte[i + 1], library[i]))
			error(EXIT_FAILURE, errno, "Can't open \"%s\"",
			      library[i]);
	}

	if (!options.no_plt) {
#ifdef __mips__
		// MIPS doesn't use the PLT and the GOT entries get changed
		// on startup.
		proc->need_to_reinitialize_breakpoints = 1;
		for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){
			GElf_Sym sym;
			const char *name;
			GElf_Addr addr = arch_plt_sym_val(lte, i, 0);
			if (gelf_getsym(lte->dynsym, i, &sym) == NULL){
				error(EXIT_FAILURE, 0,
						"Couldn't get relocation from \"%s\"",
						proc->filename);
			}
			name=lte->dynstr+sym.st_name;
			if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){
				debug(2,"sym %s not a function",name);
				continue;
			}
			add_library_symbol(addr, name, &library_symbols, 0,
					ELF64_ST_BIND(sym.st_info) != 0);
			if (!lib_tail)
				lib_tail = &(library_symbols->next);
		}
#else
		for (i = 0; i < lte->relplt_count; ++i) {
			GElf_Rel rel;
			GElf_Rela rela;
			GElf_Sym sym;
			GElf_Addr addr;
			void *ret;
			const char *name;

			if (lte->relplt->d_type == ELF_T_REL) {
				ret = gelf_getrel(lte->relplt, i, &rel);
				rela.r_offset = rel.r_offset;
				rela.r_info = rel.r_info;
				rela.r_addend = 0;
			} else
				ret = gelf_getrela(lte->relplt, i, &rela);

			if (ret == NULL
					|| ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
					|| gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
						&sym) == NULL)
				error(EXIT_FAILURE, 0,
						"Couldn't get relocation from \"%s\"",
						proc->filename);

#ifdef PLT_REINITALISATION_BP
			if (!sym.st_value && PLTs_initialized_by_here)
				proc->need_to_reinitialize_breakpoints = 1;
#endif

			name = lte->dynstr + sym.st_name;
			count = library_num ? library_num+1 : 0;

			if (in_load_libraries(name, lte, count, NULL)) {
				enum toplt pltt;
				if (sym.st_value == 0 && lte->plt_stub_vma != 0) {
					pltt = LS_TOPLT_EXEC;
					addr = lte->plt_stub_vma + PPC_PLT_STUB_SIZE * i;
				}
				else {
					pltt = PLTS_ARE_EXECUTABLE(lte)
						?  LS_TOPLT_EXEC : LS_TOPLT_POINT;
					addr = arch_plt_sym_val(lte, i, &rela);
				}

				add_library_symbol(addr, name, &library_symbols, pltt,
						ELF64_ST_BIND(sym.st_info) == STB_WEAK);
				if (!lib_tail)
					lib_tail = &(library_symbols->next);
			}
		}
#endif // !__mips__
#ifdef PLT_REINITALISATION_BP
		struct opt_x_t *main_cheat;

		if (proc->need_to_reinitialize_breakpoints) {
			/* Add "PLTs_initialized_by_here" to opt_x list, if not
				 already there. */
			main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t));
			if (main_cheat == NULL)
				error(EXIT_FAILURE, 0, "Couldn't allocate memory");
			main_cheat->next = opt_x_loc;
			main_cheat->found = 0;
			main_cheat->name = PLTs_initialized_by_here;

			for (xptr = opt_x_loc; xptr; xptr = xptr->next)
				if (strcmp(xptr->name, PLTs_initialized_by_here) == 0
						&& main_cheat) {
					free(main_cheat);
					main_cheat = NULL;
					break;
				}
			if (main_cheat)
				opt_x_loc = main_cheat;
		}
#endif
	} else {
		lib_tail = &library_symbols;
	}

	for (i = 0; i < lte->symtab_count; ++i) {
		GElf_Sym sym;
		GElf_Addr addr;
		const char *name;

		if (gelf_getsym(lte->symtab, i, &sym) == NULL)
			error(EXIT_FAILURE, 0,
			      "Couldn't get symbol from \"%s\"",
			      proc->filename);

		name = lte->strtab + sym.st_name;
		addr = sym.st_value;
		if (!addr)
			continue;

		for (xptr = opt_x_loc; xptr; xptr = xptr->next)
			if (xptr->name && strcmp(xptr->name, name) == 0) {
				/* FIXME: Should be able to use &library_symbols as above.  But
				   when you do, none of the real library symbols cause breaks. */
				add_library_symbol(opd2addr(lte, addr),
						   name, lib_tail, LS_TOPLT_NONE, 0);
				xptr->found = 1;
				break;
			}
	}

	unsigned found_count = 0;

	for (xptr = opt_x_loc; xptr; xptr = xptr->next) {
		if (xptr->found)
			continue;

		GElf_Sym sym;
		GElf_Addr addr;
		if (in_load_libraries(xptr->name, lte, library_num+1, &sym)) {
			debug(2, "found symbol %s @ %#" PRIx64 ", adding it.",
					xptr->name, sym.st_value);
			addr = sym.st_value;
			if (ELF32_ST_TYPE (sym.st_info) == STT_FUNC) {
				add_library_symbol(addr, xptr->name, lib_tail, LS_TOPLT_NONE, 0);
				xptr->found = 1;
				found_count++;
			}
		}
		if (found_count == opt_x_cnt){
			debug(2, "done, found everything: %d\n", found_count);
			break;
		}
	}

	for (xptr = opt_x_loc; xptr; xptr = xptr->next)
		if ( ! xptr->found) {
			char *badthing = "WARNING";
#ifdef PLT_REINITALISATION_BP
			if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) {
				if (lte->ehdr.e_entry) {
					add_library_symbol (
						opd2addr (lte, lte->ehdr.e_entry),
						PLTs_initialized_by_here,
						lib_tail, 1, 0);
					fprintf (stderr, "WARNING: Using e_ent"
						 "ry from elf header (%p) for "
						 "address of \"%s\"\n", (void*)
						 (long) lte->ehdr.e_entry,
						 PLTs_initialized_by_here);
					continue;
				}
				badthing = "ERROR";
				exit_out = 1;
			}
#endif
			fprintf (stderr,
				 "%s: Couldn't find symbol \"%s\" in file \"%s\" assuming it will be loaded by libdl!"
				 "\n", badthing, xptr->name, proc->filename);
		}
	if (exit_out) {
		exit (1);
	}

	for (i = 0; i < library_num + 1; ++i)
		do_close_elf(&lte[i]);

	return library_symbols;
}