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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [librdbg/] [src/] [servrpc.c] - Blame information for rev 389

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

Line No. Rev Author Line
1 30 unneback
/*
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: servrpc.c,v 1.2 2001-09-27 12:02:01 chris Exp $
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* 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
 
89
signal_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
 
105
void *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
 
122
ptrace_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
 
593
wait_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
 
702
static 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
 
712
get_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
}

powered by: WebSVN 2.1.0

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