diff options
Diffstat (limited to 'usr/src/lib/libtnfctl/prb_proc.c')
-rw-r--r-- | usr/src/lib/libtnfctl/prb_proc.c | 1004 |
1 files changed, 0 insertions, 1004 deletions
diff --git a/usr/src/lib/libtnfctl/prb_proc.c b/usr/src/lib/libtnfctl/prb_proc.c deleted file mode 100644 index 48e05b088f..0000000000 --- a/usr/src/lib/libtnfctl/prb_proc.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1994-1999 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This file contains interfaces that are wrappers over the basic - * /proc ioctls - */ - -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <sys/uio.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/fault.h> -#include <sys/procfs.h> - -#include "prb_proc_int.h" -#include "dbg.h" - -/* - * Declarations - */ - -#define PROCFORMAT "/proc/%d" - -static prb_status_t -prb_proc_open_general(pid_t pid, prb_proc_ctl_t **proc_pp, int oflg); - -/* - * prb_proc_open_general() - function to open the process file - * system entry for the supplied process. Opens with different - * options based on the 'oflg'. - * Returns a pointer to an opaque structure that contains the fd - * needed for /proc control. - */ - -prb_status_t -prb_proc_open_general(pid_t pid, prb_proc_ctl_t **proc_pp, int oflg) -{ - prb_proc_ctl_t *proc_p; - char path[MAXPATHLEN]; - int retval; - - (void) sprintf(path, PROCFORMAT, (int)pid); - - DBG_TNF_PROBE_1(prb_proc_open_1, "libtnfctl", "sunw%verbosity 2", - tnf_string, opening_proc_on, path); - - retval = open(path, oflg); - if (retval == -1) { - DBG((void) fprintf(stderr, - "proc_open: open of \"%s\" failed: %s\n", - path, strerror(errno))); - return (prb_status_map(errno)); - } - /* allocate proc_p and zero fill */ - proc_p = calloc(1, sizeof (*proc_p)); - if (proc_p == NULL) - return (PRB_STATUS_ALLOCFAIL); - proc_p->procfd = retval; - proc_p->pid = pid; - *proc_pp = proc_p; - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_open() - a wrapper which opens the process file system - * entry for the supplied process. Returns a pointer to an opaque - * structure that contains the fd needed for /proc control. - */ - -prb_status_t -prb_proc_open(pid_t pid, prb_proc_ctl_t **proc_pp) -{ - - return (prb_proc_open_general(pid, - proc_pp, O_RDWR | O_EXCL)); - -} - -/* - * prb_proc_reopen() - re-opens the process, mainly for setuid/setgid files. - * Read the last section of /proc man page for details. - * re-open should not use O_EXCL flag. - */ - -prb_status_t -prb_proc_reopen(pid_t pid, prb_proc_ctl_t **proc_pp) -{ - - return (prb_proc_open_general(pid, - proc_pp, O_RDWR)); - -} - -/* - * prob_proc_close() - close the proc fd and free the memory taken up - * by proc_p - */ -prb_status_t -prb_proc_close(prb_proc_ctl_t *proc_p) -{ - DBG_TNF_PROBE_0(prb_proc_close_1, "libtnfctl", "sunw%verbosity 2"); - - if (proc_p == NULL) - return (PRB_STATUS_OK); - - if (close(proc_p->procfd) == -1) { - DBG((void) fprintf(stderr, - "proc_close: close failed: %s\n", strerror(errno))); - return (prb_status_map(errno)); - } - free(proc_p); - return (PRB_STATUS_OK); -} - -/* - * prb_proc_pid_get() - gets the pid of the proc - */ -pid_t -prb_proc_pid_get(prb_proc_ctl_t *proc_p) -{ - return (proc_p->pid); -} - -/* - * prb_proc_stop() - stops the target process - */ -prb_status_t -prb_proc_stop(prb_proc_ctl_t *proc_p) -{ - int retval; - - DBG_TNF_PROBE_0(prb_proc_stop_1, "libtnfctl", - "sunw%verbosity 2; sunw%debug 'stopping the target process'"); - -again: - retval = ioctl(proc_p->procfd, PIOCSTOP, NULL); - if (retval == -1) { - if (errno == EINTR) - goto again; - DBG((void) fprintf(stderr, - "prb_proc_stop: PIOCSTOP failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_prstop() - runs and stops the process, used to clear a target - * process out of a system call state. - */ -prb_status_t -prb_proc_prstop(prb_proc_ctl_t *proc_p) -{ - int procfd; - int retval; - prrun_t prrun; - prstatus_t prstat; - - DBG_TNF_PROBE_0(prb_proc_prstop_1, "libtnfctl", - "sunw%verbosity 2; sunw%debug 'stepping the target process'"); - - procfd = proc_p->procfd; - (void) memset((char *)&prrun, 0, sizeof (prrun)); - (void) memset((char *)&prstat, 0, sizeof (prstat)); - -again1: - prrun.pr_flags = PRSTOP; - retval = ioctl(procfd, PIOCRUN, &prrun); - if (retval == -1) { - if (errno == EINTR) - goto again1; - DBG((void) fprintf(stderr, - "prb_proc_prstop: PIOCRUN failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } -again2: - retval = ioctl(procfd, PIOCWSTOP, &prstat); - if (retval == -1) { - if (errno == EINTR) - goto again2; - DBG((void) fprintf(stderr, - "prb_proc_prstop: PIOCWSTOP failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - /* - * if we didn't stop because we requested it (eg. if there was a - * signal in the target ?), we might need to try again - */ - if (prstat.pr_why != PR_REQUESTED) - goto again1; - - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_state() - returns the status pf the process - */ -prb_status_t -prb_proc_state(prb_proc_ctl_t *proc_p, prb_proc_state_t *state_p) -{ - int procfd; - int retval; - prstatus_t prstatus; - - DBG_TNF_PROBE_0(prb_proc_state_1, "libtnfctl", - "sunw%verbosity 2; sunw%debug 'getting the status'"); - - procfd = proc_p->procfd; - - (void) memset(&prstatus, 0, sizeof (prstatus)); - -again: - retval = ioctl(procfd, PIOCSTATUS, &prstatus); - if (retval == -1) { - if (errno == EINTR) - goto again; - DBG((void) fprintf(stderr, - "prb_proc_status: PIOCSTATUS failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - state_p->ps_isbptfault = (prstatus.pr_flags & PR_FAULTED && - prstatus.pr_what == FLTBPT); - state_p->ps_isstopped = ((prstatus.pr_flags & PR_STOPPED) != 0); - state_p->ps_isinsys = ((prstatus.pr_flags & PR_ASLEEP) != 0); - state_p->ps_isrequested = ((prstatus.pr_why & PR_REQUESTED) != 0); - state_p->ps_issysexit = ((prstatus.pr_why & PR_SYSEXIT) != 0); - state_p->ps_issysentry = ((prstatus.pr_why & PR_SYSENTRY) != 0); - state_p->ps_syscallnum = prstatus.pr_what; - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_wait() - waits for the target process to stop - */ -prb_status_t -prb_proc_wait(prb_proc_ctl_t *proc_p, boolean_t use_sigmask, sigset_t *oldmask) -{ - int procfd; - int retval; - prstatus_t prstat; - sigset_t pendmask; - int i, mask_size; - boolean_t pending_signal = B_FALSE; - - DBG_TNF_PROBE_0(prb_proc_wait_1, "libtnfctl", - "sunw%verbosity 2;" - "sunw%debug 'waiting for the target process to stop'"); - - procfd = proc_p->procfd; - - /* - * This one of the places where we do not resubmit the ioctl if - * if it is terminated by an EINTR (interrupted system call). In - * this case, the caller knows best ... - */ - (void) memset(&prstat, 0, sizeof (prstat)); - - /* if we blocked signals... */ - if (use_sigmask) { - if (sigemptyset(&pendmask) == -1) - return (prb_status_map(errno)); - if (sigpending(&pendmask) == -1) - return (prb_status_map(errno)); - /* - * check if there were any signals pending - - * XXXX libc should provide this interface - */ - mask_size = sizeof (pendmask) / sizeof (pendmask.__sigbits[0]); - for (i = 0; i < mask_size; i++) { - if (pendmask.__sigbits[i] != 0) - pending_signal = B_TRUE; - } - - /* return to original signal mask */ - if (sigprocmask(SIG_SETMASK, oldmask, NULL) == -1) - return (prb_status_map(errno)); - - /* if there was a pending signal, don't call PIOCWSTOP ioctl */ - if (pending_signal) - return (prb_status_map(EINTR)); - - /* - * XXXX - there is a a race between now and when we call - * the PIOCWSTOP ioctl. One solution, is for the user to - * call an interface in libtnfctl from their signal handler. - * This interface will do a longjmp such that it never - * calls the ioctl (the setjmp would be before we restore - * the signal mask above) - */ - } - - retval = ioctl(procfd, PIOCWSTOP, &prstat); - - DBG_TNF_PROBE_2(prb_proc_wait_2, "libtnfctl", "sunw%verbosity 2;", - tnf_opaque, pc, prstat.pr_reg[R_PC], - tnf_opaque, instr, prstat.pr_instr); - - if (retval == -1) { -#ifdef DEBUG - if (errno != EINTR && errno != ENOENT) - (void) fprintf(stderr, - "prb_proc_wait: PIOCWSTOP failed: %s\n", - strerror(errno)); - -#endif - return (prb_status_map(errno)); - } - - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_cont() - continues the target process - */ -prb_status_t -prb_proc_cont(prb_proc_ctl_t *proc_p) -{ - int procfd; - int retval; - prrun_t prrun; - - DBG_TNF_PROBE_0(prb_proc_cont_1, "libtnfctl", - "sunw%verbosity 2; sunw%debug 'starting the target process'"); - procfd = proc_p->procfd; - - (void) memset((char *)&prrun, 0, sizeof (prrun)); - -again: - prrun.pr_flags = PRCFAULT; - retval = ioctl(procfd, PIOCRUN, &prrun); - if (retval == -1) { - if (errno == EINTR) - goto again; - DBG((void) fprintf(stderr, - "prb_proc_cont: PIOCRUN failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_istepbpt() - step the target process one instruction - * - * CAUTION!!!! - this routine is specialized to only be able to single - * step over the breakpoint location. - */ -prb_status_t -prb_proc_istepbpt(prb_proc_ctl_t *proc_p) -{ - int procfd; - int retval; - prrun_t run; - fltset_t faults; - prstatus_t prstat; - - DBG_TNF_PROBE_0(prb_proc_istepbpt_1, "libtnfctl", - "sunw%verbosity 2; " - "sunw%debug 'single stepping over breakpoint'"); - - procfd = proc_p->procfd; - - (void) memset((char *)&run, 0, sizeof (run)); - - /* add trace fault to the list of current traced faults */ -again1: - retval = ioctl(procfd, PIOCGFAULT, &faults); - if (retval == -1) { - if (errno == EINTR) - goto again1; - DBG((void) fprintf(stderr, - "prb_proc_istepbpt: PIOCGFAULT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - praddset(&faults, FLTTRACE); - - /* issue the run command with the single-step option */ - run.pr_flags = PRCFAULT | PRSFAULT | PRSTEP; - run.pr_fault = faults; - - /* load the location of the breakpoint */ - run.pr_vaddr = (caddr_t)proc_p->bptaddr; - run.pr_flags |= PRSVADDR; - -again2: - retval = ioctl(procfd, PIOCRUN, &run); - if (retval == -1) { - if (errno == EINTR) - goto again2; - DBG((void) fprintf(stderr, - "prb_proc_istepbpt: PIOCRUN failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } -again3: - retval = ioctl(procfd, PIOCWSTOP, &prstat); - if (retval == -1) { - if (errno == EINTR) - goto again3; - DBG((void) fprintf(stderr, - "prb_proc_istepbpt: PIOCWSTOP failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - - DBG_TNF_PROBE_2(prb_proc_istepbpt_2, "libtnfctl", "sunw%verbosity 2;", - tnf_opaque, pc, prstat.pr_reg[R_PC], - tnf_opaque, instr, prstat.pr_instr); - - - /* clear any current faults */ -again4: - retval = ioctl(procfd, PIOCCFAULT, NULL); - if (retval == -1) { - if (errno == EINTR) - goto again4; - DBG((void) fprintf(stderr, - "prb_proc_clrbptflt: PIOCCFAULT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - /* remove the trace fault from the current traced faults */ - prdelset(&faults, FLTTRACE); -again5: - retval = ioctl(procfd, PIOCSFAULT, &faults); - if (retval == -1) { - if (errno == EINTR) - goto again5; - DBG((void) fprintf(stderr, - "prb_proc_istepbpt: PIOCSFAULT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_clrbptflt() - clear an encountered breakpoint fault - */ -prb_status_t -prb_proc_clrbptflt(prb_proc_ctl_t *proc_p) -{ - int retval; - int procfd; - - DBG_TNF_PROBE_0(prb_proc_clrbptflt_1, "libtnfctl", "sunw%verbosity 2"); - - procfd = proc_p->procfd; - - /* clear any current faults */ -again: - retval = ioctl(procfd, PIOCCFAULT, NULL); - if (retval == -1) { - if (errno == EINTR) - goto again; - DBG((void) fprintf(stderr, - "prb_proc_clrbptflt: PIOCCFAULT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_tracebpt() - sets the bpt tracing state. - */ -prb_status_t -prb_proc_tracebpt(prb_proc_ctl_t *proc_p, boolean_t bpt) -{ - int procfd; - int retval; - fltset_t faults; - - DBG_TNF_PROBE_1(prb_proc_tracebpt_1, "libtnfctl", "sunw%verbosity 2;", - tnf_string, bpt_state, (bpt) ? "enabled" : "disabled"); - - procfd = proc_p->procfd; - /* get the current set of traced faults */ -again1: - retval = ioctl(procfd, PIOCGFAULT, &faults); - if (retval == -1) { - if (errno == EINTR) - goto again1; - DBG((void) fprintf(stderr, - "prb_proc_tracebpt: PIOCGFAULT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - /* set or clear the breakpoint flag */ - if (bpt) - praddset(&faults, FLTBPT); - else - prdelset(&faults, FLTBPT); - - /* write the fault set back */ -again2: - retval = ioctl(procfd, PIOCSFAULT, &faults); - if (retval == -1) { - if (errno == EINTR) - goto again2; - DBG((void) fprintf(stderr, - "prb_proc_tracebpt: PIOCSFAULT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); -} - -/* Note - the following 3 functions should be combined */ - -/* - * prb_proc_setrlc() - sets or clears the run-on-last-close flag. - */ -prb_status_t -prb_proc_setrlc(prb_proc_ctl_t *proc_p, boolean_t rlc) -{ - int procfd; - long mode; - int retval; - - DBG_TNF_PROBE_1(prb_proc_setrlc_1, "libtnfctl", "sunw%verbosity 2;", - tnf_string, run_on_last_close, (rlc) ? "setting" : "clearing"); - - procfd = proc_p->procfd; - mode = PR_RLC; - - if (rlc) { -again1: - retval = ioctl(procfd, PIOCSET, &mode); - if (retval == -1) { - if (errno == EINTR) - goto again1; - DBG((void) fprintf(stderr, - "prb_proc_setrlc: PIOCSET failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - } else { -again2: - retval = ioctl(procfd, PIOCRESET, &mode); - if (retval == -1) { - if (errno == EINTR) - goto again2; - DBG((void) fprintf(stderr, - "prb_proc_setrlc: PIOCRESET failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - } - - return (PRB_STATUS_OK); - - -} /* end prb_proc_setrlc */ - - -/* - * prb_proc_setklc() - sets or clears the kill-on-last-close flag. - */ -prb_status_t -prb_proc_setklc(prb_proc_ctl_t *proc_p, boolean_t klc) -{ - int procfd; - long mode; - int retval; - - DBG_TNF_PROBE_1(prb_proc_setklc_1, "libtnfctl", "sunw%verbosity 2;", - tnf_string, kill_on_last_close, (klc) ? "setting" : "clearing"); - - procfd = proc_p->procfd; - mode = PR_KLC; - - if (klc) { -again1: - retval = ioctl(procfd, PIOCSET, &mode); - if (retval == -1) { - if (errno == EINTR) - goto again1; - DBG((void) fprintf(stderr, - "prb_proc_setklc: PIOCSET failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - } else { -again2: - retval = ioctl(procfd, PIOCRESET, &mode); - if (retval == -1) { - if (errno == EINTR) - goto again2; - DBG((void) fprintf(stderr, - "prb_proc_setklc: PIOCRESET failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - } - - return (PRB_STATUS_OK); - -} /* end prb_proc_setklc */ - -/* - * prb_proc_setfork() - sets or clears the inherit-on-fork flag - */ -prb_status_t -prb_proc_setfork(prb_proc_ctl_t *proc_p, boolean_t inhfork) -{ - int procfd; - long mode; - int retval; - - DBG_TNF_PROBE_1(prb_proc_setfork_1, "libtnfctl", "sunw%verbosity 2;", - tnf_string, kill_on_last_close, - (inhfork) ? "setting" : "clearing"); - - procfd = proc_p->procfd; - mode = PR_FORK; - - if (inhfork) { -again1: - retval = ioctl(procfd, PIOCSET, &mode); - if (retval == -1) { - if (errno == EINTR) - goto again1; - DBG((void) fprintf(stderr, - "prb_proc_setfork: PIOCSET failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - } else { -again2: - retval = ioctl(procfd, PIOCRESET, &mode); - if (retval == -1) { - if (errno == EINTR) - goto again2; - DBG((void) fprintf(stderr, - "prb_proc_setfork: PIOCRESET failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - } - - return (PRB_STATUS_OK); - -} /* end prb_proc_setfork */ - -/* - * prb_proc_exit() - if op is PRB_SYS_ALL, sets up the target process to stop - * on exit from all system calls. If op is PRB_SYS_NONE, sets up the target - * process so that it will not stop on exit from any system call. - * PRB_SYS_ADD and PRB_SYS_DEL adds or deletes a particular system call from - * the mask of "interested" system calls respectively. This function can be - * called multiple times to build up the mask. - */ -prb_status_t -prb_proc_exit(prb_proc_ctl_t *proc_p, - uint_t syscall, - prb_syscall_op_t op) -{ - int procfd; - int retval; - sysset_t sysmask; - - DBG_TNF_PROBE_0(prb_proc_exit_1, "libtnfctl", - "sunw%verbosity 2; " - "sunw%debug 'setting up target to stop on exit of syscall'"); - - procfd = proc_p->procfd; - - switch (op) { - case PRB_SYS_ALL: - prfillset(&sysmask); - break; - case PRB_SYS_NONE: - premptyset(&sysmask); - break; - case PRB_SYS_ADD: -again1: - retval = ioctl(procfd, PIOCGEXIT, &sysmask); - if (retval == -1) { - if (errno == EINTR) - goto again1; - DBG((void) fprintf(stderr, - "prb_proc_exit: PIOCGEXIT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - praddset(&sysmask, syscall); - break; - case PRB_SYS_DEL: -again2: - retval = ioctl(procfd, PIOCGEXIT, &sysmask); - if (retval == -1) { - if (errno == EINTR) - goto again2; - DBG((void) fprintf(stderr, - "prb_proc_exit: PIOCGEXIT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - prdelset(&sysmask, syscall); - break; - default: - DBG((void) fprintf(stderr, "prb_proc_exit: bad input arg\n")); - return (PRB_STATUS_BADARG); - } -again3: - retval = ioctl(procfd, PIOCSEXIT, &sysmask); - if (retval == -1) { - if (errno == EINTR) - goto again3; - DBG((void) fprintf(stderr, - "prb_proc_exit: PIOCSEXIT failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); - -} /* end prb_proc_exit */ - -/* - * prb_proc_entry() - if op is PRB_SYS_ALL, sets up the target process to - * stop on entry from all system calls. If op is PRB_SYS_NONE, sets up the - * target process so that it will not stop on entry from any system call. - * PRB_SYS_ADD and PRB_SYS_DEL adds or deletes a particular system call from - * the mask of "interested" system calls respectively. This function can be - * called multiple times to build up the mask. - */ -prb_status_t -prb_proc_entry(prb_proc_ctl_t *proc_p, - uint_t syscall, - prb_syscall_op_t op) -{ - int procfd; - int retval; - sysset_t sysmask; - - DBG_TNF_PROBE_0(prb_proc_entry_1, "libtnfctl", - "sunw%verbosity 2; " - "sunw%debug 'setting up target to stop on entry of syscall'"); - - procfd = proc_p->procfd; - - switch (op) { - case PRB_SYS_ALL: - prfillset(&sysmask); - break; - case PRB_SYS_NONE: - premptyset(&sysmask); - break; - case PRB_SYS_ADD: -again1: - retval = ioctl(procfd, PIOCGENTRY, &sysmask); - if (retval == -1) { - if (errno == EINTR) - goto again1; - DBG((void) fprintf(stderr, - "prb_proc_entry: PIOCGENTRY failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - praddset(&sysmask, syscall); - break; - case PRB_SYS_DEL: -again2: - retval = ioctl(procfd, PIOCGENTRY, &sysmask); - if (retval == -1) { - if (errno == EINTR) - goto again2; - DBG((void) fprintf(stderr, - "prb_proc_entry: PIOCGENTRY failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - prdelset(&sysmask, syscall); - break; - default: - DBG((void) fprintf(stderr, "prb_proc_entry: bad input arg\n")); - return (PRB_STATUS_BADARG); - } -again3: - retval = ioctl(procfd, PIOCSENTRY, &sysmask); - if (retval == -1) { - if (errno == EINTR) - goto again3; - DBG((void) fprintf(stderr, - "prb_proc_entry: PIOCSENTRY failed: %s\n", - strerror(errno))); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); -} - -/* - * prb_proc_read() - reads a block of memory from a processes address space. - */ -prb_status_t -prb_proc_read(prb_proc_ctl_t *proc_p, uintptr_t addr, void *buf, size_t size) -{ - int procfd; - ssize_t sz; - off_t offset; - - DBG_TNF_PROBE_2(prb_proc_read_1, "libtnfctl", "sunw%verbosity 3;", - tnf_long, num_bytes, size, - tnf_opaque, from_address, addr); - - procfd = proc_p->procfd; - offset = lseek(procfd, (off_t)addr, SEEK_SET); - if (offset != (off_t)addr) { - DBG(perror("prb_proc_read: lseek failed")); - return (prb_status_map(errno)); - } - sz = read(procfd, buf, size); - if (sz != size) { - DBG(perror("prb_proc_read: read failed")); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_write() - writes a block of memory from a processes address - * space. - */ -prb_status_t -prb_proc_write(prb_proc_ctl_t *proc_p, uintptr_t addr, void *buf, size_t size) -{ - int procfd; - ssize_t sz; - off_t offset; - - DBG_TNF_PROBE_2(prb_proc_write_1, "libtnfctl", "sunw%verbosity 3;", - tnf_long, num_bytes, size, - tnf_opaque, to_address, addr); - - procfd = proc_p->procfd; - offset = lseek(procfd, (off_t)addr, SEEK_SET); - if (offset != (off_t)addr) { - DBG(perror("prb_proc_write: lseek failed")); - return (prb_status_map(errno)); - } - sz = write(procfd, buf, size); - if (sz != size) { - DBG(perror("prb_proc_write: write failed")); - return (prb_status_map(errno)); - } - return (PRB_STATUS_OK); -} - - -/* - * prb_proc_readstr() - dereferences a string in the target - * NOTE: There is a similar routine called _tnfctl_readstr_targ() - * used by tnfctl layer. It would be better if there was only - * one of these functions defined. - */ - -#define BUFSZ 256 - -prb_status_t -prb_proc_readstr(prb_proc_ctl_t *proc_p, uintptr_t addr, const char **outstr_pp) -{ - prb_status_t prbstat; - int bufsz = BUFSZ; - char buffer[BUFSZ + 1]; - offset_t offset; - char *ptr, *orig_ptr; - - *outstr_pp = NULL; - offset = 0; - - /* allocate an inital return buffer */ - ptr = (char *)malloc(BUFSZ); - if (!ptr) { - DBG((void) fprintf(stderr, - "prb_proc_readstr: malloc failed\n")); - return (PRB_STATUS_ALLOCFAIL); - } - /*LINTED constant in conditional context*/ - while (1) { - int i; - - /* read a chunk into our buffer */ - prbstat = prb_proc_read(proc_p, addr + offset, buffer, bufsz); - if (prbstat) { - - /* - * if we get into trouble with a large read, try again - * with a single byte. Subsequent failure is real ... - */ - if (bufsz > 1) { - bufsz = 1; - continue; - } - - DBG((void) fprintf(stderr, - "prb_proc_readstr: prb_proc_read failed: %s\n", - prb_status_str(prbstat))); - free(ptr); - return (prbstat); - } - /* copy the chracters into the return buffer */ - for (i = 0; i < bufsz; i++) { - char c = buffer[i]; - - ptr[offset + i] = c; - if (c == '\0') { - /* hooray! we saw the end of the string */ - *outstr_pp = ptr; - return (PRB_STATUS_OK); - } - } - - /* bummer, need to grab another bufsz characters */ - offset += bufsz; - orig_ptr = ptr; - ptr = (char *)realloc(ptr, offset + bufsz); - if (!ptr) { - free(orig_ptr); - DBG((void) fprintf(stderr, - "prb_proc_readstr: realloc failed\n")); - return (PRB_STATUS_ALLOCFAIL); - } - } - -#if defined(lint) - return (PRB_STATUS_OK); -#endif -} - -prb_status_t -prb_proc_get_r0_r1(prb_proc_ctl_t *proc_p, prgreg_t *r0, prgreg_t *r1) -{ - int retval; - int procfd; - prstatus_t prstatus; - - procfd = proc_p->procfd; -again: - retval = ioctl(procfd, PIOCSTATUS, &prstatus); - if (retval == -1) { - if (errno == EINTR) - goto again; - return (prb_status_map(errno)); - } - - /* - * Use R_Rn register definitions for some uniformity - * sparc: define R_R0 R_O0 - * define R_R1 R_O1 - * x86: define R_R0 EAX - * define R_R1 EDX - */ - *r0 = prstatus.pr_reg[R_R0]; - *r1 = prstatus.pr_reg[R_R1]; - DBG((void) fprintf - (stderr, "prb_proc_get_r0_r1: R_R0 = %d, R_R1 = %d\n", *r0, *r1)); - return (PRB_STATUS_OK); -} |