Пример #1
0
/*ARGSUSED*/
static tnfctl_errcode_t
dynsec_num(tnfctl_handle_t *hndl, uintptr_t baseaddr,
	int objfd, int *num_dyn)
{
	int		num_ent = 0;
	tnfctl_errcode_t	prexstat;
	tnfctl_elf_search_t search_info;

	DBG_TNF_PROBE_0(dynsec_num_1, "libtnfctl",
		"sunw%verbosity 2;"
		"sunw%debug 'counting number of entries in .dynamic section'");

	search_info.section_func = elf_dynmatch;
	search_info.section_data = &num_ent;

	prexstat = _tnfctl_traverse_object(objfd, baseaddr, &search_info);
	if (prexstat)
		return (prexstat);

	if (num_ent == 0)
		return (TNFCTL_ERR_NOTDYNAMIC);

	*num_dyn = num_ent;

	return (TNFCTL_ERR_NONE);
}
Пример #2
0
/*
 * prb_rtld_unstalk() - remove rtld breakpoint
 */
prb_status_t
prb_rtld_unstalk(prb_proc_ctl_t *proc_p)
{
	prb_status_t	prbstat;

	DBG_TNF_PROBE_0(prb_rtld_unstalk_1, "libtnfctl", "sunw%verbosity 2");

	/* turn off BPT tracing while out of the water ... */
	prbstat = prb_proc_tracebpt(proc_p, B_FALSE);

	prbstat = unbpt(proc_p, proc_p->bptaddr);

	return (prbstat);
}
Пример #3
0
/*
 * prb_rtld_stalk() - setup for a breakpoint when rtld has opened or closed a
 * shared object.
 */
prb_status_t
prb_rtld_stalk(prb_proc_ctl_t *proc_p)
{
	prb_status_t	prbstat = PRB_STATUS_OK;

	DBG_TNF_PROBE_0(prb_rtld_stalk_1, "libtnfctl", "sunw%verbosity 2");

	if (!proc_p->bptaddr) {
		Elf3264_Dyn	   dentry;
		struct r_debug  r_dbg;

		if (proc_p->dbgaddr == 0) {
			DBG((void) fprintf(stderr,
				"prb_rtld_stalk: dbgaddr not set\n"));
			return (PRB_STATUS_BADARG);
		}

		prbstat = prb_proc_read(proc_p, proc_p->dbgaddr,
			&dentry, sizeof (dentry));
		if (prbstat || !dentry.d_un.d_ptr) {
			DBG((void) fprintf(stderr,
				"prb_rtld_stalk: error in d_un.d_ptr\n"));
			return (prbstat);
		}
		/* read in the debug struct that it points to */
		prbstat = prb_proc_read(proc_p, dentry.d_un.d_ptr,
			&r_dbg, sizeof (r_dbg));
		if (prbstat)
			return (prbstat);

		proc_p->bptaddr = r_dbg.r_brk;
	}
	/* plant a breakpoint trap in the pointed to function */
	prbstat = bpt(proc_p, proc_p->bptaddr);
	if (prbstat)
		return (prbstat);

	/* setup process to stop when breakpoint encountered */
	prbstat = prb_proc_tracebpt(proc_p, B_TRUE);

	return (prbstat);

}
Пример #4
0
/*
 * prb_rtld_setup() - turns on the flag in the rtld structure so that rtld
 * executes a getpid() stystem call after it done mapping all shared objects
 * but before it executes any init code.
 */
static prb_status_t
prb_rtld_setup(prb_proc_ctl_t *proc_p, boolean_t *synced)
{
	prb_status_t	prbstat = PRB_STATUS_OK;
	Elf3264_Dyn	dentry;

	DBG_TNF_PROBE_0(prb_rtld_setup_1, "libtnfctl", "sunw%verbosity 2");

	if (proc_p->dbgaddr == 0) {
		DBG((void) fprintf(stderr,
			"prb_rtld_setup: dbgaddr not set\n"));
		return (PRB_STATUS_BADARG);
	}

	prbstat = prb_proc_read(proc_p, proc_p->dbgaddr, &dentry,
					sizeof (dentry));
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_setup: error in d_un.d_ptr\n"));
		return (prbstat);
	}

	if ((dentry.d_un.d_ptr == 0) || (dentry.d_un.d_ptr == 1)) {
		*synced = B_FALSE;
	} else {
		*synced = B_TRUE;
		return (PRB_STATUS_OK);
	}

	/* modify it  - i.e. request rtld to do getpid() */
	dentry.d_un.d_ptr = 1;
	prbstat = prb_proc_write(proc_p, proc_p->dbgaddr, &dentry,
					sizeof (dentry));

	return (prbstat);
}
Пример #5
0
/*
 * prb_rtld_advance() - we've hit a breakpoint, replace the original
 * instruction, istep, put the breakpoint back ...
 */
prb_status_t
prb_rtld_advance(prb_proc_ctl_t *proc_p)
{
	prb_status_t	prbstat;

	DBG_TNF_PROBE_0(prb_rtld_advance_1, "libtnfctl", "sunw%verbosity 2");

	prbstat = prb_proc_clrbptflt(proc_p);
	if (prbstat)
		return (prbstat);
	prbstat = unbpt(proc_p, proc_p->bptaddr);
	if (prbstat)
		return (prbstat);

	prbstat = prb_proc_istepbpt(proc_p);
	if (prbstat)
		return (prbstat);

	prbstat = bpt(proc_p, proc_p->bptaddr);
	if (prbstat)
		return (prbstat);

	return (PRB_STATUS_OK);
}
Пример #6
0
/*
 * iterate over all loadobjects in the same address space calling the
 * callback function "obj_func".
 */
