source: rtems/c/src/librdbg/src/servrpc.c @ 4721cf1

4.104.114.84.95
Last change on this file since 4721cf1 was 4721cf1, checked in by Joel Sherrill <joel.sherrill@…>, on 12/03/98 at 23:54:14

Patch from Emmanuel Raguet <raguet@…> to add remote debug server
and RPC support to RTEMS. Thanks. :) Email follows:

Hello,

For Xmas, here is the Remote Debugger on RTEMS !

Here are 2 patches for the Remote Debugger on RTEMS for pc386 from Linux
host :

  • one for RTEMS it self,
  • one for GDB-4.17.

1/ RTEMS patch
--------------

This patch adds 2 libraries :

  • a simplified SUN RPC library
  • the Remote Debugger library

The configuration command is the following :
../rtems4/configure --target=i386-rtemself --enable-rtemsbsp=pc386
--enable-rdbg

The SUN RPC library is built only if networking is set.
The RDBG library is built if networking and enable-rdbg are set.

The function used to initialize the debugger is :

rtems_rdbg_initialize ();

A special function has been created to force a task to be
in a "debug" state : enterRdbg().
The use of this function is not mandatory.

2/ GDB-4.17 patch
-----------------

This patch create a new RTEMS target for GDB-4.17.

The configuration command is the following :
./configure --enable-shared --target=i386RTEMS

To connect to a target, use :

target rtems [your_site_address]

Then, attach the target using : attach 1

And... Debug ;)

You can obtain the original GDB-4.17 on
ftp://ftp.debian.org/debian/dists/stable/main/source/devel/gdb_4.17.orig.tar.gz

This has been tested from a Debian 2.0.1 linux host.

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