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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [librdbg/] [src/] [servrpc.c] - Blame information for rev 1780

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

Line No. Rev Author Line
1 1026 ivang
/*
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
 * servrpc.c,v 1.3 2002/02/01 17:00:01 joel 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 *
35
RPCGENSRVNAME (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 *
95
RPCGENSRVNAME (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 *
115
RPCGENSRVNAME (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 *
134
RPCGENSRVNAME (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 *
654
RPCGENSRVNAME (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
 
752
static 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 *
763
RPCGENSRVNAME (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
}

powered by: WebSVN 2.1.0

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