예제 #1
0
파일: prb_rtld.c 프로젝트: andreiw/polaris
/*
 * plants a breakpoint at the specified location in
 * the target process, and saves the existing instruction.
 */
static prb_status_t
bpt(prb_proc_ctl_t *proc_p, uintptr_t addr)
{
	prb_status_t	prbstat;
	bptsave_t	instr;

	if (!proc_p->bpt_inserted) {

		DBG_TNF_PROBE_1(bpt_1, "libtnfctl", "sunw%verbosity 2",
			tnf_opaque, bpt_planted_at, addr);

		prbstat = prb_proc_read(proc_p, addr,
			&(proc_p->saveinstr), sizeof (proc_p->saveinstr));
		if (prbstat)
			return (prbstat);

		DBG_TNF_PROBE_1(bpt_2, "libtnfctl", "sunw%verbosity 2",
			tnf_opaque, saved_instr, (unsigned)proc_p->saveinstr);

		instr = INS_BPT;

		prbstat = prb_proc_write(proc_p, addr,
			&instr, sizeof (instr));
		if (prbstat)
			return (prbstat);

		proc_p->bpt_inserted = B_TRUE;
	}
	return (PRB_STATUS_OK);
}
예제 #2
0
파일: elf.c 프로젝트: apprisi/illumos-gate
/*
 * dyn_findtag() - searches tags in _DYNAMIC table
 */
static tnfctl_errcode_t
dyn_findtag(Elf3264_Dyn * start,	/* start of dynam table read in */
		Elf3264_Sword tag,	/* tag to search for */
		uintptr_t dynam_addr,	/* base address of _DYNAMIC in target */
		int limit, /* number of entries in table */
		uintptr_t * dentry_address)
{				/* return value */
	Elf3264_Dyn	  *dp;

	for (dp = start; dp->d_tag != DT_NULL; dp++) {

		DBG_TNF_PROBE_1(dyn_findtag_1, "libtnfctl",
			"sunw%verbosity 3; sunw%debug 'in loop'",
			tnf_long, tag, dp->d_tag);

		if (dp->d_tag == tag) {
			*dentry_address = dynam_addr +
				(dp - start) * sizeof (Elf3264_Dyn);
			return (TNFCTL_ERR_NONE);
		}
		if (--limit <= 0) {
			DBG((void) fprintf(stderr,
				"dyn_findtag: exceeded limit of table\n"));
			return (TNFCTL_ERR_INTERNAL);
		}
	}

	DBG((void) fprintf(stderr,
		"dyn_findtag: couldn't find tag, last tag=%d\n",
		(int) dp->d_tag));
	return (TNFCTL_ERR_INTERNAL);
}
예제 #3
0
/*
 * prb_child_create()  - this routine instantiates and rendevous with the
 * target child process.  This routine returns an opaque handle for the
 * childs /proc entry.
 */
prb_status_t
prb_child_create(const char *cmdname, char * const *cmdargs,
                 const char *loption, const char *libtnfprobe_path,
                 char * const *envp, prb_proc_ctl_t **ret_val)
{
    prb_status_t	prbstat;
    pid_t		childpid;
    char		executable_name[PATH_MAX + 2];
    extern char 	**environ;
    char * const *	env_to_use;
    size_t		loptlen, probepathlen;
    volatile shmem_msg_t *smp;

    /* initialize shmem communication buffer to cause child to wait */
    prbstat = prb_shmem_init(&smp);
    if (prbstat)
        return (prbstat);

    /* fork to create the child process */
    childpid = fork();
    if (childpid == (pid_t) - 1) {
        DBG(perror("prb_child_create: fork failed"));
        return (prb_status_map(errno));
    }
    if (childpid == 0) {
        char		   *oldenv;
        char		   *newenv;

        /* ---- CHILD PROCESS ---- */

        DBG_TNF_PROBE_1(prb_child_create_1, "libtnfctl",
                        "sunw%verbosity 1; sunw%debug 'child process created'",
                        tnf_long, pid, getpid());

        if (envp) {
            env_to_use = envp;
            goto ContChild;
        }

        /* append libtnfprobe.so to the LD_PRELOAD environment */
        loptlen = (loption) ? strlen(loption) : 0;
        /* probepathlen has a "/" added in ("+ 1") */
        probepathlen = (libtnfprobe_path) ?
                       (strlen(libtnfprobe_path) + 1) : 0;
        oldenv = getenv(PRELOAD);
        if (oldenv) {
            newenv = (char *) malloc(strlen(PRELOAD) +
                                     1 +	/* "=" */
                                     strlen(oldenv) +
                                     1 +	/* " " */
                                     probepathlen +
                                     strlen(LIBPROBE) +
                                     1 +	/* " " */
                                     loptlen +
                                     1);	/* NULL */

            if (!newenv)
                goto ContChild;
            (void) strcpy(newenv, PRELOAD);
            (void) strcat(newenv, "=");
            (void) strcat(newenv, oldenv);
            (void) strcat(newenv, " ");
            if (probepathlen) {
                (void) strcat(newenv, libtnfprobe_path);
                (void) strcat(newenv, "/");
            }
            (void) strcat(newenv, LIBPROBE);
            if (loptlen) {
                (void) strcat(newenv, " ");
                (void) strcat(newenv, loption);
            }
        } else {
            newenv = (char *) malloc(strlen(PRELOAD) +
                                     1 +	/* "=" */
                                     probepathlen +
                                     strlen(LIBPROBE) +
                                     1 +	/* " " */
                                     loptlen +
                                     1);	/* NULL */
            if (!newenv)
                goto ContChild;
            (void) strcpy(newenv, PRELOAD);
            (void) strcat(newenv, "=");
            if (probepathlen) {
                (void) strcat(newenv, libtnfprobe_path);
                (void) strcat(newenv, "/");
            }
            (void) strcat(newenv, LIBPROBE);
            if (loptlen) {
                (void) strcat(newenv, " ");
                (void) strcat(newenv, loption);
            }
        }
        (void) putenv((char *) newenv);
        env_to_use = environ;
        /*
         * We don't check the return value of putenv because the
         * desired libraries might already be in the target, even
         * if our effort to change the environment fails.  We
         * should continue either way ...
         */
ContChild:
        /* wait until the parent releases us */
        (void) prb_shmem_wait(smp);

        DBG_TNF_PROBE_1(prb_child_create_2, "libtnfctl",
                        "sunw%verbosity 2; "
                        "sunw%debug 'child process about to exec'",
                        tnf_string, cmdname, cmdname);

        /*
         * make the child it's own process group.
         * This is so that signals delivered to parent are not
         * also delivered to child.
         */
        (void) setpgrp();
        prbstat = find_executable(cmdname, executable_name);
        if (prbstat) {
            DBG((void) fprintf(stderr, "prb_child_create: %s\n",
                               prb_status_str(prbstat)));
            /* parent waits for exit */
            _exit(1);
        }
        if (execve(executable_name, cmdargs, env_to_use) == -1) {
            DBG(perror("prb_child_create: exec failed"));
            _exit(1);
        }

        /* Never reached */
        _exit(1);
    }
    /* ---- PARENT PROCESS ---- */
    /* child is waiting for us */

    prbstat = sync_child(childpid, smp, ret_val);
    if (prbstat) {
        return (prbstat);
    }

    return (PRB_STATUS_OK);

}
예제 #4
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);
}