OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [librdbg/] [src/] [servrpc.c] - Rev 1767

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 **********************************************************************
 *
 *  Component:	RDBG
 *  Module:	servrpc.c
 *
 *  Synopsis:	support routines for RPC dispatch for remote debug server.
 *		Main server dispatch routines from RPC to support remote debug.
 *
 * $Id: servrpc.c,v 1.2 2001-09-27 12:02:01 chris Exp $
 *
 **********************************************************************
 */
 
#include <string.h>
#include <sys/errno.h>
#include <rdbg/rdbg.h>
#include <rdbg/remdeb.h>
#include <rdbg/servrpc.h>
 
/************************************************************************/
 
/* -----------------------------------------------------------------------
   open_connex_2_svc - setup a new connection from a client.
 
   Notes:
      - this function creates a new connection to a client. It allocates
	an entry in the connection structure and fills in the information
	sent and implied by the message.
      - a client connection entry is needed for all further messages to work
	properly.
   ----------------------------------------------------------------------- */
 
open_out* RPCGENSRVNAME(open_connex_2_svc) (open_in *in, struct svc_req *rqstp)
{
  static open_out out;		/* output response. This could be heap local */
  int		idx;
  static int	one_time = 0;	/* we do one-time setup on back port */
 
  /* need to support in->debug_type, in->flags, and in->destination!!! */
 
  if (!one_time)
  {				/* only setup one backport socket */
    /* now setup signals and the like for handling process changes */
    setErrno(0);
    TspInit(rqstp->rq_xprt->xp_sock); /* init transport system */
    if (getErrno())
    {				/* failed in setup */
      out.port = (u_long)-1;
      out.fp = getErrno();		/* error causing to fail */
      return(&out);		/* fail */
    }
    one_time = True;		/* disable doing this again */
  }
 
  DPRINTF(("open_connex_2_svc: Opening connection from '%s'\n",
	in->user_name));
 
  /* now setup a validation of all other connections */
  for (idx = 0; idx < conn_list_cnt; idx++)
    if (conn_list[idx].in_use)
    { 				/* setup retry timer */
      DPRINTF(("open_connex_2_svc: Still have connection %d with port %d\n",
	idx, HL_W(*((UINT16*)&conn_list[idx].back_port.c[2]))));
    }
 
  idx = ConnCreate(rqstp, in);	/* setup the connection */
  out.port = idx;		/* connection number */
  if (idx == -1)
    out.fp = getErrno();		/* error causing to fail */
  else
    out.fp = TARGET_PROC_TYPE;
 
  out.server_vers = SERVER_VERS;
  return(&out);
}
 
/* -----------------------------------------------------------------------
   send_signal_2_svc - send a kill/signal to the specified process.
 
   Notes:
      - this function sends a signal to the process specified. This process
	does not have to be under debug nor attached by this server. The kill
	may be refused on other grounds though.
      - kill(pid, 0) can be used to validate the process still exists if
	needed.
   ----------------------------------------------------------------------- */
 
signal_out *RPCGENSRVNAME(send_signal_2_svc) (signal_in *in, struct svc_req *rqstp)
{
  static signal_out out;	/* return code from kill */
 
  /* we do not care if connected */
  setErrno(0);
  out.kill_return = 0;
  out.errNo = 0;
  TotalReboot = 1;
  return(&out);
}
 
/* -----------------------------------------------------------------------
   close_connex_2_svc - close a connection from a client.
   ----------------------------------------------------------------------- */
 
void *RPCGENSRVNAME(close_connex_2_svc) (close_in *in, struct svc_req *rqstp)
{
  int		conn_idx = TspConnGetIndex(rqstp);
 
  if (conn_idx != -1)		/* found it, clear out */
    ConnDelete(conn_idx, rqstp, in->control);
 
  return (void*) ""; /* need to return something */
}
 
