Ejemplo n.º 1
0
Archivo: value.c Proyecto: 5py/ltrace
int
value_reify(struct value *val, struct value_dict *arguments)
{
	if (val->where != VAL_LOC_INFERIOR)
		return 0;
	assert(val->inferior != NULL);

	size_t size = value_size(val, arguments);
	if (size == (size_t)-1)
		return -1;

	void *data;
	enum value_location_t nloc;
	if (size <= sizeof(val->u.value)) {
		data = &val->u.value;
		nloc = VAL_LOC_WORD;
	} else {
		data = malloc(size);
		if (data == NULL)
			return -1;
		nloc = VAL_LOC_COPY;
	}

	if (umovebytes(val->inferior, val->u.inf_address, data, size) < size) {
		if (nloc == VAL_LOC_COPY)
			free(data);
		return -1;
	}

	val->where = nloc;
	if (nloc == VAL_LOC_COPY)
		val->u.address = data;

	return 0;
}
Ejemplo n.º 2
0
static int
find_dynamic_entry_addr(Process *proc, void *pvAddr, int d_tag, void **addr) {
	int i = 0, done = 0;
	ElfW(Dyn) entry;

	debug(DEBUG_FUNCTION, "find_dynamic_entry()");

	if (addr ==	NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) {
		return -1;
	}

	while ((!done) && (i < ELF_MAX_SEGMENTS) &&
		(sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) &&
		(entry.d_tag != DT_NULL)) {
		if (entry.d_tag == d_tag) {
			done = 1;
			*addr = (void *)entry.d_un.d_val;
		}
		pvAddr += sizeof(entry);
		i++;
	}

	if (done) {
		debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag);
		return 0;
	}
	else {
		debug(2, "Couldn't address for dtag!\n");
		return -1;
	}
}
Ejemplo n.º 3
0
static int
fetch_rd64(struct Process *proc, arch_addr_t addr,
	   struct lt_r_debug_64 *ret)
{
	if (umovebytes(proc, addr, ret, sizeof(*ret)) != sizeof(*ret))
		return -1;
	return 0;
}
Ejemplo n.º 4
0
static int
fetch_lm64(struct Process *proc, arch_addr_t addr,
	   struct lt_link_map_64 *ret)
{
	if (umovebytes(proc, addr, ret, sizeof(*ret)) != sizeof(*ret))
		return -1;
	return 0;
}
Ejemplo n.º 5
0
static int
fetch_dyn64(struct Process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
{
	if (umovebytes(proc, *addr, ret, sizeof(*ret)) != sizeof(*ret))
		return -1;
	*addr += sizeof(*ret);
	return 0;
}
Ejemplo n.º 6
0
static void
crawl_linkmap(Process *proc, struct r_debug *dbg, void (*callback)(void *), struct cb_data *data) {
	struct link_map rlm;
	char lib_name[BUFSIZ];
	struct link_map *lm = NULL;

	debug (DEBUG_FUNCTION, "crawl_linkmap()");

	if (!dbg || !dbg->r_map) {
		debug(2, "Debug structure or it's linkmap are NULL!");
		return;
	}

	lm = dbg->r_map;

	while (lm) {
		if (umovebytes(proc, lm, &rlm, sizeof(rlm)) != sizeof(rlm)) {
			debug(2, "Unable to read link map\n");
			return;
		}

		lm = rlm.l_next;
		if (rlm.l_name == NULL) {
			debug(2, "Invalid library name referenced in dynamic linker map\n");
			return;
		}

		umovebytes(proc, rlm.l_name, lib_name, sizeof(lib_name));

		if (lib_name[0] == '\0') {
			debug(2, "Library name is an empty string");
			continue;
		}

		if (callback) {
			debug(2, "Dispatching callback for: %s, "
					"Loaded at 0x%" PRI_ELF_ADDR "\n",
					lib_name, rlm.l_addr);
			data->addr = rlm.l_addr;
			data->lib_name = lib_name;
			callback(data);
		}
	}
	return;
}
Ejemplo n.º 7
0
static int
fetch_dyn32(struct Process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
{
	Elf32_Dyn dyn;
	if (umovebytes(proc, *addr, &dyn, sizeof(dyn)) != sizeof(dyn))
		return -1;

	*addr += sizeof(dyn);
	ret->d_tag = dyn.d_tag;
	ret->d_un.d_val = dyn.d_un.d_val;

	return 0;
}
Ejemplo n.º 8
0
static int
fetch_rd32(struct Process *proc, arch_addr_t addr,
	   struct lt_r_debug_64 *ret)
{
	struct lt_r_debug_32 rd;
	if (umovebytes(proc, addr, &rd, sizeof(rd)) != sizeof(rd))
		return -1;

	ret->r_version = rd.r_version;
	ret->r_map = rd.r_map;
	ret->r_brk = rd.r_brk;
	ret->r_state = rd.r_state;
	ret->r_ldbase = rd.r_ldbase;

	return 0;
}
Ejemplo n.º 9
0
static int
fetch_lm32(struct Process *proc, arch_addr_t addr,
	   struct lt_link_map_64 *ret)
{
	struct lt_link_map_32 lm;
	if (umovebytes(proc, addr, &lm, sizeof(lm)) != sizeof(lm))
		return -1;

	ret->l_addr = lm.l_addr;
	ret->l_name = lm.l_name;
	ret->l_ld = lm.l_ld;
	ret->l_next = lm.l_next;
	ret->l_prev = lm.l_prev;

	return 0;
}
Ejemplo n.º 10
0
int
arch_find_dl_debug(struct Process *proc, arch_addr_t dyn_addr,
		   arch_addr_t *ret)
{
	arch_addr_t rld_addr;
	int r;

	/* MIPS puts the address of the r_debug structure into the
	 * DT_MIPS_RLD_MAP entry instead of into the DT_DEBUG entry.  */
	r = proc_find_dynamic_entry_addr(proc, dyn_addr,
					 DT_MIPS_RLD_MAP, &rld_addr);
	if (r == 0) {
		if (umovebytes(proc, rld_addr,
			       ret, sizeof *ret) != sizeof *ret) {
			r = -1;
		}
	}
	return r;
}
Ejemplo n.º 11
0
static struct r_debug *
load_debug_struct(Process *proc) {
	struct r_debug *rdbg = NULL;

	debug(DEBUG_FUNCTION, "load_debug_struct");

	rdbg = malloc(sizeof(*rdbg));
	if (!rdbg) {
		return NULL;
	}

	if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) {
		debug(2, "This process does not have a debug structure!\n");
		free(rdbg);
		return NULL;
	}

	return rdbg;
}
Ejemplo n.º 12
0
static void
crawl_linkmap(struct Process *proc, struct lt_r_debug_64 *dbg)
{
	debug (DEBUG_FUNCTION, "crawl_linkmap()");

	if (!dbg || !dbg->r_map) {
		debug(2, "Debug structure or it's linkmap are NULL!");
		return;
	}

	/* XXX The double cast should be removed when
	 * arch_addr_t becomes integral type.  */
	arch_addr_t addr = (arch_addr_t)(uintptr_t)dbg->r_map;

	while (addr != 0) {
		struct lt_link_map_64 rlm = {};
		if (lm_fetcher(proc)(proc, addr, &rlm) < 0) {
			debug(2, "Unable to read link map");
			return;
		}

		arch_addr_t key = addr;
		/* XXX The double cast should be removed when
		 * arch_addr_t becomes integral type.  */
		addr = (arch_addr_t)(uintptr_t)rlm.l_next;
		if (rlm.l_name == 0) {
			debug(2, "Name of mapped library is NULL");
			return;
		}

		char lib_name[BUFSIZ];
		/* XXX The double cast should be removed when
		 * arch_addr_t becomes integral type.  */
		umovebytes(proc, (arch_addr_t)(uintptr_t)rlm.l_name,
			   lib_name, sizeof(lib_name));

		/* Library name can be an empty string, in which case
		 * the entry represents either the main binary, or a
		 * VDSO.  Unfortunately we can't rely on that, as in
		 * recent glibc, that entry is initialized to VDSO
		 * SONAME.
		 *
		 * It's not clear how to detect VDSO in this case.  We
		 * can't assume that l_name of real DSOs will be
		 * either absolute or relative (for LD_LIBRARY_PATH=:
		 * it will be neither).  We can't compare l_addr with
		 * AT_SYSINFO_EHDR either, as l_addr is bias (which
		 * also means it's not unique, and therefore useless
		 * for this).  We could load VDSO from process image
		 * and at least compare actual SONAMEs.  For now, this
		 * kludge is about the best that we can do.  */
		if (*lib_name == 0
		    || strcmp(lib_name, "linux-vdso.so.1") == 0
		    || strcmp(lib_name, "linux-gate.so.1") == 0
		    || strcmp(lib_name, "linux-vdso32.so.1") == 0
		    || strcmp(lib_name, "linux-vdso64.so.1") == 0)
			continue;

		/* Do we have that library already?  */
		if (proc_each_library(proc, NULL, library_with_key_cb, &key))
			continue;

		struct library *lib = malloc(sizeof(*lib));
		if (lib == NULL) {
		fail:
			if (lib != NULL)
				library_destroy(lib);
			fprintf(stderr, "Couldn't load ELF object %s: %s\n",
				lib_name, strerror(errno));
			continue;
		}
		library_init(lib, LT_LIBTYPE_DSO);

		if (ltelf_read_library(lib, proc, lib_name, rlm.l_addr) < 0)
			goto fail;

		lib->key = key;
		proc_add_library(proc, lib);
	}
	return;
}
Ejemplo n.º 13
0
int
arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
		    struct process *proc,
		    struct arg_type_info *info, struct value *valuep)
{
	const size_t sz = type_sizeof(proc, info);
	assert(sz != (size_t)-1);