static int
inprocess_loadobj_iter(void *opq, tnfctl_ind_obj_f *obj_func, void *cd)
{
	Elf3264_Dyn	*dtdebug = opq;
	struct r_debug	*r_dbg;
	struct link_map *lmap;
	char		path[MAXPATHLEN];
	int		procfd;
	tnfctl_ind_obj_info_t	loadobj;
	int		retval = 0;	/* sucessful return */

	DBG_TNF_PROBE_0(inprocess_loadobj_iter_start, "libtnfctl",
			"start inprocess_loadobj_iter; sunw%verbosity 1");

	r_dbg = (struct r_debug *)dtdebug->d_un.d_ptr;

	DBG_TNF_PROBE_1(inprocess_loadobj_iter_1, "libtnfctl",
		"sunw%verbosity 1",
		tnf_string, link_map_state,
		(r_dbg->r_state == RT_CONSISTENT) ? "RT_CONSISTENT" :
			(r_dbg->r_state == RT_ADD) ? "RT_ADD" : "RT_DELETE");

	/* bail if link map is not consistent */
	if (r_dbg->r_state != RT_CONSISTENT)
		return (1);

	(void) sprintf(path, PROCFORMAT, (int) getpid());

	/*
	 * opening /proc readonly, so debuggers can still run
	 * We use /proc in order to get fd on the object.
	 */
	procfd = open(path, O_RDONLY);
	if (procfd == -1)
		return (1);

	for (lmap = r_dbg->r_map; lmap; lmap = lmap->l_next) {
		loadobj.text_base = lmap->l_addr;
		loadobj.data_base = lmap->l_addr;
		loadobj.objname = lmap->l_name;
		/*
		 * client of this interface should deal with -1 for objfd,
		 * so no error checking is needed on this ioctl
		 */
		loadobj.objfd = ioctl(procfd, PIOCOPENM, &(lmap->l_addr));

		retval = obj_func(opq, &loadobj, cd);

		/* close the fd */
		if (loadobj.objfd != -1)
			close(loadobj.objfd);

		/* check for error */
		if (retval == 1)
			goto end_of_func;
	}

end_of_func:
	close(procfd);

	DBG_TNF_PROBE_0(inprocess_loadobj_iter_end, "libtnfctl",
			"end inprocess_loadobj_iter; sunw%verbosity 1");
	return (retval);
}
Пример #7
0
/*
 * prb_rtld_wait() - waits on target to execute getpid()
 */
static prb_status_t
prb_rtld_wait(prb_proc_ctl_t *proc_p)
{
	prb_proc_state_t pstate;
	prb_status_t	prbstat;

	DBG_TNF_PROBE_0(prb_rtld_wait_1, "libtnfctl", "sunw%verbosity 2");

	/* stop on exit of getpid() */
	prbstat = prb_proc_exit(proc_p, SYS_getpid, PRB_SYS_ADD);
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: couldn't set up child to stop on "
			"exit of getpid(): %s\n", prb_status_str(prbstat)));
		return (prbstat);
	}
	/* stop on entry of exit() - i.e. exec failed */
	prbstat = prb_proc_entry(proc_p, SYS_exit, PRB_SYS_ADD);
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: couldn't set up child to stop on "
			"entry of exit(): %s\n", prb_status_str(prbstat)));
		return (prbstat);
	}
	/* continue target and wait for it to stop */
	prbstat = prb_proc_cont(proc_p);
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: couldn't continue target process: %s\n",
				prb_status_str(prbstat)));
		return (prbstat);
	}
	/* wait for target to stop */
	prbstat = prb_proc_wait(proc_p, B_FALSE, NULL);
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: couldn't wait on target process: %s\n",
			prb_status_str(prbstat)));
		return (prbstat);
	}
	/* make sure it did stop on getpid() */
	prbstat = prb_proc_state(proc_p, &pstate);
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: couldn't get state of target: %s\n",
				prb_status_str(prbstat)));
		return (prbstat);
	}
	if (pstate.ps_issysentry && (pstate.ps_syscallnum == SYS_exit)) {
		DBG((void) fprintf(stderr, "prb_rtld_wait: target exited\n"));
		return (prb_status_map(EACCES));
	}
	/* catch any other errors */
	if (!(pstate.ps_issysexit && (pstate.ps_syscallnum == SYS_getpid))) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: target didn't stop on getpid\n"));
		return (PRB_STATUS_BADSYNC);
	}
	/* clear wait on getpid */
	prbstat = prb_proc_exit(proc_p, SYS_getpid, PRB_SYS_DEL);
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: couldn't clear child to stop on "
			"exit of getpid(): %s\n", prb_status_str(prbstat)));
		return (prbstat);
	}
	/* clear wait on exit */
	prbstat = prb_proc_entry(proc_p, SYS_exit, PRB_SYS_DEL);
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: couldn't clear child to stop on "
			"entry of exit(): %s\n", prb_status_str(prbstat)));
		return (prbstat);
	}
	/* start-stop the process to clear it out of the system call */
	prbstat = prb_proc_prstop(proc_p);
	if (prbstat) {
		DBG((void) fprintf(stderr,
			"prb_rtld_wait: couldn't prstop child: %s\n",
			prb_status_str(prbstat)));
		return (prbstat);
	}
	return (PRB_STATUS_OK);
}