GDBserver
lynx-low.c
Go to the documentation of this file.
1 /* Copyright (C) 2009-2018 Free Software Foundation, Inc.
2 
3  This file is part of GDB.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 
18 #include "server.h"
19 #include "target.h"
20 #include "lynx-low.h"
21 
22 #include <limits.h>
23 #include <sys/ptrace.h>
24 #include <sys/piddef.h> /* Provides PIDGET, TIDGET, BUILDPID, etc. */
25 #include <unistd.h>
26 #include <sys/ioctl.h>
27 #include <sys/types.h>
28 #include "gdb_wait.h"
29 #include <signal.h>
30 #include "filestuff.h"
31 #include "common-inferior.h"
32 #include "nat/fork-inferior.h"
33 
34 int using_threads = 1;
35 
36 const struct target_desc *lynx_tdesc;
37 
38 /* Per-process private data. */
39 
41 {
42  /* The PTID obtained from the last wait performed on this process.
43  Initialized to null_ptid until the first wait is performed. */
45 };
46 
47 /* Print a debug trace on standard output if debug_threads is set. */
48 
49 static void
50 lynx_debug (char *string, ...)
51 {
52  va_list args;
53 
54  if (!debug_threads)
55  return;
56 
57  va_start (args, string);
58  fprintf (stderr, "DEBUG(lynx): ");
59  vfprintf (stderr, string, args);
60  fprintf (stderr, "\n");
61  va_end (args);
62 }
63 
64 /* Build a ptid_t given a PID and a LynxOS TID. */
65 
66 static ptid_t
67 lynx_ptid_build (int pid, long tid)
68 {
69  /* brobecker/2010-06-21: It looks like the LWP field in ptids
70  should be distinct for each thread (see write_ptid where it
71  writes the thread ID from the LWP). So instead of storing
72  the LynxOS tid in the tid field of the ptid, we store it in
73  the lwp field. */
74  return ptid_build (pid, tid, 0);
75 }
76 
77 /* Return the process ID of the given PTID.
78 
79  This function has little reason to exist, it's just a wrapper around
80  ptid_get_pid. But since we have a getter function for the lynxos
81  ptid, it feels cleaner to have a getter for the pid as well. */
82 
83 static int
85 {
86  return ptid_get_pid (ptid);
87 }
88 
89 /* Return the LynxOS tid of the given PTID. */
90 
91 static long
93 {
94  /* See lynx_ptid_build: The LynxOS tid is stored inside the lwp field
95  of the ptid. */
96  return ptid_get_lwp (ptid);
97 }
98 
99 /* For a given PTID, return the associated PID as known by the LynxOS
100  ptrace layer. */
101 
102 static int
104 {
105  return BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
106 }
107 
108 /* Return a string image of the ptrace REQUEST number. */
109 
110 static char *
112 {
113 #define CASE(X) case X: return #X
114  switch (request)
115  {
116  CASE(PTRACE_TRACEME);
117  CASE(PTRACE_PEEKTEXT);
118  CASE(PTRACE_PEEKDATA);
119  CASE(PTRACE_PEEKUSER);
120  CASE(PTRACE_POKETEXT);
121  CASE(PTRACE_POKEDATA);
122  CASE(PTRACE_POKEUSER);
123  CASE(PTRACE_CONT);
124  CASE(PTRACE_KILL);
125  CASE(PTRACE_SINGLESTEP);
126  CASE(PTRACE_ATTACH);
127  CASE(PTRACE_DETACH);
128  CASE(PTRACE_GETREGS);
129  CASE(PTRACE_SETREGS);
130  CASE(PTRACE_GETFPREGS);
131  CASE(PTRACE_SETFPREGS);
132  CASE(PTRACE_READDATA);
133  CASE(PTRACE_WRITEDATA);
134  CASE(PTRACE_READTEXT);
135  CASE(PTRACE_WRITETEXT);
136  CASE(PTRACE_GETFPAREGS);
137  CASE(PTRACE_SETFPAREGS);
138  CASE(PTRACE_GETWINDOW);
139  CASE(PTRACE_SETWINDOW);
140  CASE(PTRACE_SYSCALL);
141  CASE(PTRACE_DUMPCORE);
142  CASE(PTRACE_SETWRBKPT);
143  CASE(PTRACE_SETACBKPT);
144  CASE(PTRACE_CLRBKPT);
145  CASE(PTRACE_GET_UCODE);
146 #ifdef PT_READ_GPR
147  CASE(PT_READ_GPR);
148 #endif
149 #ifdef PT_WRITE_GPR
150  CASE(PT_WRITE_GPR);
151 #endif
152 #ifdef PT_READ_FPR
153  CASE(PT_READ_FPR);
154 #endif
155 #ifdef PT_WRITE_FPR
156  CASE(PT_WRITE_FPR);
157 #endif
158 #ifdef PT_READ_VPR
159  CASE(PT_READ_VPR);
160 #endif
161 #ifdef PT_WRITE_VPR
162  CASE(PT_WRITE_VPR);
163 #endif
164 #ifdef PTRACE_PEEKUSP
165  CASE(PTRACE_PEEKUSP);
166 #endif
167 #ifdef PTRACE_POKEUSP
168  CASE(PTRACE_POKEUSP);
169 #endif
170  CASE(PTRACE_PEEKTHREAD);
171  CASE(PTRACE_THREADUSER);
172  CASE(PTRACE_FPREAD);
173  CASE(PTRACE_FPWRITE);
174  CASE(PTRACE_SETSIG);
175  CASE(PTRACE_CONT_ONE);
176  CASE(PTRACE_KILL_ONE);
177  CASE(PTRACE_SINGLESTEP_ONE);
178  CASE(PTRACE_GETLOADINFO);
179  CASE(PTRACE_GETTRACESIG);
180 #ifdef PTRACE_GETTHREADLIST
181  CASE(PTRACE_GETTHREADLIST);
182 #endif
183  }
184 #undef CASE
185 
186  return "<unknown-request>";
187 }
188 
189 /* A wrapper around ptrace that allows us to print debug traces of
190  ptrace calls if debug traces are activated. */
191 
192 static int
193 lynx_ptrace (int request, ptid_t ptid, int addr, int data, int addr2)
194 {
195  int result;
196  const int pid = lynx_ptrace_pid_from_ptid (ptid);
197  int saved_errno;
198 
199  if (debug_threads)
200  fprintf (stderr, "PTRACE (%s, pid=%d(pid=%d, tid=%d), addr=0x%x, "
201  "data=0x%x, addr2=0x%x)",
202  ptrace_request_to_str (request), pid, PIDGET (pid), TIDGET (pid),
203  addr, data, addr2);
204  result = ptrace (request, pid, addr, data, addr2);
205  saved_errno = errno;
206  if (debug_threads)
207  fprintf (stderr, " -> %d (=0x%x)\n", result, result);
208 
209  errno = saved_errno;
210  return result;
211 }
212 
213 /* Call add_process with the given parameters, and initializes
214  the process' private data. */
215 
216 static struct process_info *
218 {
219  struct process_info *proc;
220 
221  proc = add_process (pid, attached);
222  proc->tdesc = lynx_tdesc;
223  proc->priv = XCNEW (struct process_info_private);
225 
226  return proc;
227 }
228 
229 /* Callback used by fork_inferior to start tracing the inferior. */
230 
231 static void
233 {
234  int pgrp;
235 
236  /* Switch child to its own process group so that signals won't
237  directly affect GDBserver. */
238  pgrp = getpid();
239  if (pgrp < 0)
241  if (setpgid (0, pgrp) < 0)
242  trace_start_error_with_name ("setpgid");
243  if (ioctl (0, TIOCSPGRP, &pgrp) < 0)
244  trace_start_error_with_name ("ioctl");
245  if (lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0) < 0)
246  trace_start_error_with_name ("lynx_ptrace");
247 }
248 
249 /* Implement the create_inferior method of the target_ops vector. */
250 
251 static int
252 lynx_create_inferior (const char *program,
253  const std::vector<char *> &program_args)
254 {
255  int pid;
256  std::string str_program_args = stringify_argv (program_args);
257 
258  lynx_debug ("lynx_create_inferior ()");
259 
260  pid = fork_inferior (program,
261  str_program_args.c_str (),
263  NULL, NULL, NULL, NULL);
264 
265  post_fork_inferior (pid, program);
266 
267  lynx_add_process (pid, 0);
268  /* Do not add the process thread just yet, as we do not know its tid.
269  We will add it later, during the wait for the STOP event corresponding
270  to the lynx_ptrace (PTRACE_TRACEME) call above. */
271  return pid;
272 }
273 
274 /* Assuming we've just attached to a running inferior whose pid is PID,
275  add all threads running in that process. */
276 
277 static void
279 {
280  /* Ugh! There appears to be no way to get the list of threads
281  in the program we just attached to. So get the list by calling
282  the "ps" command. This is only needed now, as we will then
283  keep the thread list up to date thanks to thread creation and
284  exit notifications. */
285  FILE *f;
286  char buf[256];
287  int thread_pid, thread_tid;
288 
289  f = popen ("ps atx", "r");
290  if (f == NULL)
291  perror_with_name ("Cannot get thread list");
292 
293  while (fgets (buf, sizeof (buf), f) != NULL)
294  if ((sscanf (buf, "%d %d", &thread_pid, &thread_tid) == 2
295  && thread_pid == pid))
296  {
297  ptid_t thread_ptid = lynx_ptid_build (pid, thread_tid);
298 
299  if (!find_thread_ptid (thread_ptid))
300  {
301  lynx_debug ("New thread: (pid = %d, tid = %d)",
302  pid, thread_tid);
303  add_thread (thread_ptid, NULL);
304  }
305  }
306 
307  pclose (f);
308 }
309 
310 /* Implement the attach target_ops method. */
311 
312 static int
313 lynx_attach (unsigned long pid)
314 {
315  ptid_t ptid = lynx_ptid_build (pid, 0);
316 
317  if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0)
318  error ("Cannot attach to process %lu: %s (%d)\n", pid,
319  strerror (errno), errno);
320 
321  lynx_add_process (pid, 1);
323 
324  return 0;
325 }
326 
327 /* Implement the resume target_ops method. */
328 
329 static void
330 lynx_resume (struct thread_resume *resume_info, size_t n)
331 {
332  ptid_t ptid = resume_info[0].thread;
333  const int request
334  = (resume_info[0].kind == resume_step
335  ? (n == 1 ? PTRACE_SINGLESTEP_ONE : PTRACE_SINGLESTEP)
336  : PTRACE_CONT);
337  const int signal = resume_info[0].sig;
338 
339  /* If given a minus_one_ptid, then try using the current_process'
340  private->last_wait_event_ptid. On most LynxOS versions,
341  using any of the process' thread works well enough, but
342  LynxOS 178 is a little more sensitive, and triggers some
343  unexpected signals (Eg SIG61) when we resume the inferior
344  using a different thread. */
345  if (ptid_equal (ptid, minus_one_ptid))
347 
348  /* The ptid might still be minus_one_ptid; this can happen between
349  the moment we create the inferior or attach to a process, and
350  the moment we resume its execution for the first time. It is
351  fine to use the current_thread's ptid in those cases. */
352  if (ptid_equal (ptid, minus_one_ptid))
353  ptid = ptid_of (current_thread);
354 
356 
357  errno = 0;
358  lynx_ptrace (request, ptid, 1, signal, 0);
359  if (errno)
360  perror_with_name ("ptrace");
361 }
362 
363 /* Resume the execution of the given PTID. */
364 
365 static void
367 {
368  struct thread_resume resume_info;
369 
370  resume_info.thread = ptid;
371  resume_info.kind = resume_continue;
372  resume_info.sig = 0;
373 
374  lynx_resume (&resume_info, 1);
375 }
376 
377 /* A wrapper around waitpid that handles the various idiosyncrasies
378  of LynxOS' waitpid. */
379 
380 static int
381 lynx_waitpid (int pid, int *stat_loc)
382 {
383  int ret = 0;
384 
385  while (1)
386  {
387  ret = waitpid (pid, stat_loc, WNOHANG);
388  if (ret < 0)
389  {
390  /* An ECHILD error is not indicative of a real problem.
391  It happens for instance while waiting for the inferior
392  to stop after attaching to it. */
393  if (errno != ECHILD)
394  perror_with_name ("waitpid (WNOHANG)");
395  }
396  if (ret > 0)
397  break;
398  /* No event with WNOHANG. See if there is one with WUNTRACED. */
399  ret = waitpid (pid, stat_loc, WNOHANG | WUNTRACED);
400  if (ret < 0)
401  {
402  /* An ECHILD error is not indicative of a real problem.
403  It happens for instance while waiting for the inferior
404  to stop after attaching to it. */
405  if (errno != ECHILD)
406  perror_with_name ("waitpid (WNOHANG|WUNTRACED)");
407  }
408  if (ret > 0)
409  break;
410  usleep (1000);
411  }
412  return ret;
413 }
414 
415 /* Implement the wait target_ops method. */
416 
417 static ptid_t
418 lynx_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options)
419 {
420  int pid;
421  int ret;
422  int wstat;
423  ptid_t new_ptid;
424 
425  if (ptid_equal (ptid, minus_one_ptid))
427  else
428  pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
429 
430 retry:
431 
432  ret = lynx_waitpid (pid, &wstat);
433  new_ptid = lynx_ptid_build (ret, ((union wait *) &wstat)->w_tid);
434  find_process_pid (ret)->priv->last_wait_event_ptid = new_ptid;
435 
436  /* If this is a new thread, then add it now. The reason why we do
437  this here instead of when handling new-thread events is because
438  we need to add the thread associated to the "main" thread - even
439  for non-threaded applications where the new-thread events are not
440  generated. */
441  if (!find_thread_ptid (new_ptid))
442  {
443  lynx_debug ("New thread: (pid = %d, tid = %d)",
444  lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid));
445  add_thread (new_ptid, NULL);
446  }
447 
448  if (WIFSTOPPED (wstat))
449  {
450  status->kind = TARGET_WAITKIND_STOPPED;
451  status->value.integer = gdb_signal_from_host (WSTOPSIG (wstat));
452  lynx_debug ("process stopped with signal: %d",
453  status->value.integer);
454  }
455  else if (WIFEXITED (wstat))
456  {
457  status->kind = TARGET_WAITKIND_EXITED;
458  status->value.integer = WEXITSTATUS (wstat);
459  lynx_debug ("process exited with code: %d", status->value.integer);
460  }
461  else if (WIFSIGNALED (wstat))
462  {
463  status->kind = TARGET_WAITKIND_SIGNALLED;
464  status->value.integer = gdb_signal_from_host (WTERMSIG (wstat));
465  lynx_debug ("process terminated with code: %d",
466  status->value.integer);
467  }
468  else
469  {
470  /* Not sure what happened if we get here, or whether we can
471  in fact get here. But if we do, handle the event the best
472  we can. */
473  status->kind = TARGET_WAITKIND_STOPPED;
474  status->value.integer = gdb_signal_from_host (0);
475  lynx_debug ("unknown event ????");
476  }
477 
478  /* SIGTRAP events are generated for situations other than single-step/
479  breakpoint events (Eg. new-thread events). Handle those other types
480  of events, and resume the execution if necessary. */
481  if (status->kind == TARGET_WAITKIND_STOPPED
482  && status->value.integer == GDB_SIGNAL_TRAP)
483  {
484  const int realsig = lynx_ptrace (PTRACE_GETTRACESIG, new_ptid, 0, 0, 0);
485 
486  lynx_debug ("(realsig = %d)", realsig);
487  switch (realsig)
488  {
489  case SIGNEWTHREAD:
490  /* We just added the new thread above. No need to do anything
491  further. Just resume the execution again. */
492  lynx_continue (new_ptid);
493  goto retry;
494 
495  case SIGTHREADEXIT:
496  remove_thread (find_thread_ptid (new_ptid));
497  lynx_continue (new_ptid);
498  goto retry;
499  }
500  }
501 
502  return new_ptid;
503 }
504 
505 /* A wrapper around lynx_wait_1 that also prints debug traces when
506  such debug traces have been activated. */
507 
508 static ptid_t
509 lynx_wait (ptid_t ptid, struct target_waitstatus *status, int options)
510 {
511  ptid_t new_ptid;
512 
513  lynx_debug ("lynx_wait (pid = %d, tid = %ld)",
514  lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
515  new_ptid = lynx_wait_1 (ptid, status, options);
516  lynx_debug (" -> (pid=%d, tid=%ld, status->kind = %d)",
517  lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid),
518  status->kind);
519  return new_ptid;
520 }
521 
522 /* Implement the kill target_ops method. */
523 
524 static int
525 lynx_kill (int pid)
526 {
527  ptid_t ptid = lynx_ptid_build (pid, 0);
528  struct target_waitstatus status;
529  struct process_info *process;
530 
531  process = find_process_pid (pid);
532  if (process == NULL)
533  return -1;
534 
535  lynx_ptrace (PTRACE_KILL, ptid, 0, 0, 0);
536  lynx_wait (ptid, &status, 0);
537  the_target->mourn (process);
538  return 0;
539 }
540 
541 /* Implement the detach target_ops method. */
542 
543 static int
545 {
546  ptid_t ptid = lynx_ptid_build (pid, 0);
547  struct process_info *process;
548 
549  process = find_process_pid (pid);
550  if (process == NULL)
551  return -1;
552 
553  lynx_ptrace (PTRACE_DETACH, ptid, 0, 0, 0);
554  the_target->mourn (process);
555  return 0;
556 }
557 
558 /* Implement the mourn target_ops method. */
559 
560 static void
561 lynx_mourn (struct process_info *proc)
562 {
564 
565  /* Free our private data. */
566  free (proc->priv);
567  proc->priv = NULL;
568 
569  remove_process (proc);
570 }
571 
572 /* Implement the join target_ops method. */
573 
574 static void
576 {
577  /* The PTRACE_DETACH is sufficient to detach from the process.
578  So no need to do anything extra. */
579 }
580 
581 /* Implement the thread_alive target_ops method. */
582 
583 static int
585 {
586  /* The list of threads is updated at the end of each wait, so it
587  should be up to date. No need to re-fetch it. */
588  return (find_thread_ptid (ptid) != NULL);
589 }
590 
591 /* Implement the fetch_registers target_ops method. */
592 
593 static void
595 {
596  struct lynx_regset_info *regset = lynx_target_regsets;
597  ptid_t inferior_ptid = ptid_of (current_thread);
598 
599  lynx_debug ("lynx_fetch_registers (regno = %d)", regno);
600 
601  while (regset->size >= 0)
602  {
603  char *buf;
604  int res;
605 
606  buf = xmalloc (regset->size);
607  res = lynx_ptrace (regset->get_request, inferior_ptid, (int) buf, 0, 0);
608  if (res < 0)
609  perror ("ptrace");
610  regset->store_function (regcache, buf);
611  free (buf);
612  regset++;
613  }
614 }
615 
616 /* Implement the store_registers target_ops method. */
617 
618 static void
620 {
621  struct lynx_regset_info *regset = lynx_target_regsets;
622  ptid_t inferior_ptid = ptid_of (current_thread);
623 
624  lynx_debug ("lynx_store_registers (regno = %d)", regno);
625 
626  while (regset->size >= 0)
627  {
628  char *buf;
629  int res;
630 
631  buf = xmalloc (regset->size);
632  res = lynx_ptrace (regset->get_request, inferior_ptid, (int) buf, 0, 0);
633  if (res == 0)
634  {
635  /* Then overlay our cached registers on that. */
636  regset->fill_function (regcache, buf);
637  /* Only now do we write the register set. */
638  res = lynx_ptrace (regset->set_request, inferior_ptid, (int) buf,
639  0, 0);
640  }
641  if (res < 0)
642  perror ("ptrace");
643  free (buf);
644  regset++;
645  }
646 }
647 
648 /* Implement the read_memory target_ops method. */
649 
650 static int
651 lynx_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
652 {
653  /* On LynxOS, memory reads needs to be performed in chunks the size
654  of int types, and they should also be aligned accordingly. */
655  int buf;
656  const int xfer_size = sizeof (buf);
657  CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
658  ptid_t inferior_ptid = ptid_of (current_thread);
659 
660  while (addr < memaddr + len)
661  {
662  int skip = 0;
663  int truncate = 0;
664 
665  errno = 0;
666  if (addr < memaddr)
667  skip = memaddr - addr;
668  if (addr + xfer_size > memaddr + len)
669  truncate = addr + xfer_size - memaddr - len;
670  buf = lynx_ptrace (PTRACE_PEEKTEXT, inferior_ptid, addr, 0, 0);
671  if (errno)
672  return errno;
673  memcpy (myaddr + (addr - memaddr) + skip, (gdb_byte *) &buf + skip,
674  xfer_size - skip - truncate);
675  addr += xfer_size;
676  }
677 
678  return 0;
679 }
680 
681 /* Implement the write_memory target_ops method. */
682 
683 static int
684 lynx_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
685 {
686  /* On LynxOS, memory writes needs to be performed in chunks the size
687  of int types, and they should also be aligned accordingly. */
688  int buf;
689  const int xfer_size = sizeof (buf);
690  CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
691  ptid_t inferior_ptid = ptid_of (current_thread);
692 
693  while (addr < memaddr + len)
694  {
695  int skip = 0;
696  int truncate = 0;
697 
698  if (addr < memaddr)
699  skip = memaddr - addr;
700  if (addr + xfer_size > memaddr + len)
701  truncate = addr + xfer_size - memaddr - len;
702  if (skip > 0 || truncate > 0)
703  {
704  /* We need to read the memory at this address in order to preserve
705  the data that we are not overwriting. */
706  lynx_read_memory (addr, (unsigned char *) &buf, xfer_size);
707  if (errno)
708  return errno;
709  }
710  memcpy ((gdb_byte *) &buf + skip, myaddr + (addr - memaddr) + skip,
711  xfer_size - skip - truncate);
712  errno = 0;
713  lynx_ptrace (PTRACE_POKETEXT, inferior_ptid, addr, buf, 0);
714  if (errno)
715  return errno;
716  addr += xfer_size;
717  }
718 
719  return 0;
720 }
721 
722 /* Implement the kill_request target_ops method. */
723 
724 static void
726 {
727  ptid_t inferior_ptid = ptid_of (get_first_thread ());
728 
729  kill (lynx_ptid_get_pid (inferior_ptid), SIGINT);
730 }
731 
732 /* The LynxOS target_ops vector. */
733 
734 static struct target_ops lynx_target_ops = {
736  NULL, /* post_create_inferior */
737  lynx_attach,
738  lynx_kill,
739  lynx_detach,
740  lynx_mourn,
741  lynx_join,
743  lynx_resume,
744  lynx_wait,
747  NULL, /* prepare_to_access_memory */
748  NULL, /* done_accessing_memory */
751  NULL, /* look_up_symbols */
753  NULL, /* read_auxv */
754  NULL, /* supports_z_point_type */
755  NULL, /* insert_point */
756  NULL, /* remove_point */
757  NULL, /* stopped_by_sw_breakpoint */
758  NULL, /* supports_stopped_by_sw_breakpoint */
759  NULL, /* stopped_by_hw_breakpoint */
760  NULL, /* supports_stopped_by_hw_breakpoint */
762  NULL, /* stopped_by_watchpoint */
763  NULL, /* stopped_data_address */
764  NULL, /* read_offsets */
765  NULL, /* get_tls_address */
766  NULL, /* qxfer_spu */
767  NULL, /* hostio_last_error */
768  NULL, /* qxfer_osdata */
769  NULL, /* qxfer_siginfo */
770  NULL, /* supports_non_stop */
771  NULL, /* async */
772  NULL, /* start_non_stop */
773  NULL, /* supports_multi_process */
774  NULL, /* supports_fork_events */
775  NULL, /* supports_vfork_events */
776  NULL, /* supports_exec_events */
777  NULL, /* handle_new_gdb_connection */
778  NULL, /* handle_monitor_command */
779 };
780 
781 void
783 {
786 }
787 
int debug_threads
Definition: debug.c:24
const char * string
Definition: signals.c:50
struct thread_info * current_thread
Definition: inferiors.c:28
int target_can_do_hardware_single_step(void)
Definition: target.c:340
struct process_info * add_process(int pid, int attached)
Definition: inferiors.c:140
struct thread_info * find_thread_ptid(ptid_t ptid)
Definition: inferiors.c:64
#define WNOHANG
Definition: gdb_wait.h:102
bfd_vma CORE_ADDR
Definition: common-types.h:41
void(* store_function)(struct regcache *regcache, const char *buf)
Definition: lynx-low.h:32
static void lynx_mourn(struct process_info *proc)
Definition: lynx-low.c:561
int ptid_get_pid(const ptid_t &ptid)
Definition: ptid.c:47
std::string stringify_argv(const std::vector< char *> &args)
Definition: common-utils.c:392
static int lynx_ptrace(int request, ptid_t ptid, int addr, int data, int addr2)
Definition: lynx-low.c:193
static ptid_t ptid_of(const thread_info *thread)
Definition: gdbthread.h:206
void(* fill_function)(struct regcache *regcache, char *buf)
Definition: lynx-low.h:30
static int lynx_write_memory(CORE_ADDR memaddr, const unsigned char *myaddr, int len)
Definition: lynx-low.c:684
void(* mourn)(struct process_info *proc)
Definition: target.h:104
struct linux_target_ops the_low_target
static void lynx_ptrace_fun()
Definition: lynx-low.c:232
static void for_each_thread(Func func)
Definition: gdbthread.h:142
int attached
Definition: inferiors.h:45
struct target_ops * the_target
Definition: target.c:24
const struct target_desc * tdesc
Definition: inferiors.h:67
void perror(const char *)
Definition: wincecompat.c:24
PTRACE_TYPE_RET ptrace()
ptid_t ptid_build(int pid, long lwp, long tid)
Definition: ptid.c:31
static long lynx_ptid_get_tid(ptid_t ptid)
Definition: lynx-low.c:92
#define WSTOPSIG
Definition: gdb_wait.h:75
#define WTERMSIG(w)
Definition: gdb_wait.h:71
static char * ptrace_request_to_str(int request)
Definition: lynx-low.c:111
static int lynx_ptrace_pid_from_ptid(ptid_t ptid)
Definition: lynx-low.c:103
gdb_environ * get_environ()
Definition: server.c:277
const struct target_desc * lynx_tdesc
Definition: lynx-low.c:36
process_info * find_process_pid(int pid)
Definition: inferiors.c:164
enum resume_kind kind
Definition: target.h:47
#define WIFEXITED(w)
Definition: gdb_wait.h:44
Definition: ptid.h:35
static void lynx_debug(char *string,...)
Definition: lynx-low.c:50
static void lynx_resume(struct thread_resume *resume_info, size_t n)
Definition: lynx-low.c:330
void free(T *ptr)=delete
enum gdb_signal gdb_signal_from_host(int)
Definition: signals.c:116
static int lynx_waitpid(int pid, int *stat_loc)
Definition: lynx-low.c:381
static int lynx_detach(int pid)
Definition: lynx-low.c:544
void remove_process(struct process_info *process)
Definition: inferiors.c:154
void set_target_ops(struct target_ops *target)
Definition: target.c:299
struct process_info * current_process(void)
Definition: inferiors.c:210
#define WEXITSTATUS(w)
Definition: gdb_wait.h:67
struct process_info_private * priv
Definition: inferiors.h:70
long ptid_get_lwp(const ptid_t &ptid)
Definition: ptid.c:55
void post_fork_inferior(int pid, const char *program)
Definition: fork-child.c:97
#define errno
Definition: wincecompat.h:24
static int lynx_kill(int pid)
Definition: lynx-low.c:525
struct thread_info * get_first_thread(void)
Definition: inferiors.c:55
static ptid_t lynx_ptid_build(int pid, long tid)
Definition: lynx-low.c:67
#define WIFSTOPPED(w)
Definition: gdb_wait.h:62
bfd_byte gdb_byte
Definition: common-types.h:38
ptid_t null_ptid
Definition: ptid.c:25
void trace_start_error_with_name(const char *string)
#define WUNTRACED
Definition: gdb_wait.h:106
struct lynx_regset_info lynx_target_regsets[]
ptid_t thread
Definition: target.h:44
#define XCNEW(T)
Definition: poison.h:121
static int lynx_create_inferior(const char *program, const std::vector< char *> &program_args)
Definition: lynx-low.c:252
pid_t fork_inferior(const char *exec_file_arg, const std::string &allargs, char **env, void(*traceme_fun)(), void(*init_trace_fun)(int), void(*pre_trace_fun)(), const char *shell_file_arg, void(*exec_fun)(const char *file, char *const *argv, char *const *env))
static ptid_t lynx_wait_1(ptid_t ptid, struct target_waitstatus *status, int options)
Definition: lynx-low.c:418
ptid_t last_wait_event_ptid
Definition: lynx-low.c:44
static int lynx_thread_alive(ptid_t ptid)
Definition: lynx-low.c:584
char ** envp() const
Definition: environ.c:166
void perror_with_name(const char *string)
Definition: utils.c:57
void remove_thread(struct thread_info *thread)
Definition: inferiors.c:98
int ptid_equal(const ptid_t &ptid1, const ptid_t &ptid2)
Definition: ptid.c:71
void regcache_invalidate_pid(int pid)
Definition: regcache.c:99
PTR xmalloc(size_t size)
Definition: common-utils.c:35
static void lynx_continue(ptid_t ptid)
Definition: lynx-low.c:366
#define WIFSIGNALED(w)
Definition: gdb_wait.h:48
static ptid_t lynx_wait(ptid_t ptid, struct target_waitstatus *status, int options)
Definition: lynx-low.c:509
void initialize_low(void)
Definition: lynx-low.c:782
void(* arch_setup)(void)
Definition: linux-low.h:131
static struct process_info * lynx_add_process(int pid, int attached)
Definition: lynx-low.c:217
static int lynx_attach(unsigned long pid)
Definition: lynx-low.c:313
static void lynx_join(int pid)
Definition: lynx-low.c:575
static int lynx_ptid_get_pid(ptid_t ptid)
Definition: lynx-low.c:84
static void lynx_fetch_registers(struct regcache *regcache, int regno)
Definition: lynx-low.c:594
static std::vector< char * > program_args
Definition: server.c:112
struct thread_info * add_thread(ptid_t ptid, void *target_data)
Definition: inferiors.c:34
static void lynx_store_registers(struct regcache *regcache, int regno)
Definition: lynx-low.c:619
int using_threads
Definition: lynx-low.c:34
static void lynx_add_threads_after_attach(int pid)
Definition: lynx-low.c:278
void error(const char *fmt,...)
Definition: errors.c:38
#define CASE(X)
ptid_t minus_one_ptid
Definition: ptid.c:26
static int lynx_read_memory(CORE_ADDR memaddr, unsigned char *myaddr, int len)
Definition: lynx-low.c:651
char * strerror(int)
static void lynx_request_interrupt(void)
Definition: lynx-low.c:725