source: rtems/c/src/librdbg/src/servrpc.c @ df49c60

4.104.114.84.95
Last change on this file since df49c60 was 981b99f, checked in by Joel Sherrill <joel.sherrill@…>, on 08/10/99 at 16:41:44

Patch from Eric Valette <valette@…> and Emmanuel Raguet
<raguet@…>:

  • the dec21140 driver code has been hardened (various bug fixed) Emmanuel,
  • bug in the mcp750 init code have been fixed (interrupt stack/initial stack initialization), BSS correctly cleared (Eric V)
  • remote debugging over TCP/IP is nearly complete (berakpoints, backtrace, variables,...) (Eric V),
  • exception handling code has also been improved in order to fully support RDBG requirements (Eric V),
  • Property mode set to 100644
File size: 22.8 KB
RevLine 
[4721cf1]1/*
2 **********************************************************************
3 *
4 *  Component:  RDBG
5 *  Module:     servrpc.c
6 *
7 *  Synopsis:   support routines for RPC dispatch for remote debug server.
8 *              Main server dispatch routines from RPC to support remote debug.
9 *
[981b99f]10 * $Id$
11 *
[4721cf1]12 **********************************************************************
13 */
14
15#include <string.h>
16#include <sys/errno.h>
17#include <rdbg/rdbg.h>
18#include <rdbg/remdeb.h>
19#include <rdbg/servrpc.h>
20
21/************************************************************************/
22
23/* -----------------------------------------------------------------------
24   open_connex_2_svc - setup a new connection from a client.
25
26   Notes:
27      - this function creates a new connection to a client. It allocates
28        an entry in the connection structure and fills in the information
29        sent and implied by the message.
30      - a client connection entry is needed for all further messages to work
31        properly.
32   ----------------------------------------------------------------------- */
33
34open_out* RPCGENSRVNAME(open_connex_2_svc) (open_in *in, struct svc_req *rqstp)
35{
36  static open_out out;          /* output response. This could be heap local */
37  int           idx;
38  static int    one_time = 0;   /* we do one-time setup on back port */
39
40  /* need to support in->debug_type, in->flags, and in->destination!!! */
41
42  if (!one_time)
43  {                             /* only setup one backport socket */
44    /* now setup signals and the like for handling process changes */
45    setErrno(0);
46    TspInit(rqstp->rq_xprt->xp_sock); /* init transport system */
47    if (getErrno())
48    {                           /* failed in setup */
49      out.port = (u_long)-1;
50      out.fp = getErrno();              /* error causing to fail */
51      return(&out);             /* fail */
52    }
53    one_time = True;            /* disable doing this again */
54  }
55
56  DPRINTF(("open_connex_2_svc: Opening connection from '%s'\n",
57        in->user_name));
58
59  /* now setup a validation of all other connections */
60  for (idx = 0; idx < conn_list_cnt; idx++)
61    if (conn_list[idx].in_use)
62    {                           /* setup retry timer */
63      DPRINTF(("open_connex_2_svc: Still have connection %d with port %d\n",
64        idx, HL_W(*((UINT16*)&conn_list[idx].back_port.c[2]))));
65    }
66
67  idx = ConnCreate(rqstp, in);  /* setup the connection */
68  out.port = idx;               /* connection number */
69  if (idx == -1)
70    out.fp = getErrno();                /* error causing to fail */
71  else
72    out.fp = TARGET_PROC_TYPE;
73
74  out.server_vers = SERVER_VERS;
75  return(&out);
76}
77
78/* -----------------------------------------------------------------------
79   send_signal_2_svc - send a kill/signal to the specified process.
80
81   Notes:
82      - this function sends a signal to the process specified. This process
83        does not have to be under debug nor attached by this server. The kill
84        may be refused on other grounds though.
85      - kill(pid, 0) can be used to validate the process still exists if
86        needed.
87   ----------------------------------------------------------------------- */
88
89signal_out *RPCGENSRVNAME(send_signal_2_svc) (signal_in *in, struct svc_req *rqstp)
90{
91  static signal_out out;        /* return code from kill */
92
93  /* we do not care if connected */
94  setErrno(0);
95  out.kill_return = 0;
96  out.errNo = 0;
97  TotalReboot = 1;
98  return(&out);
99}
100
101/* -----------------------------------------------------------------------
102   close_connex_2_svc - close a connection from a client.
103   ----------------------------------------------------------------------- */
104
105void *RPCGENSRVNAME(close_connex_2_svc) (close_in *in, struct svc_req *rqstp)
106{
107  int           conn_idx = TspConnGetIndex(rqstp);
108
109  if (conn_idx != -1)           /* found it, clear out */
110    ConnDelete(conn_idx, rqstp, in->control);
111
112  return (void*) ""; /* need to return something */
113}
114
115/* -----------------------------------------------------------------------
116   ptrace_2_svc - control process under debug.
117   ----------------------------------------------------------------------- */
118
119#define REG_COUNT \
120    (sizeof (xdr_regs) / sizeof (int))
121
122ptrace_out *RPCGENSRVNAME(ptrace_2_svc) (ptrace_in *in, struct svc_req *rqstp)
123{
124  int           conn_idx = rqstp ? TspConnGetIndex(rqstp) : -1;
125  static ptrace_out out;        /* outut response (error or data) */
126  void          *addr, *addr2;  /* used for actual ptrace call */
127  unsigned int  data;
128  int           req, pid, ret, pid_idx, idx;
129  static union
130  {                             /* local buffer for returned data */
131    Objects_Id  t_list[UTHREAD_MAX]; /* thread_list return */
132    char        t_name[THREADNAMEMAX]; /* thread name return */
133  } local_buff;                 /* for return handling of strings and the like */
134  PID_LIST      *plst = NULL;   /* current pid_list entry */
135
136  DPRINTF (("ptrace_2_svc: entered (%s (%d), %d, XXXX, %d, XXXX)\n",
137      PtraceName (in->addr.req), in->addr.req, in->pid,
138      in->data));
139
140  out.addr.ptrace_addr_data_out_u.addr = 0;
141
142  /* validate the connection */
143  if (conn_idx == -1  &&  rqstp != NULL)
144  {                             /* no connection, error */
145    DPRINTF(("ptrace_2_svc: msg from unknown debugger!\n"));
146    out.result = -1;
147    out.errNo = ECHILD;         /* closest error */
148    out.addr.req = 0;           /* to avoid copies that should not occur */
149    return(&out);
150  }
151    /* Consider that the last back-message is acknowledged */
152  if (conn_idx >= 0  &&  conn_list[conn_idx].retry) {
153    TspMessageReceive(conn_idx, in->pid);
154  }
155
156  req = in->addr.req;
157  out.addr.req = req;           /* needed for RPC */
158  pid = in->pid;
159  addr = addr2 = NULL;
160  data = in->data;
161  setErrno(0);                  /* assume works */
162  out.result = 0;               /* assume worked ok */
163  out.errNo = 0;
164
165  /* lookup process to make sure we have under control */
166  pid_idx = FindPidEntry (in->pid);
167  if (pid_idx >= 0)             /* found it */
168  {
169    plst = &pid_list[pid_idx];
170    if (conn_idx < 0)
171      conn_idx = plst->primary_conn;
172  }
173
174  /* now we handle the special case of ATTACH to a pid we already control */
175  if (req == RPT_ATTACH)
176  {                             /* look it up first */
177    if (plst)
178    {                           /* we have controlled , so return ok+show conn */
179      ret = 2;                  /* normally secondary connection */
180      if (! PIDMAP_TEST (conn_idx, pid_idx))
181      {                         /* mark as an owner if not already */
182        plst->owners++;
183        PIDMAP_SET (conn_idx, pid_idx);         /* mask in */
184      }
185      else if (plst->primary_conn != NO_PRIMARY)
186      {                         /* regrab makes primary */
187            /* Only if not primary already */
188        if (plst->primary_conn != conn_idx) {
189            TspSendWaitChange(plst->primary_conn, BMSG_NOT_PRIM,
190                        conn_idx, plst->pid, 0, False); /* tell old owner */
191        }
192        plst->primary_conn = NO_PRIMARY;
193      }
194
195      if (plst->primary_conn == NO_PRIMARY)
196      {                         /* none now, so take over */
197        plst->primary_conn = conn_idx; /* new primary */
198        ret = 1;                /* primary */
199      }
200      out.result = ret;         /* primary or secondary owner */
201      return(&out);
202    }
203    /* else attach process using target code */
204    setErrno(ESRCH);            /* assume the worst */
205    if (!TgtAttach(conn_idx, pid))
206    {                           /* failed */
207      out.errNo = getErrno();
208      out.result = 0;
209    }
210    return(&out);
211  }
212  else if (req == RPT_DETACH)
213  {                             /* see which kind of detach */
214    if (data == PTRDET_UNOWN)
215    {                           /* only want to disconnect from */
216      TgtDetachCon(conn_idx, pid_idx, True); /* remove from control */
217      return(&out);             /* done */
218    }
219  }
220  else if (plst  &&  (req == RPT_GETNAME  ||  req == RPT_GETBREAK))
221  {
222    /* do nothing */
223  }
224
225  else if (plst  &&  req == RPT_CLRBREAK) {
226     /* To be able to remove breakpoints from a "running" system */
227    DPRINTF (("ptrace_2_svc: allowing RPT_CLRBREAK %d\n", data));
228        /* do nothing */
229  }
230
231  else if (plst && plst->running)
232  {                             /* error, process is running and not detach */
233    out.result = -1;
234    out.errNo = ETXTBSY;        /* closest error */
235    DPRINTF (("ptrace_2_svc: failed, still running.\n"));
236    return(&out);
237  }
238  if (plst == NULL) {
239    out.result = -1;
240    out.errNo = ESRCH;
241    DPRINTF (("ptrace_2_svc: No such process.\n"));
242    return (&out);
243  }
244
245  /* now make sure secondary owner is not trying to modify */
246  if (!(in->flags & PTRFLG_NON_OWNER)) /* if not overriden */
247    if (conn_idx != plst->primary_conn
248    &&  ( (req >= RPT_POKETEXT && req <= RPT_SINGLESTEP)
249          || (req >= RPT_SETREGS && req <= RPT_SETFPAREGS && (req & 1))
250          || (req >= RPT_SYSCALL && req <= RPT_DUMPCORE)
251          || (req >= RPT_SETTARGETTHREAD && req <= RPT_THREADRESUME)
252          || (req >= RPT_SETTHREADNAME && req <= RPT_SETTHREADREGS)
253          || (req >= RPT_STEPRANGE && req <= RPT_CLRBREAK)
254          || (req == RPT_STOP)
255          || (req >= RPT_PSETREGS && req <= RPT_PSETTHREADREGS)))
256    {                           /* not owner */
257      out.result = -1;
258      out.errNo = EPERM;                /* cannot alter as not primary */
259      DPRINTF (("ptrace_2_svc: refused, not owner, flags %d conn_idx %d primary_conn %d\n", in->flags, conn_idx,
260        plst->primary_conn));
261      return(&out);
262    }
263
264  addr = (void *)in->addr.ptrace_addr_data_in_u.address; /* default */
265  /* now setup normal ptrace request by unpacking. May execute here. */
266  switch (req)
267  {                             /* handle unpacking or setup for real call */
268    /* first the ones where addr points to input data */
269    case RPT_SETREGS:
270    case RPT_SETTHREADREGS:
271      addr = (void *)&in->addr.ptrace_addr_data_in_u.regs; /* reg list */
272      break;
273
274    case RPT_PSETREGS:
275    case RPT_PSETTHREADREGS:
276      if (in->addr.ptrace_addr_data_in_u.pregs.pregs_len != REG_COUNT) {
277        DPRINTF(("ptrace_2_svc: pid %d got %d expected %d\n", pid,
278            in->addr.ptrace_addr_data_in_u.pregs.pregs_len, REG_COUNT));
279        setErrno(EINVAL);
280        break;
281      }
282      req = req == RPT_PSETREGS ? RPT_SETREGS : RPT_SETTHREADREGS;
283      addr = (void *) in->addr.ptrace_addr_data_in_u.pregs.pregs_val;
284      break;
285
286    case RPT_SETTHREADNAME:
287      addr = (void *)in->addr.ptrace_addr_data_in_u.name;
288      break;
289    case RPT_WRITETEXT:
290    case RPT_WRITEDATA:
291      if ((int) data < 0) {
292        setErrno(EINVAL);
293        break;
294      }
295      addr = (void *)in->addr.ptrace_addr_data_in_u.mem.addr; /* targ addr */
296      addr2 = (void *)in->addr.ptrace_addr_data_in_u.mem.data; /* buff */
297
298        /* Forbid writing over breakpoints */
299      if (BreakOverwrite (plst, addr, data)) {
300        setErrno(EBUSY);
301      }
302      break;
303
304    case RPT_POKETEXT:
305    case RPT_POKEDATA:
306        /* Forbid writing over breakpoints */
307      if (BreakOverwrite (plst, addr, sizeof (int))) {
308        setErrno(EBUSY);
309      }
310      break;
311
312    /* now ones where we handle locally */
313    case RPT_GETTARGETTHREAD:
314      out.result = plst->thread;
315      req = 0;                  /* force exit */
316      break;
317
318    case RPT_PGETREGS:  /* return from our buffer */
319      out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT;
320      out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs;
321      req = 0;                  /* force exit */     
322      break;
323
324    case RPT_GETREGS:
325      /* return directly from our buffer */
326      /* this buffer is refreshed when changing target thread */
327      out.addr.ptrace_addr_data_out_u.regs = plst->regs;
328      req = 0;                  /* force exit */     
329      break;
330
331    case RPT_SETBREAK:
332      idx = BreakSet (plst, conn_idx, &in->addr.ptrace_addr_data_in_u.breakp);
333      if (idx < 0) break;
334      req = 0;                  /* force exit */
335      out.result = idx;         /* return break index (>0) */
336      break;
337 
338    case RPT_CLRBREAK:
339      if (conn_list[conn_idx].flags & DEBUGGER_IS_GDB) {
340          data = BreakGetIndex (plst, addr);
341      }
342      out.result = BreakClear (plst, conn_idx, data);
343      /* if errored, errno will still be set */
344      req = 0;
345      break;
346
347    case RPT_GETBREAK:
348      /* data=handle, addr=in_buffer, returns next break. Data=0, returns cnt */
349      out.result = BreakGet (plst, data, &out.addr.
350        ptrace_addr_data_out_u.breakp);
351      req = 0;                  /* handle locally */
352      break;
353
354    case RPT_GETNAME:           /* get the name of the process */
355      if (!plst->name)
356        out.addr.ptrace_addr_data_out_u.mem.dataNb = 0;
357      else
358      {
359        int maxLen = sizeof out.addr.ptrace_addr_data_out_u.mem.data - 1;
360        data = strlen(plst->name);
361        if (data > maxLen)
362          data = maxLen;
363        out.addr.ptrace_addr_data_out_u.mem.dataNb = data+1;
364        memcpy(out.addr.ptrace_addr_data_out_u.mem.data, plst->name, data+1);
365        out.addr.ptrace_addr_data_out_u.mem.data [maxLen] = '\0';
366      }
367      req = 0;
368      break;
369
370    case RPT_CONTTO:
371      if (BreakSetAt (plst, conn_idx, (u_long) addr, BRKT_STEPEMUL) < 0)
372      {
373        DPRINTF(("ptrace_2_svc: BreakSet failed at %x", addr));
374        break;
375      }
376      req = RPT_CONT;
377      /* data can contain a signal number, addr2 is unused */
378      goto case_RPT_CONT;
379
380    case RPT_STEPRANGE:
381      /* convert to step */
382      if (!data)
383        data = 1;               /* should we give an error?? */
384      BreakStepRange (plst, addr, data);
385      if (getErrno()) break;
386
387      req = RPT_SINGLESTEP;     /* do by stepping */
388      addr = (void*) 1;         /* start from current PC */
389      data = -2;                /* want non-atomic stepping */
390      /* fall through to other exec cases */
391
392    case RPT_CONT:
393    case_RPT_CONT:
394    case RPT_SINGLESTEP:
395
396      if (BreakStepOff (plst, &addr2))
397      {                         /* need clear then step off break */
398            /* clear break, step, then do exec */
399        if (addr == (void*) 1)
400          addr = (void*) plst->regs.REG_PC;/* need for patch */
401
402          /* data is always 0, so atomic single-step */
403      } else if (req == RPT_SINGLESTEP) {
404        data = -2;              /* want non-atomic stepping */
405      }
406      break;
407
408    /* now ones where addr points to an output area */
409    case RPT_PGETTHREADREGS:
410      addr = (void*) out.addr.ptrace_addr_data_out_u.mem.data;
411      if (sizeof out.addr.ptrace_addr_data_out_u.mem.data <
412            REG_COUNT * sizeof(int)) {
413        setErrno(EINVAL);
414        break;
415      }
416      if (data == plst->thread) {
417        out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT;
418        out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs;
419        req = 0;                        /* force exit */
420        break;
421      }
422      req = RPT_GETTHREADREGS;
423      break;
424
425    case RPT_GETTHREADREGS:
426      addr = (void*) &out.addr.ptrace_addr_data_out_u.regs;
427      break;
428    case RPT_GETTHREADNAME:
429      out.addr.ptrace_addr_data_out_u.name = local_buff.t_name;
430      addr = (void*) out.addr.ptrace_addr_data_out_u.name;
431      break;
432    case RPT_THREADLIST:
433      out.addr.ptrace_addr_data_out_u.threads.threads =(ptThreadList) local_buff.t_list;
434      addr = (void*) out.addr.ptrace_addr_data_out_u.threads.threads;
435      break;
436    case RPT_READTEXT:
437    case RPT_READDATA:
438      if ((int) data < 0) {
439        setErrno(EINVAL);
440        break;
441      }
442      addr = (void *)in->addr.ptrace_addr_data_in_u.address;
443      addr2 = (void *)out.addr.ptrace_addr_data_out_u.mem.data;
444      out.addr.ptrace_addr_data_out_u.mem.dataNb = data;
445      break;
446    case RPT_DETACH:
447      /* Do not allow detaching if breakpoints still there */
448      if (BreakGet (plst, 0, NULL))
449      {                         /* some bkpts still set */
450        setErrno(EINVAL);               /* cannot detach safely */
451        break;
452      }
453      /* fall through */
454    case RPT_KILL:
455      /* in the event they are trying to detach or kill a terminated process,
456         we just delete the entry.                                      */
457      if (PROC_TERMINATED (plst))
458      {
459        TgtDelete(plst, -1, BMSG_KILLED);       /* just blow off */
460        req = 0;                /* now exit */
461      }
462      break;
463  }
464
465  if (getErrno())
466  {                             /* failed in code above */
467    out.result = -1;
468    out.errNo = getErrno();
469    DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo));
470    return(&out);
471  }
472  else if (!req)
473  {                             /* bail out now */
474    DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo));
475    return(&out);
476  }
477
478  /* OK, make the call */
479  out.result = TgtPtrace(req, pid, addr, data, addr2);
480  out.errNo = getErrno();
481
482  /* if no error, cleanup afterwards */
483  if (getErrno())
484  {
485      /* Remove step-emul breakpoints if any */
486    if (req == RPT_SINGLESTEP || req == RPT_CONT) {
487      BreakClear (plst, -1, -1);
488    }
489    DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo));
490    return(&out);               /* return error */
491  }
492
493  switch (in->addr.req)
494  {                             /* handle some special calls that affect state */
495    case RPT_CONT:
496    case RPT_STEPRANGE:
497      /* change to running */
498      if (in->addr.req == RPT_STEPRANGE)
499        plst->last_start = LAST_RANGE; /* so range steps */
500      else if (addr2)
501        plst->last_start = LAST_STEPOFF; /* now continue after wait */
502      else
503          plst->last_start = LAST_CONT;
504      plst->running = 1;        /* mark as running */
505      if (!rqstp) /* Called internally to restart bkpt, no msg to anybody */
506        break;
507      TgtNotifyAll(pid_idx, BMSG_WAIT, 0, 0, (in->flags & PTRFLG_NON_OWNER)
508                        ? -1 : conn_idx, True);
509      break;
510    case RPT_SINGLESTEP:
511      /* mark as step */
512      plst->last_start = LAST_STEP; /* so we know how started */
513      plst->running = 1;        /* mark as running (wait should catch fast) */
514      break;
515    case RPT_DETACH:            /* mark as disconnected */
516    case RPT_KILL:              /* mark as killed */
517      if (in->flags & PTRFLG_FREE) /* notify and delete entry */
518        TgtDelete(plst, -1, (in->addr.req==RPT_KILL) ? BMSG_KILLED : BMSG_DETACH);
519      else
520      {                         /* notify and mark */
521        plst->last_start = (in->addr.req==RPT_KILL) ?
522                LAST_KILLED : LAST_DETACHED;
523        plst->state = -1;
524        plst->running = False;
525        TgtNotifyAll(pid_idx, (in->addr.req==RPT_KILL) ?
526                BMSG_KILLED : BMSG_DETACH, 0, 0, -1, True);
527      }
528      break;
529    case RPT_SETTHREADREGS:
530    case RPT_PSETTHREADREGS:
531        if (data != plst->thread)
532          break;
533        DPRINTF(("ptrace_2_svc: pid %d target thread regs changed!\n", pid));
534
535    case RPT_SETREGS:
536    case RPT_PSETREGS:
537      /* change our buffer as well */
538      if (plst->regs.REG_PC != ((xdr_regs*)addr)->REG_PC)
539        BreakPcChanged (plst);
540      plst->regs = *(xdr_regs*) addr; /* copy in */
541      break;
542
543    /* case RPT_PGETREGS has been handled locally above */
544    case RPT_PGETTHREADREGS:
545        /* We need to update pointer so that XDR works on return */
546      out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT;
547      out.addr.ptrace_addr_data_out_u.pregs.pregs_val =
548          (void*) out.addr.ptrace_addr_data_out_u.mem.data;
549      break;
550
551    case RPT_PEEKTEXT:
552    case RPT_PEEKDATA:
553    case RPT_READDATA:
554    case RPT_READTEXT:
555      if (req < RPT_READDATA)
556      {                         /* peek */
557        /* addr is start */
558        data = sizeof(int);
559        addr2 = &out.result;    /* data buffer */
560        /* Like read: addr is start, data is length, addr2 is buffer */
561      }
562      BreakHide (plst, addr, data, addr2);
563      break;
564
565    case RPT_SETTARGETTHREAD:
566      DPRINTF(("ptrace_2_svc: pid %d new target thread %d\n", pid, data));
567      TgtPtrace (RPT_GETREGS, pid, (char*) &plst->regs, 0, NULL);
568      plst->thread = data;
569      if (plst->break_list) {   /* Forget we had to step off breakpoint */
570        BASE_BREAK* base = (BASE_BREAK*) plst->break_list;
571        DPRINTF(("ptrace_2_svc: clr_step %d last_break %d\n", base->clr_step,
572                base->last_break));
573        base->clr_step = 0;     /* Not stopped on break */
574        base->last_break = 0;
575      }
576      break;
577
578    case RPT_THREADLIST:
579      out.addr.ptrace_addr_data_out_u.threads.nbThread = out.result;     
580      break;
581
582    default:
583      break;
584  }                             /* end switch */
585  DPRINTF(("ptrace_2_svc 2: result %d errNo %d\n", out.result, out.errNo));
586  return(&out);
587}
588
589/* -----------------------------------------------------------------------
590   wait_info_2_svc - non-blocking wait request to check status.
591   ----------------------------------------------------------------------- */
592
593wait_out *RPCGENSRVNAME(wait_info_2_svc) (in, rqstp)
594     wait_in *in;
595     struct svc_req *rqstp;     /* server info */
596{
597  int           conn_idx = TspConnGetIndex(rqstp);
598  static wait_out out;          /* output of pid and status */
599  int           idx;
600  PID_LIST      *plst;
601
602  memset(&out, 0, sizeof(out)); /* zero for safety */
603  out.reason = STOP_ERROR;      /* assume the worst */
604
605  if (conn_idx == -1)
606  {                             /* no connection, error */
607    DPRINTF(("wait_info_2_svc: msg from unknown debugger!\n"));
608    out.wait_return = -1;
609    out.errNo = ECHILD;         /* closest error */
610    return(&out);
611  }
612  else
613  {                             /* see if confirming message received */
614    if (conn_list[conn_idx].retry)
615      TspMessageReceive(conn_idx, in->pid);
616  }
617
618  if (!in->pid)
619  {                             /* warm test verify only */
620    /* this call (pid==0) is made to confirm that that connection is still
621        active.         */
622    /* we let it fall through as an error since any use other than connection
623        reset would be an error (there is no pid0).                     */
624  }
625  else
626  {                             /* normal request */
627    idx = FindPidEntry (in->pid);
628    if (idx >= 0)
629    {                           /* found process they requested on */
630      plst = &pid_list[idx];
631      out.wait_return = plst->running ? 0 : in->pid;
632      /* return: 0 is running, pid is stopped/term */
633      out.errNo = 0;
634      out.status = plst->state; /* last stopped reason if stopped */
635      out.thread = plst->thread;/* current thread (or -1 if none) from stop */
636      if (!out.wait_return)
637        out.reason = STOP_NONE; /* running, no action */
638      else if (STS_SIGNALLED (out.status))
639      {                 /* stopped on signal */
640        out.handle = STS_GETSIG (out.status); /* signal number */
641        if (out.handle == SIGTRAP)
642          if (plst->is_step)
643          {                     /* single step with hitting a break */
644            out.reason = STOP_STEP;
645            out.handle = 0;     /* no information */
646          }
647          else
648          {                     /* stopped on break */
649            out.reason = STOP_BREAK;
650            if (plst->break_list)
651              out.handle = ((BASE_BREAK*)plst->break_list)->last_break;
652            else
653              out.handle = 0;   /* no break */
654          }
655        else
656          out.reason = STOP_SIGNAL;
657        out.PC = plst->regs.REG_PC; /* copy standard regs */
658        out.SP = plst->regs.REG_SP;
659        out.FP = plst->regs.REG_FP;
660      }
661      else
662      {                         /* terminated, so lower use count */
663        if (plst->last_start == LAST_KILLED)
664          out.reason = STOP_KILLED;
665        else if (plst->last_start == LAST_DETACHED)
666          out.reason = STOP_DETACHED;
667        else if (plst->last_start == LAST_START)
668        {                       /* failed in exec */
669          out.reason = STOP_SPAWN_FAILED;
670          out.handle = STS_GETCODE (out.status); /* errno reason */
671        }
672        else if (STS_TERMONSIG (out.status))
673        {                       /* terminated on signal */
674          out.reason = STOP_TERM_SIG;
675          /* mask off the core-dumped bit 7 */
676          out.handle = (int)(unsigned)(u_char) STS_TERMGETSIG (out.status);
677        }
678        else
679        {                       /* exit(2)ed */
680          out.reason = STOP_TERM_EXIT;
681          out.handle = STS_GETCODE (out.status); /* code */
682        }
683      }
684      DPRINTF(("wait_info_2_svc: pid %d return %d status %x errNo %d"
685        " reason %d handle %d pc %x sp %x fp %x thread %d\n",
686        in->pid, out.wait_return, out.status, out.errNo, out.reason,
687        out.handle, out.PC, out.SP, out.FP, out.thread));
688      return(&out);
689    }
690  }
691  /* if not found in list, we return error: no such process */
692  out.wait_return = -1;
693  out.errNo = ESRCH;            /* no process */
694  out.status = 0;
695  return(&out);
696}
697
698/* -----------------------------------------------------------------------
699   get_signal_names_2_svc - return names for signals
700   ----------------------------------------------------------------------- */
701
702static one_signal SignalNames[] = {
703    {SIGILL,    "SIGILL/EVT_ILL"},
704    {SIGTRAP,   "SIGTRAP/EVT_BKPT"},   
705    {SIGFPE,    "SIGFPE/EVT_FPE"},
706    {SIGKILL,   "SIGKILL/EVT_AKILL"},
707    {SIGSEGV,   "SIGSEGV/EVT_SEGV"},
708    {17,        "SIGSTOP"},             
709    {23,        "SIGSTOP"}             
710};
711
712get_signal_names_out* RPCGENSRVNAME(get_signal_names_2_svc) (in, rqstp)
713     void* in;
714     struct svc_req *rqstp;     /* server info */
715{
716  static get_signal_names_out out;
717
718  out.signals.all_signals_len = sizeof SignalNames / sizeof SignalNames[0];
719  out.signals.all_signals_val = SignalNames;
720
721  return(&out);
722}
Note: See TracBrowser for help on using the repository browser.