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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [gdbserver/] [nto-low.c] - Blame information for rev 861

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

Line No. Rev Author Line
1 330 jeremybenn
/* QNX Neutrino specific low level interface, for the remote server
2
   for GDB.
3
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
 
21
#include "server.h"
22
#include "nto-low.h"
23
 
24
#include <limits.h>
25
#include <fcntl.h>
26
#include <spawn.h>
27
#include <sys/procfs.h>
28
#include <sys/auxv.h>
29
#include <stdarg.h>
30
#include <sys/iomgr.h>
31
#include <sys/neutrino.h>
32
 
33
 
34
extern int using_threads;
35
int using_threads = 1;
36
 
37
static void
38
nto_trace (const char *fmt, ...)
39
{
40
  va_list arg_list;
41
 
42
  if (debug_threads == 0)
43
    return;
44
  fprintf (stderr, "nto:");
45
  va_start (arg_list, fmt);
46
  vfprintf (stderr, fmt, arg_list);
47
  va_end (arg_list);
48
}
49
 
50
#define TRACE nto_trace
51
 
52
/* Structure holding neutrino specific information about
53
   inferior.  */
54
 
55
struct nto_inferior
56
{
57
  char nto_procfs_path[PATH_MAX];
58
  int ctl_fd;
59
  pid_t pid;
60
  int exit_signo; /* For tracking exit status.  */
61
};
62
 
63
static struct nto_inferior nto_inferior;
64
 
65
static void
66
init_nto_inferior (struct nto_inferior *nto_inferior)
67
{
68
  memset (nto_inferior, 0, sizeof (struct nto_inferior));
69
  nto_inferior->ctl_fd = -1;
70
  nto_inferior->pid = -1;
71
}
72
 
73
static void
74
do_detach (void)
75
{
76
  if (nto_inferior.ctl_fd != -1)
77
    {
78
      nto_trace ("Closing fd\n");
79
      close (nto_inferior.ctl_fd);
80
      init_nto_inferior (&nto_inferior);
81
    }
82
}
83
 
84
/* Set current thread. Return 1 on success, 0 otherwise.  */
85
 
86
static int
87
nto_set_thread (ptid_t ptid)
88
{
89
  int res = 0;
90
 
91
  TRACE ("%s pid: %d tid: %ld\n", __func__, ptid_get_pid (ptid),
92
         ptid_get_lwp (ptid));
93
  if (nto_inferior.ctl_fd != -1
94
      && !ptid_equal (ptid, null_ptid)
95
      && !ptid_equal (ptid, minus_one_ptid))
96
    {
97
      pthread_t tid = ptid_get_lwp (ptid);
98
 
99
      if (EOK == devctl (nto_inferior.ctl_fd, DCMD_PROC_CURTHREAD, &tid,
100
          sizeof (tid), 0))
101
        res = 1;
102
      else
103
        TRACE ("%s: Error: failed to set current thread\n", __func__);
104
    }
105
  return res;
106
}
107
 
108
/* This function will determine all alive threads.  Note that we do not list
109
   dead but unjoined threads even though they are still in the process' thread
110
   list.
111
 
112
   NTO_INFERIOR must not be NULL.  */
113
 
114
static void
115
nto_find_new_threads (struct nto_inferior *nto_inferior)
116
{
117
  pthread_t tid;
118
 
119
  TRACE ("%s pid:%d\n", __func__, nto_inferior->pid);
120
 
121
  if (nto_inferior->ctl_fd == -1)
122
    return;
123
 
124
  for (tid = 1;; ++tid)
125
    {
126
      procfs_status status;
127
      ptid_t ptid;
128
      int err;
129
 
130
      status.tid = tid;
131
      err = devctl (nto_inferior->ctl_fd, DCMD_PROC_TIDSTATUS, &status,
132
                    sizeof (status), 0);
133
 
134
      if (err != EOK || status.tid == 0)
135
        break;
136
 
137
      /* All threads in between are gone.  */
138
      while (tid != status.tid || status.state == STATE_DEAD)
139
        {
140
          struct thread_info *ti;
141
 
142
          ptid = ptid_build (nto_inferior->pid, tid, 0);
143
          ti = find_thread_ptid (ptid);
144
          if (ti != NULL)
145
            {
146
              TRACE ("Removing thread %d\n", tid);
147
              remove_thread (ti);
148
            }
149
          if (tid == status.tid)
150
            break;
151
          ++tid;
152
        }
153
 
154
      if (status.state != STATE_DEAD)
155
        {
156
          TRACE ("Adding thread %d\n", tid);
157
          ptid = ptid_build (nto_inferior->pid, tid, 0);
158
          if (!find_thread_ptid (ptid))
159
            add_thread (ptid, NULL);
160
        }
161
    }
162
}
163
 
