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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [gdbserver/] [nto-low.c] - Blame information for rev 833

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

Line No. Rev Author Line
1 227 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
/* Check if the given thread is alive.
410
 
411
   Return 1 if alive, 0 otherwise.  */
412
 
413
static int
414
nto_thread_alive (ptid_t ptid)
415
{
416
  int res;
417
 
418
  TRACE ("%s pid:%d tid:%d\n", __func__, ptid_get_pid (ptid),
419
         ptid_get_lwp (ptid));
420
  if (SignalKill (0, ptid_get_pid (ptid), ptid_get_lwp (ptid),
421
                  0, 0, 0) == -1)
422
    res = 0;
423
  else
424
    res = 1;
425
  TRACE ("%s: %s\n", __func__, res ? "yes" : "no");
426
  return res;
427
}
428
 
429
/* Resume inferior's execution.  */
430
 
431
static void
432
nto_resume (struct thread_resume *resume_info, size_t n)
433
{
434
  /* We can only work in all-stop mode.  */
435
  procfs_status status;
436
  procfs_run run;
437
  int err;
438
 
439
  TRACE ("%s\n", __func__);
440
  /* Workaround for aliasing rules violation. */
441
  sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
442
 
443
  nto_set_thread (resume_info->thread);
444
 
445
  run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
446
  if (resume_info->kind == resume_step)
447
    run.flags |= _DEBUG_RUN_STEP;
448
  run.flags |= _DEBUG_RUN_ARM;
449
 
450
  sigemptyset (run_fault);
451
  sigaddset (run_fault, FLTBPT);
452
  sigaddset (run_fault, FLTTRACE);
453
  sigaddset (run_fault, FLTILL);
454
  sigaddset (run_fault, FLTPRIV);
455
  sigaddset (run_fault, FLTBOUNDS);
456
  sigaddset (run_fault, FLTIOVF);
457
  sigaddset (run_fault, FLTIZDIV);
458
  sigaddset (run_fault, FLTFPE);
459
  sigaddset (run_fault, FLTPAGE);
460
  sigaddset (run_fault, FLTSTACK);
461
  sigaddset (run_fault, FLTACCESS);
462
 
463
  sigemptyset (&run.trace);
464
  if (resume_info->sig)
465
    {
466
      int signal_to_pass;
467
 
468
      devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
469
              0);
470
      signal_to_pass = resume_info->sig;
471
      if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
472
        {
473
          if (signal_to_pass != status.info.si_signo)
474
            {
475
              kill (status.pid, signal_to_pass);
476
              run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
477
            }
478
          else          /* Let it kill the program without telling us.  */
479
            sigdelset (&run.trace, signal_to_pass);
480
        }
481
    }
482
  else
483
    run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
484
 
485
  sigfillset (&run.trace);
486
 
487
  regcache_invalidate ();
488
 
489
  err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
490
  if (err != EOK)
491
    TRACE ("Error: %d \"%s\"\n", err, strerror (err));
492
}
493
 
494
/* Wait for inferior's event.
495
 
496
   Return ptid of thread that caused the event.  */
497
 
498
static ptid_t
499
nto_wait (ptid_t ptid,
500
          struct target_waitstatus *ourstatus, int target_options)
501
{
502
  sigset_t set;
503
  siginfo_t info;
504
  procfs_status status;
505
  const int trace_mask = (_DEBUG_FLAG_TRACE_EXEC | _DEBUG_FLAG_TRACE_RD
506
                          | _DEBUG_FLAG_TRACE_WR | _DEBUG_FLAG_TRACE_MODIFY);
507
 
508
  TRACE ("%s\n", __func__);
509
 
510
  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
511
 
512
  sigemptyset (&set);
513
  sigaddset (&set, SIGUSR1);
514
 
515
  devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
516
  while (!(status.flags & _DEBUG_FLAG_ISTOP))
517
    {
518
      sigwaitinfo (&set, &info);
519
      devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
520
              0);
521
    }
522
  nto_find_new_threads (&nto_inferior);
523
 
524
  if (status.flags & _DEBUG_FLAG_SSTEP)
525
    {
526
      TRACE ("SSTEP\n");
527
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
528
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
529
    }
530
  /* Was it a breakpoint?  */
531
  else if (status.flags & trace_mask)
532
    {
533
      TRACE ("STOPPED\n");
534
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
535
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
536
    }
537
  else if (status.flags & _DEBUG_FLAG_ISTOP)
