source: rtems/c/src/librdbg/src/servrpc.c @ 40cf43ea

4.104.114.84.95
Last change on this file since 40cf43ea was 40cf43ea, checked in by Joel Sherrill <joel.sherrill@…>, on 02/01/02 at 17:00:01
  • So many patches have been posted recently on the mailing list and because we were unable to find correct solution to compile on various linux distros (due to rpcgen incompatibilities), and because the coding style of rdbg was rather inconsistant among various pieces of code, I decided to:

1) make some cleaning regarding global coding style (using

indent + manual edits),

2) incorporate/review the paches send by various people

(S. Holford, T. Strauman),

3) Fix the bug due to varying rpcgen code generation

in remdeb_svc.c,

4) Remove some dead code,
5) Apply a patches enabling to call enterRdbg imediately

after rdbg initialization is done,

NB : the paches is huge but it is mainly due to coding styke chnages.
Only few lines of codes have been really changed and they do not impact
rdbg functionnality (AFAIKT).

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