164
/* Given pid, open procfs path.  */
165
 
166
static pid_t
167
do_attach (pid_t pid)
168
{
169
  procfs_status status;
170
  struct sigevent event;
171
 
172
  if (nto_inferior.ctl_fd != -1)
173
    {
174
      close (nto_inferior.ctl_fd);
175
      init_nto_inferior (&nto_inferior);
176
    }
177
  snprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
178
  nto_inferior.ctl_fd = open (nto_inferior.nto_procfs_path, O_RDWR);
179
  if (nto_inferior.ctl_fd == -1)
180
    {
181
      TRACE ("Failed to open %s\n", nto_inferior.nto_procfs_path);
182
      init_nto_inferior (&nto_inferior);
183
      return -1;
184
    }
185
  if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0)
186
      != EOK)
187
    {
188
      do_detach ();
189
      return -1;
190
    }
191
  nto_inferior.pid = pid;
192
  /* Define a sigevent for process stopped notification.  */
193
  event.sigev_notify = SIGEV_SIGNAL_THREAD;
194
  event.sigev_signo = SIGUSR1;
195
  event.sigev_code = 0;
196
  event.sigev_value.sival_ptr = NULL;
197
  event.sigev_priority = -1;
198
  devctl (nto_inferior.ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
199
 
200
  if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
201
              0) == EOK
202
      && (status.flags & _DEBUG_FLAG_STOPPED))
203
    {
204
      ptid_t ptid;
205
 
206
      kill (pid, SIGCONT);
207
      ptid = ptid_build (status.pid, status.tid, 0);
208
      the_low_target.arch_setup ();
209
      add_process (status.pid, 1);
210
      TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid,
211
             ptid_get_lwp (ptid));
212
      nto_find_new_threads (&nto_inferior);
213
    }
214
  else
215
    {
216
      do_detach ();
217
      return -1;
218
    }
219
 
220
  return pid;
221
}
222
 
223
/* Read or write LEN bytes from/to inferior's MEMADDR memory address
224
   into gdbservers's MYADDR buffer.  Return number of bytes actually
225
   transfered.  */
226
 
227
static int
228
nto_xfer_memory (off_t memaddr, unsigned char *myaddr, int len,
229
                 int dowrite)
230
{
231
  int nbytes = 0;
232
 
233
  if (lseek (nto_inferior.ctl_fd, memaddr, SEEK_SET) == memaddr)
234
    {
235
      if (dowrite)
236
        nbytes = write (nto_inferior.ctl_fd, myaddr, len);
237
      else
238
        nbytes = read (nto_inferior.ctl_fd, myaddr, len);
239
      if (nbytes < 0)
240
        nbytes = 0;
241
    }
242
  if (nbytes == 0)
243
    {
244
      int e = errno;
245
      TRACE ("Error in %s : errno=%d (%s)\n", __func__, e, strerror (e));
246
    }
247
  return nbytes;
248
}
249
 
250
/* Insert or remove breakpoint or watchpoint at address ADDR.
251
   TYPE can be one of Neutrino breakpoint types.  SIZE must be 0 for
252
   inserting the point, -1 for removing it.
253
 
254
   Return 0 on success, 1 otherwise.  */
255
 
256
static int
257
nto_breakpoint (CORE_ADDR addr, int type, int size)
258
{
259
  procfs_break brk;
260
 
261
  brk.type = type;
262
  brk.addr = addr;
263
  brk.size = size;
264
  if (devctl (nto_inferior.ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0)
265
      != EOK)
266
    return 1;
267
  return 0;
268
}
269
 
270
/* Read auxiliary vector from inferior's initial stack into gdbserver's
271
   MYADDR buffer, up to LEN bytes.
272
 
273
   Return number of bytes read.  */
274
 
275
static int
276
nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack,
277
                                  unsigned char *myaddr,
278
                                  unsigned int len)
