示例#1
0
prmap_t *
proc_name2map(struct proc_handle *p, const char *name)
{
	size_t i;
	int cnt;
	prmap_t *map;
	char tmppath[MAXPATHLEN];
	struct kinfo_vmentry *kves, *kve;
	rd_loadobj_t *rdl;

	/*
	 * If we haven't iterated over the list of loaded objects,
	 * librtld_db isn't yet initialized and it's very likely
	 * that librtld_db called us. We need to do the heavy
	 * lifting here to find the symbol librtld_db is looking for.
	 */
	if (p->nobjs == 0) {
		if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL)
			return (NULL);
		for (i = 0; i < (size_t)cnt; i++) {
			kve = kves + i;
			basename_r(kve->kve_path, tmppath);
			if (strcmp(tmppath, name) == 0) {
				map = proc_addr2map(p, kve->kve_start);
				free(kves);
				return (map);
			}
		}
		free(kves);
		return (NULL);
	}
	if (name == NULL || strcmp(name, "a.out") == 0) {
		map = proc_addr2map(p, p->rdobjs[0].rdl_saddr);
		return (map);
	}
	for (i = 0; i < p->nobjs; i++) {
		rdl = &p->rdobjs[i];
		basename_r(rdl->rdl_path, tmppath);
		if (strcmp(tmppath, name) == 0) {
			if ((map = malloc(sizeof(*map))) == NULL)
				return (NULL);
			proc_rdl2prmap(rdl, map);
			return (map);
		}
	}

	return (NULL);
}
示例#2
0
/*
 * Wait for the specified process to hit a breakpoint at the specified symbol.
 */
static void
verify_bkpt(struct proc_handle *phdl, GElf_Sym *sym, const char *symname,
    const char *mapname)
{
	char mapbname[MAXPATHLEN], *name;
	GElf_Sym tsym;
	prmap_t *map;
	size_t namesz;
	u_long addr;
	int error, state;

	state = proc_wstatus(phdl);
	ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has state %d", state);

	/* Get the program counter and decrement it. */
	error = proc_regget(phdl, REG_PC, &addr);
	ATF_REQUIRE_EQ_MSG(error, 0, "failed to obtain PC for '%s'",
	    target_prog_file);
	proc_bkptregadj(&addr);

	/*
	 * Make sure the PC matches the expected value obtained from the symbol
	 * definition we looked up earlier.
	 */
	ATF_CHECK_EQ_MSG(addr, sym->st_value,
	    "program counter 0x%lx doesn't match expected value 0x%jx",
	    addr, (uintmax_t)sym->st_value);

	/*
	 * Ensure we can look up the r_debug_state symbol using its starting
	 * address and that the resulting symbol matches the one we found using
	 * a name lookup.
	 */
	namesz = strlen(symname) + 1;
	name = malloc(namesz);
	ATF_REQUIRE(name != NULL);

	error = proc_addr2sym(phdl, addr, name, namesz, &tsym);
	ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up symbol at 0x%lx", addr);
	ATF_REQUIRE_EQ(memcmp(sym, &tsym, sizeof(*sym)), 0);
	ATF_REQUIRE_EQ_MSG(strcmp(symname, name), 0,
	    "expected symbol name '%s' doesn't match '%s'", symname, name);
	free(name);

	map = proc_addr2map(phdl, addr);
	ATF_REQUIRE_MSG(map != NULL, "failed to look up map for address 0x%lx",
	    addr);
	basename_r(map->pr_mapname, mapbname);
	ATF_REQUIRE_EQ_MSG(strcmp(mapname, mapbname), 0,
	    "expected map name '%s' doesn't match '%s'", mapname, mapbname);
}
示例#3
0
int
proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
    size_t namesz, GElf_Sym *symcopy)
{
	Elf *e;
	Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
	Elf_Data *data;
	GElf_Shdr shdr;
	GElf_Sym sym;
	GElf_Ehdr ehdr;
	int fd, error = -1;
	size_t i;
	uint64_t rsym;
	prmap_t *map;
	char *s;
	unsigned long symtabstridx = 0, dynsymstridx = 0;

	if ((map = proc_addr2map(p, addr)) == NULL)
		return (-1);
	if (!map->pr_mapname || (fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) {
		warn("ERROR: open %s failed", map->pr_mapname);
		goto err0;
	}
	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		warn("ERROR: elf_begin() failed");
		goto err1;
	}
	if (gelf_getehdr(e, &ehdr) == NULL) {
		warn("ERROR: gelf_getehdr() failed");
		goto err2;
	}
	/*
	 * Find the index of the STRTAB and SYMTAB sections to locate
	 * symbol names.
	 */
	scn = NULL;
	while ((scn = elf_nextscn(e, scn)) != NULL) {
		gelf_getshdr(scn, &shdr);
		switch (shdr.sh_type) {
		case SHT_SYMTAB:
			symtabscn = scn;
			symtabstridx = shdr.sh_link;
			break;
		case SHT_DYNSYM:
			dynsymscn = scn;
			dynsymstridx = shdr.sh_link;
			break;
		default:
			break;
		}
	}
	/*
	 * Iterate over the Dynamic Symbols table to find the symbol.
	 * Then look up the string name in STRTAB (.dynstr)
	 */
	if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
		DPRINTF("ERROR: elf_getdata() failed");
		goto symtab;
	}
	i = 0;
	while (gelf_getsym(data, i++, &sym) != NULL) {
		/*
		 * Calculate the address mapped to the virtual memory
		 * by rtld.
		 */
		rsym = map->pr_vaddr + sym.st_value;
		if (addr >= rsym && addr <= (rsym + sym.st_size)) {
			s = elf_strptr(e, dynsymstridx, sym.st_name);
			if (s) {
				if (s[0] == '_' && s[1] == 'Z' && s[2])
					demangle(s, name, namesz);
				else
					strlcpy(name, s, namesz);
				memcpy(symcopy, &sym, sizeof(sym));
				/*
				 * DTrace expects the st_value to contain
				 * only the address relative to the start of
				 * the function.
				 */
				symcopy->st_value = rsym;
				error = 0;
				goto out;
			}
		}
	}