538
    {
539
      TRACE ("ISTOP\n");
540
      switch (status.why)
541
        {
542
        case _DEBUG_WHY_SIGNALLED:
543
          TRACE ("  SIGNALLED\n");
544
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
545
          ourstatus->value.sig =
546
            target_signal_from_host (status.info.si_signo);
547
          nto_inferior.exit_signo = ourstatus->value.sig;
548
          break;
549
        case _DEBUG_WHY_FAULTED:
550
          TRACE ("  FAULTED\n");
551
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
552
          if (status.info.si_signo == SIGTRAP)
553
            {
554
              ourstatus->value.sig = 0;
555
              nto_inferior.exit_signo = 0;
556
            }
557
          else
558
            {
559
              ourstatus->value.sig =
560
                target_signal_from_host (status.info.si_signo);
561
              nto_inferior.exit_signo = ourstatus->value.sig;
562
            }
563
          break;
564
 
565
        case _DEBUG_WHY_TERMINATED:
566
          {
567
            int waitval = 0;
568
 
569
            TRACE ("  TERMINATED\n");
570
            waitpid (ptid_get_pid (ptid), &waitval, WNOHANG);
571
            if (nto_inferior.exit_signo)
572
              {
573
                /* Abnormal death.  */
574
                ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
575
                ourstatus->value.sig = nto_inferior.exit_signo;
576
              }
577
            else
578
              {
579
                /* Normal death.  */
580
                ourstatus->kind = TARGET_WAITKIND_EXITED;
581
                ourstatus->value.integer = WEXITSTATUS (waitval);
582
              }
583
            nto_inferior.exit_signo = 0;
584
            break;
585
          }
586
 
587
        case _DEBUG_WHY_REQUESTED:
588
          TRACE ("REQUESTED\n");
589
          /* We are assuming a requested stop is due to a SIGINT.  */
590
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
591
          ourstatus->value.sig = TARGET_SIGNAL_INT;
592
          nto_inferior.exit_signo = 0;
593
          break;
594
        }
595
    }
596
 
597
  return ptid_build (status.pid, status.tid, 0);
598
}
599
 
600
/* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR).
601
   If REGNO is -1, fetch all registers, or REGNO register only otherwise.  */
602
 
603
static void
604
nto_fetch_registers (struct regcache *regcache, int regno)
605
{
606
  int regsize;
607
  procfs_greg greg;
608
  ptid_t ptid;
609
 
610
  TRACE ("%s (regno=%d)\n", __func__, regno);
611
  if (regno >= the_low_target.num_regs)
612
    return;
613
 
614
  if (current_inferior == NULL)
615
    {
616
      TRACE ("current_inferior is NULL\n");
617
      return;
618
    }
619
  ptid = thread_to_gdb_id (current_inferior);
620
  if (!nto_set_thread (ptid))
621
    return;
622
 
623
  if (devctl (nto_inferior.ctl_fd, DCMD_PROC_GETGREG, &greg, sizeof (greg),
624
              &regsize) == EOK)
625
    {
626
      if (regno == -1) /* All registers. */
627
        {
628
          for (regno = 0; regno != the_low_target.num_regs; ++regno)
629
            {
630
              const unsigned int registeroffset
631
                = the_low_target.register_offset (regno);
632
              supply_register (regcache, regno, ((char *)&greg) + registeroffset);
633
            }
634
        }
635
      else
636
        {
637
          const unsigned int registeroffset
638
            = the_low_target.register_offset (regno);
639
          if (registeroffset == -1)
640
            return;
641
          supply_register (regcache, regno, ((char *)&greg) + registeroffset);
642
        }
643
    }
644
  else
645
    TRACE ("ERROR reading registers from inferior.\n");
646
}
647
 
648
/* Store registers for currently selected thread (CURRENT_INFERIOR).
649
   We always store all registers, regardless of REGNO.  */
650
 
651
static void
652
nto_store_registers (struct regcache *regcache, int regno)
653
{
654
  procfs_greg greg;
655
  int err;
656
  ptid_t ptid;
657
 
658
  TRACE ("%s (regno:%d)\n", __func__, regno);
659
 
660
  if (current_inferior == NULL)
661
    {
662
      TRACE ("current_inferior is NULL\n");
663
      return;
664
    }
665
  ptid = thread_to_gdb_id (current_inferior);
666
  if (!nto_set_thread (ptid))
667
    return;
668
 
669
  memset (&greg, 0, sizeof (greg));
670
  for  (regno = 0; regno != the_low_target.num_regs; ++regno)
671
    {
672
      const unsigned int regoffset
673
        = the_low_target.register_offset (regno);
674
      collect_register (regcache, regno, ((char *)&greg) + regoffset);
675
    }
676
  err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg),
677
                0);
678
  if (err != EOK)
679
    TRACE ("Error: setting registers.\n");
680
}
681
 
682
/* Read LEN bytes from inferior's memory address MEMADDR into
683
   gdbserver's MYADDR buffer.
684
 
685
   Return 0 on success -1 otherwise.  */
686
 
687
static int
688
nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
689
{
690
  TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__, memaddr, len);
691
 
692
  if (nto_xfer_memory (memaddr, myaddr, len, 0) != len)
693
    {
694
      TRACE ("Failed to read memory\n");
695
      return -1;
696
    }
697
 
698
  return 0;
699
}
700
 
701
/* Write LEN bytes from gdbserver's buffer MYADDR into inferior's
702
   memory at address MEMADDR.
703
 
704
   Return 0 on success -1 otherwise.  */
705
 
706
static int
707
nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
708
{
709
  int len_written;
710
 
711
  TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len);
712
  if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len,
713
                                      1))
714
      != len)
715
    {
716
      TRACE ("Wanted to write: %d but written: %d\n", len, len_written);
717
      return -1;
718
    }
719
 
720
  return 0;
721
}
722
 
723
/* Stop inferior.  We always stop all threads.  */
724
 
725
static void
726
nto_request_interrupt (void)
727
{
728
  TRACE ("%s\n", __func__);
729
  nto_set_thread (ptid_build (nto_inferior.pid, 1, 0));
730
  if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0))
731
    TRACE ("Error stopping inferior.\n");
732
}
733
 
734
/* Read auxiliary vector from inferior's memory into gdbserver's buffer
735
   MYADDR.  We always read whole auxv.
736
 
737
   Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0
738
   or -1 on error.  */
739
 
740
static int
741
nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
742
{
743
  int err;
744
  CORE_ADDR initial_stack;
745
  procfs_info procinfo;
746
 
747
  TRACE ("%s\n", __func__);
748
  if (offset > 0)
749
    return 0;
750
 
751
  err = devctl (nto_inferior.ctl_fd, DCMD_PROC_INFO, &procinfo,
752
                sizeof procinfo, 0);
753
  if (err != EOK)
754
    return -1;
755
 
756
  initial_stack = procinfo.initial_stack;
757
 
758
  return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
759
}
760
 
761
/* Insert {break/watch}point at address ADDR.
762
   TYPE must be in '0'..'4' range.  LEN is not used.  */
763
 
764
static int
765
nto_insert_point (char type, CORE_ADDR addr, int len)
766
{
767
  int wtype = _DEBUG_BREAK_HW; /* Always request HW.  */
768
 
769
  TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
770
  switch (type)
771
    {
772
    case '0': /* software-breakpoint */
773
      wtype = _DEBUG_BREAK_EXEC;
774
      break;
775
    case '1': /* hardware-breakpoint */
776
      wtype |= _DEBUG_BREAK_EXEC;
777
      break;
778
    case '2':  /* write watchpoint */
779
      wtype |= _DEBUG_BREAK_RW;
780
      break;
781
    case '3':  /* read watchpoint */
782
      wtype |= _DEBUG_BREAK_RD;
783
      break;
784
    case '4':  /* access watchpoint */
785
      wtype |= _DEBUG_BREAK_RW;
786
      break;
787
    default:
788
      return 1; /* Not supported.  */
789
    }
790
  return nto_breakpoint (addr, wtype, 0);
791
}
792
 
793
/* Remove {break/watch}point at address ADDR.
794
   TYPE must be in '0'..'4' range.  LEN is not used.  */
795
 