279
{
280
  int data_ofs = 0;
281
  int anint;
282
  unsigned int len_read = 0;
283
 
284
  /* Skip over argc, argv and envp... Comment from ldd.c:
285
 
286
     The startup frame is set-up so that we have:
287
     auxv
288
     NULL
289
     ...
290
     envp2
291
     envp1 <----- void *frame + (argc + 2) * sizeof(char *)
292
     NULL
293
     ...
294
     argv2
295
     argv1
296
     argc  <------ void * frame
297
 
298
     On entry to ldd, frame gives the address of argc on the stack.  */
299
  if (nto_xfer_memory (initial_stack, (unsigned char *)&anint,
300
                       sizeof (anint), 0) != sizeof (anint))
301
    return 0;
302
 
303
  /* Size of pointer is assumed to be 4 bytes (32 bit arch. ) */
304
  data_ofs += (anint + 2) * sizeof (void *); /* + 2 comes from argc itself and
305
                                                NULL terminating pointer in
306
                                                argv.  */
307
 
308
  /* Now loop over env table:  */
309
  while (nto_xfer_memory (initial_stack + data_ofs,
310
                          (unsigned char *)&anint, sizeof (anint), 0)
311
         == sizeof (anint))
312
    {
313
      data_ofs += sizeof (anint);
314
      if (anint == 0)
315
        break;
316
    }
317
  initial_stack += data_ofs;
318
 
319
  memset (myaddr, 0, len);
320
  while (len_read <= len - sizeof (auxv_t))
321
    {
322
      auxv_t *auxv = (auxv_t *)myaddr;
323
 
324
      /* Search backwards until we have read AT_PHDR (num. 3),
325
         AT_PHENT (num 4), AT_PHNUM (num 5)  */
326
      if (nto_xfer_memory (initial_stack, (unsigned char *)auxv,
327
                           sizeof (auxv_t), 0) == sizeof (auxv_t))
328
        {
329
          if (auxv->a_type != AT_NULL)
330
            {
331
              auxv++;
332
              len_read += sizeof (auxv_t);
333
            }
334
          if (auxv->a_type == AT_PHNUM) /* That's all we need.  */
335
            break;
336
          initial_stack += sizeof (auxv_t);
337
        }
338
      else
339
        break;
340
    }
341
  TRACE ("auxv: len_read: %d\n", len_read);
342
  return len_read;
343
}
344
 
345
/* Start inferior specified by PROGRAM passing arguments ALLARGS.  */
346
 
347
static int
348
nto_create_inferior (char *program, char **allargs)
349
{
350
  struct inheritance inherit;
351
  pid_t pid;
352
  sigset_t set;
353
 
354
  TRACE ("%s %s\n", __func__, program);
355
  /* Clear any pending SIGUSR1's but keep the behavior the same.  */
356
  signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
357
 
358
  sigemptyset (&set);
359
  sigaddset (&set, SIGUSR1);
360
  sigprocmask (SIG_UNBLOCK, &set, NULL);
361
 
362
  memset (&inherit, 0, sizeof (inherit));
363
  inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
364
  inherit.pgroup = SPAWN_NEWPGROUP;
365
  pid = spawnp (program, 0, NULL, &inherit, allargs, 0);
366
  sigprocmask (SIG_BLOCK, &set, NULL);
367
 
368
  if (pid == -1)
369
    return -1;
370
 
371
  if (do_attach (pid) != pid)
372
    return -1;
373
 
374
  return pid;
375
}
376
 
377
/* Attach to process PID.  */
378
 
379
static int
380
nto_attach (unsigned long pid)
381
{
382
  TRACE ("%s %ld\n", __func__, pid);
383
  if (do_attach (pid) != pid)
384
    error ("Unable to attach to %ld\n", pid);
385
  return 0;
386
}
387
 
388
/* Send signal to process PID.  */
389
 
390
static int
391
nto_kill (int pid)
392
{
393
  TRACE ("%s %d\n", __func__, pid);
394
  kill (pid, SIGKILL);
395
  do_detach ();
396
  return 0;
397
}
398
 
399
/* Detach from process PID.  */
400
 
401
static int
402
nto_detach (int pid)
403
{
404
  TRACE ("%s %d\n", __func__, pid);
405
  do_detach ();
406
  return 0;
407
}
408
 
409
static void
410
nto_mourn (struct process_info *process)
411
{
412
  remove_process (process);
413
}
414
 
415
/* Check if the given thread is alive.
416
 
417
   Return 1 if alive, 0 otherwise.  */
418
 
419
static int
420
nto_thread_alive (ptid_t ptid)
421
{
422
  int res;
423
 
424
  TRACE ("%s pid:%d tid:%d\n", __func__, ptid_get_pid (ptid),
425
         ptid_get_lwp (ptid));
426
  if (SignalKill (0, ptid_get_pid (ptid), ptid_get_lwp (ptid),
427
                  0, 0, 0) == -1)
428
    res = 0;
429
  else
430
    res = 1;
431
  TRACE ("%s: %s\n", __func__, res ? "yes" : "no");
432
  return res;
433
}
434
 
435
/* Resume inferior's execution.  */
436
 
437
static void
438
nto_resume (struct thread_resume *resume_info, size_t n)
439
{
440
  /* We can only work in all-stop mode.  */
441
  procfs_status status;
442
  procfs_run run;
443
  int err;
444
 
445
  TRACE ("%s\n", __func__);
446
  /* Workaround for aliasing rules violation. */
447
  sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
448
 
449
  nto_set_thread (resume_info->thread);
450
 
451
  run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
452
  if (resume_info->kind == resume_step)
453
    run.flags |= _DEBUG_RUN_STEP;
454
  run.flags |= _DEBUG_RUN_ARM;
455
 
456
  sigemptyset (run_fault);
457
  sigaddset (run_fault, FLTBPT);
458
  sigaddset (run_fault, FLTTRACE);
459
  sigaddset (run_fault, FLTILL);
460
  sigaddset (run_fault, FLTPRIV);
461
  sigaddset (run_fault, FLTBOUNDS);
462
  sigaddset (run_fault, FLTIOVF);
463
  sigaddset (run_fault, FLTIZDIV);
464
  sigaddset (run_fault, FLTFPE);
465
  sigaddset (run_fault, FLTPAGE);
466
  sigaddset (run_fault, FLTSTACK);
467
  sigaddset (run_fault, FLTACCESS);
468
 
469
  sigemptyset (&run.trace);
470
  if (resume_info->sig)
471
    {
472
      int signal_to_pass;
473
 
474
      devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
475
              0);
476
      signal_to_pass = resume_info->sig;
477
      if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
478
        {
479
          if (signal_to_pass != status.info.si_signo)
480
            {
481
              kill (status.pid, signal_to_pass);
482
              run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
483
            }
484
          else          /* Let it kill the program without telling us.  */
485
            sigdelset (&run.trace, signal_to_pass);
486
        }
487
    }
488
  else
489
    run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
490
 
491
  sigfillset (&run.trace);
492
 
493
  regcache_invalidate ();
494
 
495
  err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
496
  if (err != EOK)
497
    TRACE ("Error: %d \"%s\"\n", err, strerror (err));
498
}
499
 
500
/* Wait for inferior's event.
501
 
502
   Return ptid of thread that caused the event.  */
503
 
504
static ptid_t
505
nto_wait (ptid_t ptid,
506
          struct target_waitstatus *ourstatus, int target_options)
507
{
508
  sigset_t set;
509
  siginfo_t info;
510
  procfs_status status;
511
  const int trace_mask = (_DEBUG_FLAG_TRACE_EXEC | _DEBUG_FLAG_TRACE_RD
512
                          | _DEBUG_FLAG_TRACE_WR | _DEBUG_FLAG_TRACE_MODIFY);
513
 
514
  TRACE ("%s\n", __func__);
515
 
516
  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
517
 
518
  sigemptyset (&set);
519
  sigaddset (&set, SIGUSR1);
520
 
521
  devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
522
  while (!(status.flags & _DEBUG_FLAG_ISTOP))
523
    {
524
      sigwaitinfo (&set, &info);
525
      devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
526
              0);
527
    }
528
  nto_find_new_threads (&nto_inferior);
529
 
530
  if (status.flags & _DEBUG_FLAG_SSTEP)
531
    {
532
      TRACE ("SSTEP\n");
533
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
534
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
535
    }
536
  /* Was it a breakpoint?  */
537
  else if (status.flags & trace_mask)
538
    {
539
      TRACE ("STOPPED\n");
540
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
541
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
542
    }
543
  else if (status.flags & _DEBUG_FLAG_ISTOP)
544
    {
545
      TRACE ("ISTOP\n");
546
      switch (status.why)
547
        {
548
        case _DEBUG_WHY_SIGNALLED:
549
          TRACE ("  SIGNALLED\n");
550
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
551
          ourstatus->value.sig =
552
            target_signal_from_host (status.info.si_signo);
553
          nto_inferior.exit_signo = ourstatus->value.sig;
554
          break;
555
        case _DEBUG_WHY_FAULTED:
556
          TRACE ("  FAULTED\n");
557
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
558
          if (status.info.si_signo == SIGTRAP)
559
            {
560
              ourstatus->value.sig = 0;
561
              nto_inferior.exit_signo = 0;
562
            }
563
          else
564
            {
565
              ourstatus->value.sig =
566
                target_signal_from_host (status.info.si_signo);
567
              nto_inferior.exit_signo = ourstatus->value.sig;
568
            }
569
          break;
570
 
571
        case _DEBUG_WHY_TERMINATED:
572
          {
573
            int waitval = 0;
574
 
575
            TRACE ("  TERMINATED\n");
576
            waitpid (ptid_get_pid (ptid), &waitval, WNOHANG);
577
            if (nto_inferior.exit_signo)
578
              {
579
                /* Abnormal death.  */
580
                ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
581
                ourstatus->value.sig = nto_inferior.exit_signo;
582
              }
583
            else
584
              {
585
                /* Normal death.  */
586
                ourstatus->kind = TARGET_WAITKIND_EXITED;
587
                ourstatus->value.integer = WEXITSTATUS (waitval);
588
              }
589
            nto_inferior.exit_signo = 0;
590
            break;
591
          }
592
 
593
        case _DEBUG_WHY_REQUESTED:
594
          TRACE ("REQUESTED\n");
595
          /* We are assuming a requested stop is due to a SIGINT.  */
596
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
597
          ourstatus->value.sig = TARGET_SIGNAL_INT;
598
          nto_inferior.exit_signo = 0;
599
          break;
600
        }
601
    }
602
 
603
  return ptid_build (status.pid, status.tid, 0);
604
}
605
 
606
/* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR).
607
   If REGNO is -1, fetch all registers, or REGNO register only otherwise.  */
608
 
609
static void
610
nto_fetch_registers (struct regcache *regcache, int regno)
611
{
612
  int regsize;
613
  procfs_greg greg;
614
  ptid_t ptid;
615
 
616
  TRACE ("%s (regno=%d)\n", __func__, regno);
617
  if (regno >= the_low_target.num_regs)
618
    return;
619
 
620
  if (current_inferior == NULL)
621
    {
622
      TRACE ("current_inferior is NULL\n");
623
      return;
624
    }
625
  ptid = thread_to_gdb_id (current_inferior);
626
  if (!nto_set_thread (ptid))
627
    return;
628
 
629
  if (devctl (nto_inferior.ctl_fd, DCMD_PROC_GETGREG, &greg, sizeof (greg),
630
              &regsize) == EOK)
631
    {
632
      if (regno == -1) /* All registers. */
633
        {
634
          for (regno = 0; regno != the_low_target.num_regs; ++regno)
635
            {
636
              const unsigned int registeroffset
637
                = the_low_target.register_offset (regno);
638
              supply_register (regcache, regno, ((char *)&greg) + registeroffset);
639
            }
640
        }
641
      else
642
        {
643
          const unsigned int registeroffset
644
            = the_low_target.register_offset (regno);
645
          if (registeroffset == -1)
646
            return;
647
          supply_register (regcache, regno, ((char *)&greg) + registeroffset);
648
        }
649
    }
650
  else
651
    TRACE ("ERROR reading registers from inferior.\n");
652
}
653
 
654
/* Store registers for currently selected thread (CURRENT_INFERIOR).
655
   We always store all registers, regardless of REGNO.  */
656
 
657
static void
658
nto_store_registers (struct regcache *regcache, int regno)
659
{
660
  procfs_greg greg;
661
  int err;
662
  ptid_t ptid;
663
 
664
  TRACE ("%s (regno:%d)\n", __func__, regno);
665
 
666
  if (current_inferior == NULL)
667
    {
668
      TRACE ("current_inferior is NULL\n");
669
      return;
670
    }
671
  ptid = thread_to_gdb_id (current_inferior);
672
  if (!nto_set_thread (ptid))
673
    return;
674
 
675
  memset (&greg, 0, sizeof (greg));
676
  for  (regno = 0; regno != the_low_target.num_regs; ++regno)
677
    {
678
      const unsigned int regoffset
679
        = the_low_target.register_offset (regno);
680
      collect_register (regcache, regno, ((char *)&greg) + regoffset);
681
    }
682
  err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg),
683
                0);
684
  if (err != EOK)
685
    TRACE ("Error: setting registers.\n");
686
}
687
 
688
/* Read LEN bytes from inferior's memory address MEMADDR into
689
   gdbserver's MYADDR buffer.
690
 
691
   Return 0 on success -1 otherwise.  */
692
 
693
static int
694
nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
695
{
696
  TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__, memaddr, len);
697
 
698
  if (nto_xfer_memory (memaddr, myaddr, len, 0) != len)
699
    {
700
      TRACE ("Failed to read memory\n");
701
      return -1;
702
    }
703
 
704
  return 0;
705
}
706
 
707
/* Write LEN bytes from gdbserver's buffer MYADDR into inferior's
708
   memory at address MEMADDR.
709
 
710
   Return 0 on success -1 otherwise.  */
711
 
712
static int
713
nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
714
{
715
  int len_written;
716
 
717
  TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len);
718
  if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len,
719
                                      1))
720
      != len)
721
    {
722
      TRACE ("Wanted to write: %d but written: %d\n", len, len_written);
723
      return -1;
724
    }
725
 
726
  return 0;
727
}
728
 
729
/* Stop inferior.  We always stop all threads.  */
730
 
731
static void
732
nto_request_interrupt (void)
733
{
734
  TRACE ("%s\n", __func__);
735
  nto_set_thread (ptid_build (nto_inferior.pid, 1, 0));
736
  if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0))
737
    TRACE ("Error stopping inferior.\n");
738
}
739
 
740
/* Read auxiliary vector from inferior's memory into gdbserver's buffer
741
   MYADDR.  We always read whole auxv.
742
 
743
   Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0
744
   or -1 on error.  */
745
 
746
static int
747
nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
748
{
749
  int err;
750
  CORE_ADDR initial_stack;
751
  procfs_info procinfo;
752
 
753
  TRACE ("%s\n", __func__);
754
  if (offset > 0)
755
    return 0;
756
 
757
  err = devctl (nto_inferior.ctl_fd, DCMD_PROC_INFO, &procinfo,
758
                sizeof procinfo, 0);
759
  if (err != EOK)
760
    return -1;
761
 
762
  initial_stack = procinfo.initial_stack;
763
 
764
  return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
765
}
766
 
767
/* Insert {break/watch}point at address ADDR.
768
   TYPE must be in '0'..'4' range.  LEN is not used.  */
769
 
770
static int
771
nto_insert_point (char type, CORE_ADDR addr, int len)
772
{
773
  int wtype = _DEBUG_BREAK_HW; /* Always request HW.  */
774
 
775
  TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
776
  switch (type)
777
    {
778
    case '0': /* software-breakpoint */
779
      wtype = _DEBUG_BREAK_EXEC;
780
      break;
781
    case '1': /* hardware-breakpoint */
782
      wtype |= _DEBUG_BREAK_EXEC;
783
      break;
784
    case '2':  /* write watchpoint */
785
      wtype |= _DEBUG_BREAK_RW;
786
      break;
787
    case '3':  /* read watchpoint */
788
      wtype |= _DEBUG_BREAK_RD;
789
      break;
790
    case '4':  /* access watchpoint */
791
      wtype |= _DEBUG_BREAK_RW;
792
      break;
793
    default:
794
      return 1; /* Not supported.  */
795
    }
796
  return nto_breakpoint (addr, wtype, 0);
797
}
798
 
799
/* Remove {break/watch}point at address ADDR.
800
   TYPE must be in '0'..'4' range.  LEN is not used.  */
801
 
802
static int
803
nto_remove_point (char type, CORE_ADDR addr, int len)
804
{
805
  int wtype = _DEBUG_BREAK_HW; /* Always request HW.  */
806
 
807
  TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
808
  switch (type)
809
    {
810
    case '0': /* software-breakpoint */
811
      wtype = _DEBUG_BREAK_EXEC;
812
      break;
813
    case '1': /* hardware-breakpoint */
814
      wtype |= _DEBUG_BREAK_EXEC;
815
      break;
816
    case '2':  /* write watchpoint */
817
      wtype |= _DEBUG_BREAK_RW;
818
      break;
819
    case '3':  /* read watchpoint */
820
      wtype |= _DEBUG_BREAK_RD;
821
      break;
822
    case '4':  /* access watchpoint */
823
      wtype |= _DEBUG_BREAK_RW;
824
      break;
825
    default:
826
      return 1; /* Not supported.  */
827
    }
828
  return nto_breakpoint (addr, wtype, -1);
829
}
830
 
831
/* Check if the reason of stop for current thread (CURRENT_INFERIOR) is
832
   a watchpoint.
833
 
834
   Return 1 if stopped by watchpoint, 0 otherwise.  */
835
 
836
static int
837
nto_stopped_by_watchpoint (void)
838
{
839
  int ret = 0;
840
 
841
  TRACE ("%s\n", __func__);
842
  if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
843
    {
844
      ptid_t ptid;
845
 
846
      ptid = thread_to_gdb_id (current_inferior);
847
      if (nto_set_thread (ptid))
848
        {
849
          const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
850
                                | _DEBUG_FLAG_TRACE_MODIFY;
851
          procfs_status status;
852
          int err;
853
 
854
          err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
855
                        sizeof (status), 0);
856
          if (err == EOK && (status.flags & watchmask))
857
            ret = 1;
858
        }
859
    }
860
  TRACE ("%s: %s\n", __func__, ret ? "yes" : "no");
861
  return ret;
862
}
863
 
864
/* Get instruction pointer for CURRENT_INFERIOR thread.
865
 
866
   Return inferior's instruction pointer value, or 0 on error.  */
867
 
868
static CORE_ADDR
869
nto_stopped_data_address (void)
870
{
871
  CORE_ADDR ret = (CORE_ADDR)0;
872
 
873
  TRACE ("%s\n", __func__);
874
  if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
875
    {
876
      ptid_t ptid;
877
 
878
      ptid = thread_to_gdb_id (current_inferior);
879
 
880
      if (nto_set_thread (ptid))
881
        {
882
          procfs_status status;
883
 
884
          if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
885
                      sizeof (status), 0) == EOK)
886
            ret = status.ip;
887
        }
888
    }
889
  TRACE ("%s: 0x%08lx\n", __func__, ret);
890
  return ret;
891
}
892
 
893
/* We do not currently support non-stop.  */
894
 
895
static int
896
nto_supports_non_stop (void)
897
{
898
  TRACE ("%s\n", __func__);
899
  return 0;
900
}
901
 
902
 
903
 
904
static struct target_ops nto_target_ops = {
905
  nto_create_inferior,
906
  nto_attach,
907
  nto_kill,
908
  nto_detach,
909
  nto_mourn,
910
  NULL, /* nto_join */
911
  nto_thread_alive,
912
  nto_resume,
913
  nto_wait,
914
  nto_fetch_registers,
915
  nto_store_registers,
916
  nto_read_memory,
917
  nto_write_memory,
918
  NULL, /* nto_look_up_symbols */
919
  nto_request_interrupt,
920
  nto_read_auxv,
921
  nto_insert_point,
922
  nto_remove_point,
923
  nto_stopped_by_watchpoint,
924
  nto_stopped_data_address,
925
  NULL, /* nto_read_offsets */
926
  NULL, /* thread_db_set_tls_address */
927
  NULL,
928
  hostio_last_error_from_errno,
929
  NULL, /* nto_qxfer_osdata */
930
  NULL, /* xfer_siginfo */
931
  nto_supports_non_stop,
932
  NULL, /* async */
933
  NULL  /* start_non_stop */
934
};
935
 
936
 
937
/* Global function called by server.c.  Initializes QNX Neutrino
938
   gdbserver.  */
939
 
940
void
941
initialize_low (void)
942
{
943
  sigset_t set;
944
 
945
  TRACE ("%s\n", __func__);
946
  set_target_ops (&nto_target_ops);
947
  set_breakpoint_data (the_low_target.breakpoint,
948
                       the_low_target.breakpoint_len);
949
 
950
  /* We use SIGUSR1 to gain control after we block waiting for a process.
951
     We use sigwaitevent to wait.  */
952
  sigemptyset (&set);
953
  sigaddset (&set, SIGUSR1);
954
  sigprocmask (SIG_BLOCK, &set, NULL);
955
}
956
 

powered by: WebSVN 2.1.0

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