symtab:
	/*
	 * Iterate over the Symbols Table to find the symbol.
	 * Then look up the string name in STRTAB (.dynstr)
	 */
	if (symtabscn == NULL)
		goto err2;
	if ((data = elf_getdata(symtabscn, NULL)) == NULL) {
		DPRINTF("ERROR: elf_getdata() failed");
		goto err2;
	}
	i = 0;
	while (gelf_getsym(data, i++, &sym) != NULL) {
		/*
		 * Calculate the address mapped to the virtual memory
		 * by rtld.
		 */
		if (ehdr.e_type != ET_EXEC)
			rsym = map->pr_vaddr + sym.st_value;
		else
			rsym = sym.st_value;
		if (addr >= rsym && addr <= (rsym + sym.st_size)) {
			s = elf_strptr(e, symtabstridx, sym.st_name);
			if (s) {
				if (s[0] == '_' && s[1] == 'Z' && s[2])
					demangle(s, name, namesz);
				else
					strlcpy(name, s, namesz);
				memcpy(symcopy, &sym, sizeof(sym));
				/*
				 * DTrace expects the st_value to contain
				 * only the address relative to the start of
				 * the function.
				 */
				symcopy->st_value = rsym;
				error = 0;
				goto out;
			}
		}
	}
out:
err2:
	elf_end(e);
err1:
	close(fd);
err0:
	free(map);
	return (error);
}
示例#4
0
文件: proc_sym.c 项目: sambuc/netbsd
int
proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
    size_t namesz, GElf_Sym *symcopy)
{
	GElf_Ehdr ehdr;
	GElf_Shdr shdr;
	Elf *e;
	Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
	prmap_t *map;
	const char *s;
	uintptr_t off;
	u_long symtabstridx = 0, dynsymstridx = 0;
	int fd, error = -1;

	if ((map = proc_addr2map(p, addr)) == NULL)
		return (-1);
	if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
		DPRINTF("ERROR: open %s failed", map->pr_mapname);
		goto err0;
	}
	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
		goto err1;
	}
	if (gelf_getehdr(e, &ehdr) == NULL) {
		DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
		goto err2;
	}

	/*
	 * Find the index of the STRTAB and SYMTAB sections to locate
	 * symbol names.
	 */
	scn = NULL;
	while ((scn = elf_nextscn(e, scn)) != NULL) {
		gelf_getshdr(scn, &shdr);
		switch (shdr.sh_type) {
		case SHT_SYMTAB:
			symtabscn = scn;
			symtabstridx = shdr.sh_link;
			break;
		case SHT_DYNSYM:
			dynsymscn = scn;
			dynsymstridx = shdr.sh_link;
			break;
		}
	}

	off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;

	/*
	 * First look up the symbol in the dynsymtab, and fall back to the
	 * symtab if the lookup fails.
	 */
	error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy);
	if (error == 0)
		goto out;

	error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy);
	if (error != 0)
		goto err2;

out:
	demangle(s, name, namesz);
err2:
	elf_end(e);
err1:
	close(fd);
err0:
	free(map);
	return (error);
}