⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 servrpc.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ********************************************************************** * *  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.3 2002/02/01 17:00:01 joel 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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -