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