/* -----------------------------------------------------------------------
   ptrace_2_svc - control process under debug. 
   ----------------------------------------------------------------------- */
 
#define REG_COUNT \
    (sizeof (xdr_regs) / sizeof (int))
 
ptrace_out *RPCGENSRVNAME(ptrace_2_svc) (ptrace_in *in, struct svc_req *rqstp)
{
  int		conn_idx = rqstp ? TspConnGetIndex(rqstp) : -1;
  static ptrace_out out;	/* outut response (error or data) */
  void		*addr, *addr2;	/* used for actual ptrace call */
  unsigned int	data;
  int		req, pid, ret, pid_idx, idx;
  static union
  {				/* local buffer for returned data */
    Objects_Id	t_list[UTHREAD_MAX]; /* thread_list return */
    char	t_name[THREADNAMEMAX]; /* thread name return */
  } local_buff;			/* for return handling of strings and the like */
  PID_LIST	*plst = NULL;	/* current pid_list entry */
 
  DPRINTF (("ptrace_2_svc: entered (%s (%d), %d, XXXX, %d, XXXX)\n",
      PtraceName (in->addr.req), in->addr.req, in->pid,
      in->data));
 
  out.addr.ptrace_addr_data_out_u.addr = 0;
 
  /* validate the connection */
  if (conn_idx == -1  &&  rqstp != NULL)
  {				/* no connection, error */
    DPRINTF(("ptrace_2_svc: msg from unknown debugger!\n"));
    out.result = -1;
    out.errNo = ECHILD;		/* closest error */
    out.addr.req = 0;		/* to avoid copies that should not occur */
    return(&out);
  }
    /* Consider that the last back-message is acknowledged */
  if (conn_idx >= 0  &&  conn_list[conn_idx].retry) {
    TspMessageReceive(conn_idx, in->pid);
  }
 
  req = in->addr.req;
  out.addr.req = req; 		/* needed for RPC */
  pid = in->pid;
  addr = addr2 = NULL;
  data = in->data;
  setErrno(0);			/* assume works */
  out.result = 0;		/* assume worked ok */
  out.errNo = 0;
 
  /* lookup process to make sure we have under control */
  pid_idx = FindPidEntry (in->pid);
  if (pid_idx >= 0)		/* found it */
  {
    plst = &pid_list[pid_idx];
    if (conn_idx < 0)
      conn_idx = plst->primary_conn;
  }
 
  /* now we handle the special case of ATTACH to a pid we already control */
  if (req == RPT_ATTACH)
  {				/* look it up first */
    if (plst)
    {				/* we have controlled , so return ok+show conn */
      ret = 2;			/* normally secondary connection */
      if (! PIDMAP_TEST (conn_idx, pid_idx))
      {				/* mark as an owner if not already */
	plst->owners++;
	PIDMAP_SET (conn_idx, pid_idx);		/* mask in */
      }
      else if (plst->primary_conn != NO_PRIMARY)
      {				/* regrab makes primary */
	    /* Only if not primary already */
	if (plst->primary_conn != conn_idx) {
	    TspSendWaitChange(plst->primary_conn, BMSG_NOT_PRIM,
			conn_idx, plst->pid, 0, False); /* tell old owner */
	}
	plst->primary_conn = NO_PRIMARY;
      }
 
      if (plst->primary_conn == NO_PRIMARY)
      {				/* none now, so take over */
	plst->primary_conn = conn_idx; /* new primary */
	ret = 1;		/* primary */
      }
      out.result = ret; 	/* primary or secondary owner */
      return(&out);
    }
    /* else attach process using target code */
    setErrno(ESRCH); 		/* assume the worst */
    if (!TgtAttach(conn_idx, pid))
    {				/* failed */
      out.errNo = getErrno();
      out.result = 0;
    }
    return(&out);
  }
  else if (req == RPT_DETACH)
  {				/* see which kind of detach */
    if (data == PTRDET_UNOWN)
    {				/* only want to disconnect from */
      TgtDetachCon(conn_idx, pid_idx, True); /* remove from control */
      return(&out);		/* done */
    }
  }
  else if (plst  &&  (req == RPT_GETNAME  ||  req == RPT_GETBREAK))
  {
    /* do nothing */
  }
 
  else if (plst  &&  req == RPT_CLRBREAK) {
     /* To be able to remove breakpoints from a "running" system */
    DPRINTF (("ptrace_2_svc: allowing RPT_CLRBREAK %d\n", data));
	/* do nothing */
  }
 
  else if (plst && plst->running)
  {				/* error, process is running and not detach */
    out.result = -1;
    out.errNo = ETXTBSY;	/* closest error */
    DPRINTF (("ptrace_2_svc: failed, still running.\n"));
    return(&out);
  }
  if (plst == NULL) {
    out.result = -1;
    out.errNo = ESRCH;
    DPRINTF (("ptrace_2_svc: No such process.\n"));
    return (&out);
  }
 
  /* now make sure secondary owner is not trying to modify */
  if (!(in->flags & PTRFLG_NON_OWNER)) /* if not overriden */
    if (conn_idx != plst->primary_conn
    &&  ( (req >= RPT_POKETEXT && req <= RPT_SINGLESTEP)
       	  || (req >= RPT_SETREGS && req <= RPT_SETFPAREGS && (req & 1))
	  || (req >= RPT_SYSCALL && req <= RPT_DUMPCORE)
	  || (req >= RPT_SETTARGETTHREAD && req <= RPT_THREADRESUME)
	  || (req >= RPT_SETTHREADNAME && req <= RPT_SETTHREADREGS)
       	  || (req >= RPT_STEPRANGE && req <= RPT_CLRBREAK)
	  || (req == RPT_STOP)
	  || (req >= RPT_PSETREGS && req <= RPT_PSETTHREADREGS)))
    {				/* not owner */
      out.result = -1;
      out.errNo = EPERM;		/* cannot alter as not primary */
      DPRINTF (("ptrace_2_svc: refused, not owner, flags %d conn_idx %d primary_conn %d\n", in->flags, conn_idx,
	plst->primary_conn));
      return(&out);
    }
 
  addr = (void *)in->addr.ptrace_addr_data_in_u.address; /* default */
  /* now setup normal ptrace request by unpacking. May execute here. */
  switch (req)
  {				/* handle unpacking or setup for real call */
    /* first the ones where addr points to input data */
    case RPT_SETREGS:
    case RPT_SETTHREADREGS:
      addr = (void *)&in->addr.ptrace_addr_data_in_u.regs; /* reg list */
      break;
 
    case RPT_PSETREGS:
    case RPT_PSETTHREADREGS:
      if (in->addr.ptrace_addr_data_in_u.pregs.pregs_len != REG_COUNT) {
	DPRINTF(("ptrace_2_svc: pid %d got %d expected %d\n", pid,
	    in->addr.ptrace_addr_data_in_u.pregs.pregs_len, REG_COUNT));
	setErrno(EINVAL);
	break;
      }
      req = req == RPT_PSETREGS ? RPT_SETREGS : RPT_SETTHREADREGS;
      addr = (void *) in->addr.ptrace_addr_data_in_u.pregs.pregs_val;
      break;
 
    case RPT_SETTHREADNAME:
      addr = (void *)in->addr.ptrace_addr_data_in_u.name;
      break;
    case RPT_WRITETEXT:
    case RPT_WRITEDATA:
      if ((int) data < 0) {
	setErrno(EINVAL);
	break;
      }
      addr = (void *)in->addr.ptrace_addr_data_in_u.mem.addr; /* targ addr */
      addr2 = (void *)in->addr.ptrace_addr_data_in_u.mem.data; /* buff */
 
	/* Forbid writing over breakpoints */
      if (BreakOverwrite (plst, addr, data)) {
	setErrno(EBUSY);
      }
      break;
 
    case RPT_POKETEXT:
    case RPT_POKEDATA:
	/* Forbid writing over breakpoints */
      if (BreakOverwrite (plst, addr, sizeof (int))) {
	setErrno(EBUSY);
      }
      break;
 
    /* now ones where we handle locally */
    case RPT_GETTARGETTHREAD:
      out.result = plst->thread;
      req = 0;			/* force exit */
      break;
 
    case RPT_PGETREGS:	/* return from our buffer */
      out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT;
      out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs;
      req = 0;			/* force exit */     
      break;
 
    case RPT_GETREGS:
      /* return directly from our buffer */
      /* this buffer is refreshed when changing target thread */
      out.addr.ptrace_addr_data_out_u.regs = plst->regs;
      req = 0;			/* force exit */     
      break;
 
    case RPT_SETBREAK:
      idx = BreakSet (plst, conn_idx, &in->addr.ptrace_addr_data_in_u.breakp);
      if (idx < 0) break;
      req = 0;			/* force exit */
      out.result = idx;		/* return break index (>0) */ 
      break;
 
    case RPT_CLRBREAK:
      if (conn_list[conn_idx].flags & DEBUGGER_IS_GDB) {
          data = BreakGetIndex (plst, addr);
      }
      out.result = BreakClear (plst, conn_idx, data);
      /* if errored, errno will still be set */
      req = 0;
      break;
 
    case RPT_GETBREAK:
      /* data=handle, addr=in_buffer, returns next break. Data=0, returns cnt */
      out.result = BreakGet (plst, data, &out.addr.
	ptrace_addr_data_out_u.breakp);
      req = 0;			/* handle locally */
      break;
 
    case RPT_GETNAME:		/* get the name of the process */
      if (!plst->name)
        out.addr.ptrace_addr_data_out_u.mem.dataNb = 0;
      else
      {
	int maxLen = sizeof out.addr.ptrace_addr_data_out_u.mem.data - 1;
	data = strlen(plst->name);
	if (data > maxLen)
	  data = maxLen;
        out.addr.ptrace_addr_data_out_u.mem.dataNb = data+1;
        memcpy(out.addr.ptrace_addr_data_out_u.mem.data, plst->name, data+1);
        out.addr.ptrace_addr_data_out_u.mem.data [maxLen] = '\0';
      }
      req = 0;
      break;
 
    case RPT_CONTTO:
      if (BreakSetAt (plst, conn_idx, (u_long) addr, BRKT_STEPEMUL) < 0)
      {
	DPRINTF(("ptrace_2_svc: BreakSet failed at %x", addr));
	break;
      }
      req = RPT_CONT;
      /* data can contain a signal number, addr2 is unused */
      goto case_RPT_CONT;
 
    case RPT_STEPRANGE:
      /* convert to step */
      if (!data)
        data = 1;		/* should we give an error?? */
      BreakStepRange (plst, addr, data);
      if (getErrno()) break;
 
      req = RPT_SINGLESTEP;	/* do by stepping */
      addr = (void*) 1;		/* start from current PC */
      data = -2;		/* want non-atomic stepping */
      /* fall through to other exec cases */
 
    case RPT_CONT:
    case_RPT_CONT:
    case RPT_SINGLESTEP:
 
      if (BreakStepOff (plst, &addr2))
      {				/* need clear then step off break */
	    /* clear break, step, then do exec */
	if (addr == (void*) 1)
	  addr = (void*) plst->regs.REG_PC;/* need for patch */
 
	  /* data is always 0, so atomic single-step */
      } else if (req == RPT_SINGLESTEP) {
	data = -2;		/* want non-atomic stepping */
      }
      break;
 
    /* now ones where addr points to an output area */
    case RPT_PGETTHREADREGS:
      addr = (void*) out.addr.ptrace_addr_data_out_u.mem.data;
      if (sizeof out.addr.ptrace_addr_data_out_u.mem.data <
	    REG_COUNT * sizeof(int)) {
	setErrno(EINVAL);
	break;
      }
      if (data == plst->thread) {
	out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT;
	out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs;
	req = 0;			/* force exit */
	break;
      }
      req = RPT_GETTHREADREGS;
      break;
 
    case RPT_GETTHREADREGS:
      addr = (void*) &out.addr.ptrace_addr_data_out_u.regs;
      break;
    case RPT_GETTHREADNAME:
      out.addr.ptrace_addr_data_out_u.name = local_buff.t_name;
      addr = (void*) out.addr.ptrace_addr_data_out_u.name;
      break;
    case RPT_THREADLIST:
      out.addr.ptrace_addr_data_out_u.threads.threads =(ptThreadList) local_buff.t_list;
      addr = (void*) out.addr.ptrace_addr_data_out_u.threads.threads;
      break;
    case RPT_READTEXT:
    case RPT_READDATA:
      if ((int) data < 0) {
	setErrno(EINVAL);
	break;
      }
      addr = (void *)in->addr.ptrace_addr_data_in_u.address;
      addr2 = (void *)out.addr.ptrace_addr_data_out_u.mem.data;
      out.addr.ptrace_addr_data_out_u.mem.dataNb = data;
      break;
    case RPT_DETACH:
      /* Do not allow detaching if breakpoints still there */
      if (BreakGet (plst, 0, NULL))
      {				/* some bkpts still set */
	setErrno(EINVAL);		/* cannot detach safely */
	break;
      }
      /* fall through */
    case RPT_KILL:
      /* in the event they are trying to detach or kill a terminated process,
	 we just delete the entry.					*/
      if (PROC_TERMINATED (plst))
      { 
	TgtDelete(plst, -1, BMSG_KILLED);	/* just blow off */
	req = 0;		/* now exit */
      }
      break;
  }
 
  if (getErrno())
  {				/* failed in code above */
    out.result = -1;
    out.errNo = getErrno();
    DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo));
    return(&out);
  }
  else if (!req)
  {				/* bail out now */
    DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo));
    return(&out); 
  }
 
  /* OK, make the call */
  out.result = TgtPtrace(req, pid, addr, data, addr2);
  out.errNo = getErrno();
 
  /* if no error, cleanup afterwards */
  if (getErrno())
  {
      /* Remove step-emul breakpoints if any */
    if (req == RPT_SINGLESTEP || req == RPT_CONT) {
      BreakClear (plst, -1, -1);
    }
    DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo));
    return(&out);		/* return error */
  }
 
  switch (in->addr.req)
  {				/* handle some special calls that affect state */
    case RPT_CONT:
    case RPT_STEPRANGE:
      /* change to running */
      if (in->addr.req == RPT_STEPRANGE)
	plst->last_start = LAST_RANGE; /* so range steps */
      else if (addr2)
	plst->last_start = LAST_STEPOFF; /* now continue after wait */
      else
          plst->last_start = LAST_CONT;
      plst->running = 1; 	/* mark as running */
      if (!rqstp) /* Called internally to restart bkpt, no msg to anybody */
	break;
      TgtNotifyAll(pid_idx, BMSG_WAIT, 0, 0, (in->flags & PTRFLG_NON_OWNER)
			? -1 : conn_idx, True);
      break;
    case RPT_SINGLESTEP:
      /* mark as step */
      plst->last_start = LAST_STEP; /* so we know how started */
      plst->running = 1; 	/* mark as running (wait should catch fast) */
      break;
    case RPT_DETACH: 		/* mark as disconnected */
    case RPT_KILL:		/* mark as killed */
      if (in->flags & PTRFLG_FREE) /* notify and delete entry */
        TgtDelete(plst, -1, (in->addr.req==RPT_KILL) ? BMSG_KILLED : BMSG_DETACH);
      else
      {				/* notify and mark */
	plst->last_start = (in->addr.req==RPT_KILL) ? 
		LAST_KILLED : LAST_DETACHED;
	plst->state = -1;
	plst->running = False;
	TgtNotifyAll(pid_idx, (in->addr.req==RPT_KILL) ? 
		BMSG_KILLED : BMSG_DETACH, 0, 0, -1, True);
      }
      break;
    case RPT_SETTHREADREGS:
    case RPT_PSETTHREADREGS:
	if (data != plst->thread)
	  break;
	DPRINTF(("ptrace_2_svc: pid %d target thread regs changed!\n", pid));
 
    case RPT_SETREGS:
    case RPT_PSETREGS:
      /* change our buffer as well */
      if (plst->regs.REG_PC != ((xdr_regs*)addr)->REG_PC)
	BreakPcChanged (plst);
      plst->regs = *(xdr_regs*) addr; /* copy in */
      break;
 
    /* case RPT_PGETREGS has been handled locally above */
    case RPT_PGETTHREADREGS:
	/* We need to update pointer so that XDR works on return */
      out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT;
      out.addr.ptrace_addr_data_out_u.pregs.pregs_val =
	  (void*) out.addr.ptrace_addr_data_out_u.mem.data;
      break;
 
    case RPT_PEEKTEXT:
    case RPT_PEEKDATA:
    case RPT_READDATA:
    case RPT_READTEXT:
      if (req < RPT_READDATA)
      {				/* peek */
	/* addr is start */
	data = sizeof(int);
	addr2 = &out.result;	/* data buffer */
	/* Like read: addr is start, data is length, addr2 is buffer */
      }
      BreakHide (plst, addr, data, addr2);
      break;
 
    case RPT_SETTARGETTHREAD:
      DPRINTF(("ptrace_2_svc: pid %d new target thread %d\n", pid, data));
      TgtPtrace (RPT_GETREGS, pid, (char*) &plst->regs, 0, NULL);
      plst->thread = data;
      if (plst->break_list) {	/* Forget we had to step off breakpoint */
	BASE_BREAK* base = (BASE_BREAK*) plst->break_list;
	DPRINTF(("ptrace_2_svc: clr_step %d last_break %d\n", base->clr_step,
		base->last_break));
	base->clr_step = 0;	/* Not stopped on break */
	base->last_break = 0;
      }
      break;
 
    case RPT_THREADLIST:
      out.addr.ptrace_addr_data_out_u.threads.nbThread = out.result;      
      break;
 
    default:
      break;
  }				/* end switch */
  DPRINTF(("ptrace_2_svc 2: result %d errNo %d\n", out.result, out.errNo));
  return(&out);
}
 