	if (ctx->hardfp && !ctx->in_varargs) {
		int rc;
		if ((rc = consider_vfp(ctx, proc, info, valuep)) != 1)
			return rc;
	}

	/* IHI0042E_aapcs: If the argument requires double-word
	 * alignment (8-byte), the NCRN is rounded up to the next even
	 * register number.  */
	const size_t al = type_alignof(proc, info);
	assert(al != (size_t)-1);
	if (al == 8)
		ctx->ncrn = ((ctx->ncrn + 1) / 2) * 2;

	/* If the size in words of the argument is not more than r4
	 * minus NCRN, the argument is copied into core registers,
	 * starting at the NCRN.  */
	/* If the NCRN is less than r4 and the NSAA is equal to the
	 * SP, the argument is split between core registers and the
	 * stack.  */

	const size_t words = (sz + 3) / 4;
	if (ctx->ncrn < 4 && ctx->nsaa == ctx->sp) {
		unsigned char *data = value_reserve(valuep, words * 4);
		if (data == NULL)
			return -1;
		size_t i;
		for (i = 0; i < words && ctx->ncrn < 4; ++i) {
			memcpy(data, &ctx->regs.uregs[ctx->ncrn++], 4);
			data += 4;
		}
		const size_t rest = (words - i) * 4;
		if (rest > 0) {
			umovebytes(proc, ctx->nsaa, data, rest);
			ctx->nsaa += rest;
		}
		return 0;
	}

	assert(ctx->ncrn == 4);

	/* If the argument required double-word alignment (8-byte),
	 * then the NSAA is rounded up to the next double-word
	 * address.  */
	if (al == 8)
		/* XXX double cast.  */
		ctx->nsaa = (arch_addr_t)((((uintptr_t)ctx->nsaa + 7) / 8) * 8);
	else
		ctx->nsaa = (arch_addr_t)((((uintptr_t)ctx->nsaa + 3) / 4) * 4);

	value_in_inferior(valuep, ctx->nsaa);
	ctx->nsaa += sz;

	return 0;
}