796
static int
797
nto_remove_point (char type, CORE_ADDR addr, int len)
798
{
799
  int wtype = _DEBUG_BREAK_HW; /* Always request HW.  */
800
 
801
  TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
802
  switch (type)
803
    {
804
    case '0': /* software-breakpoint */
805
      wtype = _DEBUG_BREAK_EXEC;
806
      break;
807
    case '1': /* hardware-breakpoint */
808
      wtype |= _DEBUG_BREAK_EXEC;
809
      break;
810
    case '2':  /* write watchpoint */
811
      wtype |= _DEBUG_BREAK_RW;
812
      break;
813
    case '3':  /* read watchpoint */
814
      wtype |= _DEBUG_BREAK_RD;
815
      break;
816
    case '4':  /* access watchpoint */
817
      wtype |= _DEBUG_BREAK_RW;
818
      break;
819
    default:
820
      return 1; /* Not supported.  */
821
    }
822
  return nto_breakpoint (addr, wtype, -1);
823
}
824
 
825
/* Check if the reason of stop for current thread (CURRENT_INFERIOR) is
826
   a watchpoint.
827
 
828
   Return 1 if stopped by watchpoint, 0 otherwise.  */
829
 
830
static int
831
nto_stopped_by_watchpoint (void)
832
{
833
  int ret = 0;
834
 
835
  TRACE ("%s\n", __func__);
836
  if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
837
    {
838
      ptid_t ptid;
839
 
840
      ptid = thread_to_gdb_id (current_inferior);
841
      if (nto_set_thread (ptid))
842
        {
843
          const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
844
                                | _DEBUG_FLAG_TRACE_MODIFY;
845
          procfs_status status;
846
          int err;
847
 
848
          err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
849
                        sizeof (status), 0);
850
          if (err == EOK && (status.flags & watchmask))
851
            ret = 1;
852
        }
853
    }
854
  TRACE ("%s: %s\n", __func__, ret ? "yes" : "no");
855
  return ret;
856
}
857
 
858
/* Get instruction pointer for CURRENT_INFERIOR thread.
859
 
860
   Return inferior's instruction pointer value, or 0 on error.  */
861
 
862
static CORE_ADDR
863
nto_stopped_data_address (void)
864
{
865
  CORE_ADDR ret = (CORE_ADDR)0;
866
 
867
  TRACE ("%s\n", __func__);
868
  if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
869
    {
870
      ptid_t ptid;
871
 
872
      ptid = thread_to_gdb_id (current_inferior);
873
 
874
      if (nto_set_thread (ptid))
875
        {
876
          procfs_status status;
877
 
878
          if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
879
                      sizeof (status), 0) == EOK)
880
            ret = status.ip;
881
        }
882
    }
883
  TRACE ("%s: 0x%08lx\n", __func__, ret);
884
  return ret;
885
}
886
 
887
/* We do not currently support non-stop.  */
888
 
889
static int
890
nto_supports_non_stop (void)
891
{
892
  TRACE ("%s\n", __func__);
893
  return 0;
894
}
895
 
896
 
897
 
898
static struct target_ops nto_target_ops = {
899
  nto_create_inferior,
900
  nto_attach,
901
  nto_kill,
902
  nto_detach,
903
  NULL, /* nto_join */
904
  nto_thread_alive,
905
  nto_resume,
906
  nto_wait,
907
  nto_fetch_registers,
908
  nto_store_registers,
909
  nto_read_memory,
910
  nto_write_memory,
911
  NULL, /* nto_look_up_symbols */
912
  nto_request_interrupt,
913
  nto_read_auxv,
914
  nto_insert_point,
915
  nto_remove_point,
916
  nto_stopped_by_watchpoint,
917
  nto_stopped_data_address,
918
  NULL, /* nto_read_offsets */
919
  NULL, /* thread_db_set_tls_address */
920
  NULL,
921
  hostio_last_error_from_errno,
922
  NULL, /* nto_qxfer_osdata */
923
  NULL, /* xfer_siginfo */
924
  nto_supports_non_stop,
925
  NULL, /* async */
926
  NULL  /* start_non_stop */
927
};
928
 
929
 
930
/* Global function called by server.c.  Initializes QNX Neutrino
931
   gdbserver.  */
932
 
933
void
934
initialize_low (void)
935
{
936
  sigset_t set;
937
 
938
  TRACE ("%s\n", __func__);
939
  set_target_ops (&nto_target_ops);
940
  set_breakpoint_data (the_low_target.breakpoint,
941
                       the_low_target.breakpoint_len);
942
 
943
  /* We use SIGUSR1 to gain control after we block waiting for a process.
944
     We use sigwaitevent to wait.  */
945
  sigemptyset (&set);
946
  sigaddset (&set, SIGUSR1);
947
  sigprocmask (SIG_BLOCK, &set, NULL);
948
}
949
 

powered by: WebSVN 2.1.0

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