/* -----------------------------------------------------------------------
   wait_info_2_svc - non-blocking wait request to check status.
   ----------------------------------------------------------------------- */
 
wait_out *RPCGENSRVNAME(wait_info_2_svc) (in, rqstp)
     wait_in *in;
     struct svc_req *rqstp;	/* server info */
{
  int		conn_idx = TspConnGetIndex(rqstp);
  static wait_out out;		/* output of pid and status */
  int		idx;
  PID_LIST	*plst;
 
  memset(&out, 0, sizeof(out));	/* zero for safety */
  out.reason = STOP_ERROR;	/* assume the worst */
 
  if (conn_idx == -1)
  {				/* no connection, error */
    DPRINTF(("wait_info_2_svc: msg from unknown debugger!\n"));
    out.wait_return = -1;
    out.errNo = ECHILD;		/* closest error */
    return(&out);
  }
  else
  {				/* see if confirming message received */
    if (conn_list[conn_idx].retry)
      TspMessageReceive(conn_idx, in->pid);
  }
 
  if (!in->pid)
  {				/* warm test verify only */
    /* this call (pid==0) is made to confirm that that connection is still
	active.		*/
    /* we let it fall through as an error since any use other than connection
	reset would be an error (there is no pid0).			*/
  }
  else
  {				/* normal request */
    idx = FindPidEntry (in->pid);
    if (idx >= 0)
    {				/* found process they requested on */
      plst = &pid_list[idx];
      out.wait_return = plst->running ? 0 : in->pid;
      /* return: 0 is running, pid is stopped/term */
      out.errNo = 0;
      out.status = plst->state; /* last stopped reason if stopped */
      out.thread = plst->thread;/* current thread (or -1 if none) from stop */
      if (!out.wait_return)
	out.reason = STOP_NONE;	/* running, no action */
      else if (STS_SIGNALLED (out.status))
      {			/* stopped on signal */
	out.handle = STS_GETSIG (out.status); /* signal number */
	if (out.handle == SIGTRAP)
	  if (plst->is_step)
	  {			/* single step with hitting a break */
	    out.reason = STOP_STEP;
	    out.handle = 0;	/* no information */
	  }
	  else
	  {			/* stopped on break */
	    out.reason = STOP_BREAK; 
	    if (plst->break_list) 
	      out.handle = ((BASE_BREAK*)plst->break_list)->last_break;
	    else
	      out.handle = 0;	/* no break */
	  }
	else
	  out.reason = STOP_SIGNAL;
	out.PC = plst->regs.REG_PC; /* copy standard regs */
	out.SP = plst->regs.REG_SP;
	out.FP = plst->regs.REG_FP;
      } 
      else
      {				/* terminated, so lower use count */
	if (plst->last_start == LAST_KILLED)
	  out.reason = STOP_KILLED;
	else if (plst->last_start == LAST_DETACHED)
	  out.reason = STOP_DETACHED;
	else if (plst->last_start == LAST_START)
	{			/* failed in exec */
	  out.reason = STOP_SPAWN_FAILED;
	  out.handle = STS_GETCODE (out.status); /* errno reason */
	}
	else if (STS_TERMONSIG (out.status))
	{			/* terminated on signal */
	  out.reason = STOP_TERM_SIG;
	  /* mask off the core-dumped bit 7 */
	  out.handle = (int)(unsigned)(u_char) STS_TERMGETSIG (out.status);
	}
	else
	{			/* exit(2)ed */
	  out.reason = STOP_TERM_EXIT;
	  out.handle = STS_GETCODE (out.status); /* code */
	}
      }
      DPRINTF(("wait_info_2_svc: pid %d return %d status %x errNo %d"
	" reason %d handle %d pc %x sp %x fp %x thread %d\n",
	in->pid, out.wait_return, out.status, out.errNo, out.reason,
	out.handle, out.PC, out.SP, out.FP, out.thread));
      return(&out);
    }
  }
  /* if not found in list, we return error: no such process */
  out.wait_return = -1;
  out.errNo = ESRCH;		/* no process */
  out.status = 0;
  return(&out);
}
 
/* -----------------------------------------------------------------------
   get_signal_names_2_svc - return names for signals
   ----------------------------------------------------------------------- */
 
static one_signal SignalNames[] = {
    {SIGILL,	"SIGILL/EVT_ILL"},
    {SIGTRAP,	"SIGTRAP/EVT_BKPT"},	
    {SIGFPE,	"SIGFPE/EVT_FPE"},
    {SIGKILL,	"SIGKILL/EVT_AKILL"},
    {SIGSEGV,	"SIGSEGV/EVT_SEGV"},
    {17,	"SIGSTOP"},		
    {23,	"SIGSTOP"}		
};
 
get_signal_names_out* RPCGENSRVNAME(get_signal_names_2_svc) (in, rqstp)
     void* in;
     struct svc_req *rqstp;	/* server info */
{
  static get_signal_names_out out;
 
  out.signals.all_signals_len = sizeof SignalNames / sizeof SignalNames[0];
  out.signals.all_signals_val = SignalNames;
 
  return(&out);
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.