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
40 struct process_info_private
41 {
42 /* The PTID obtained from the last wait performed on this process.
43 Initialized to null_ptid until the first wait is performed. */
44 ptid_t last_wait_event_ptid;
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
84 lynx_ptid_get_pid (ptid_t ptid)
85 {
86 return ptid_get_pid (ptid);
87 }
88
89 /* Return the LynxOS tid of the given PTID. */
90
91 static long
92 lynx_ptid_get_tid (ptid_t ptid)
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
103 lynx_ptrace_pid_from_ptid (ptid_t ptid)
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 *
111 ptrace_request_to_str (int request)
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 *
217 lynx_add_process (int pid, int attached)
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);
224 proc->priv->last_wait_event_ptid = null_ptid;
225
226 return proc;
227 }
228
229 /* Callback used by fork_inferior to start tracing the inferior. */
230
231 static void
232 lynx_ptrace_fun ()
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)
240 trace_start_error_with_name ("pgrp");
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 (),
262 get_environ ()->envp (), lynx_ptrace_fun,
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
278 lynx_add_threads_after_attach (int pid)
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);
322 lynx_add_threads_after_attach (pid);
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))
346 ptid = current_process()->priv->last_wait_event_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
355 regcache_invalidate_pid (ptid_get_pid (ptid));
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
366 lynx_continue (ptid_t ptid)
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))
426 pid = lynx_ptid_get_pid (ptid_of (current_thread));
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
544 lynx_detach (int pid)
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 {
563 for_each_thread (proc->pid, remove_thread);
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
575 lynx_join (int pid)
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
584 lynx_thread_alive (ptid_t ptid)
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
594 lynx_fetch_registers (struct regcache *regcache, int regno)
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
619 lynx_store_registers (struct regcache *regcache, int regno)
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
725 lynx_request_interrupt (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 = {
735 lynx_create_inferior,
736 NULL, /* post_create_inferior */
737 lynx_attach,
738 lynx_kill,
739 lynx_detach,
740 lynx_mourn,
741 lynx_join,
742 lynx_thread_alive,
743 lynx_resume,
744 lynx_wait,
745 lynx_fetch_registers,
746 lynx_store_registers,
747 NULL, /* prepare_to_access_memory */
748 NULL, /* done_accessing_memory */
749 lynx_read_memory,
750 lynx_write_memory,
751 NULL, /* look_up_symbols */
752 lynx_request_interrupt,
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 */
761 target_can_do_hardware_single_step,
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
782 initialize_low (void)
783 {
784 set_target_ops (&lynx_target_ops);
785 the_low_target.arch_setup ();
786 }
787
debug_threads
int debug_threads
Definition: debug.c:24
string
const char * string
Definition: signals.c:50
current_thread
struct thread_info * current_thread
Definition: inferiors.c:28
target_can_do_hardware_single_step
int target_can_do_hardware_single_step(void)
Definition: target.c:340
add_process
struct process_info * add_process(int pid, int attached)
Definition: inferiors.c:140
find_thread_ptid
struct thread_info * find_thread_ptid(ptid_t ptid)
Definition: inferiors.c:64
types.h
WNOHANG
#define WNOHANG
Definition: gdb_wait.h:102
CORE_ADDR
bfd_vma CORE_ADDR
Definition: common-types.h:41
lynx_regset_info::store_function
void(* store_function)(struct regcache *regcache, const char *buf)
Definition: lynx-low.h:32
lynx_mourn
static void lynx_mourn(struct process_info *proc)
Definition: lynx-low.c:561
ptid_get_pid
int ptid_get_pid(const ptid_t &ptid)
Definition: ptid.c:47
stringify_argv
std::string stringify_argv(const std::vector< char *> &args)
Definition: common-utils.c:392
lynx_ptrace
static int lynx_ptrace(int request, ptid_t ptid, int addr, int data, int addr2)
Definition: lynx-low.c:193
ptid_of
static ptid_t ptid_of(const thread_info *thread)
Definition: gdbthread.h:206
lynx_regset_info::fill_function
void(* fill_function)(struct regcache *regcache, char *buf)
Definition: lynx-low.h:30
process_info
Definition: inferiors.h:34
lynx_write_memory
static int lynx_write_memory(CORE_ADDR memaddr, const unsigned char *myaddr, int len)
Definition: lynx-low.c:684
target_ops::mourn
void(* mourn)(struct process_info *proc)
Definition: target.h:104
the_low_target
struct linux_target_ops the_low_target
Definition: linux-aarch64-low.c:2955
lynx_ptrace_fun
static void lynx_ptrace_fun()
Definition: lynx-low.c:232
for_each_thread
static void for_each_thread(Func func)
Definition: gdbthread.h:142
process_info::attached
int attached
Definition: inferiors.h:45
the_target
struct target_ops * the_target
Definition: target.c:24
process_info::tdesc
const struct target_desc * tdesc
Definition: inferiors.h:67
regcache
Definition: regcache.h:31
perror
void perror(const char *)
Definition: wincecompat.c:24
ptrace
PTRACE_TYPE_RET ptrace()
ptid_build
ptid_t ptid_build(int pid, long lwp, long tid)
Definition: ptid.c:31
thread_resume::sig
int sig
Definition: target.h:54
lynx_ptid_get_tid
static long lynx_ptid_get_tid(ptid_t ptid)
Definition: lynx-low.c:92
lynx_target_ops
Definition: lynx-low.h:44
WSTOPSIG
#define WSTOPSIG
Definition: gdb_wait.h:75
process_info_private
Definition: linux-low.h:113
WTERMSIG
#define WTERMSIG(w)
Definition: gdb_wait.h:71
ptrace_request_to_str
static char * ptrace_request_to_str(int request)
Definition: lynx-low.c:111
lynx_ptrace_pid_from_ptid
static int lynx_ptrace_pid_from_ptid(ptid_t ptid)
Definition: lynx-low.c:103
get_environ
gdb_environ * get_environ()
Definition: server.c:277
target_ops
Definition: target.h:66
lynx_tdesc
const struct target_desc * lynx_tdesc
Definition: lynx-low.c:36
find_process_pid
process_info * find_process_pid(int pid)
Definition: inferiors.c:164
thread_resume::kind
enum resume_kind kind
Definition: target.h:47
WIFEXITED
#define WIFEXITED(w)
Definition: gdb_wait.h:44
ptid_t
Definition: ptid.h:35
lynx_debug
static void lynx_debug(char *string,...)
Definition: lynx-low.c:50
unistd.h
lynx_resume
static void lynx_resume(struct thread_resume *resume_info, size_t n)
Definition: lynx-low.c:330
signal.h
free
void free(T *ptr)=delete
gdb_signal_from_host
enum gdb_signal gdb_signal_from_host(int)
Definition: signals.c:116
server.h
lynx_waitpid
static int lynx_waitpid(int pid, int *stat_loc)
Definition: lynx-low.c:381
thread_resume
Definition: target.h:42
lynx_detach
static int lynx_detach(int pid)
Definition: lynx-low.c:544
remove_process
void remove_process(struct process_info *process)
Definition: inferiors.c:154
set_target_ops
void set_target_ops(struct target_ops *target)
Definition: target.c:299
current_process
struct process_info * current_process(void)
Definition: inferiors.c:210
WEXITSTATUS
#define WEXITSTATUS(w)
Definition: gdb_wait.h:67
process_info::priv
struct process_info_private * priv
Definition: inferiors.h:70
ptid_get_lwp
long ptid_get_lwp(const ptid_t &ptid)
Definition: ptid.c:55
post_fork_inferior
void post_fork_inferior(int pid, const char *program)
Definition: fork-child.c:97
errno
#define errno
Definition: wincecompat.h:24
lynx_kill
static int lynx_kill(int pid)
Definition: lynx-low.c:525
get_first_thread
struct thread_info * get_first_thread(void)
Definition: inferiors.c:55
lynx_ptid_build
static ptid_t lynx_ptid_build(int pid, long tid)
Definition: lynx-low.c:67
WIFSTOPPED
#define WIFSTOPPED(w)
Definition: gdb_wait.h:62
gdb_byte
bfd_byte gdb_byte
Definition: common-types.h:38
fork-inferior.h
process_info::pid
int pid
Definition: inferiors.h:41
null_ptid
ptid_t null_ptid
Definition: ptid.c:25
trace_start_error_with_name
void trace_start_error_with_name(const char *string)
Definition: fork-inferior.c:613
WUNTRACED
#define WUNTRACED
Definition: gdb_wait.h:106
lynx_target_regsets
struct lynx_regset_info lynx_target_regsets[]
Definition: lynx-i386-low.c:306
thread_resume::thread
ptid_t thread
Definition: target.h:44
XCNEW
#define XCNEW(T)
Definition: poison.h:121
lynx_create_inferior
static int lynx_create_inferior(const char *program, const std::vector< char *> &program_args)
Definition: lynx-low.c:252
fork_inferior
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))
Definition: fork-inferior.c:287
target_desc
Definition: tdesc.h:33
lynx_wait_1
static ptid_t lynx_wait_1(ptid_t ptid, struct target_waitstatus *status, int options)
Definition: lynx-low.c:418
process_info_private::last_wait_event_ptid
ptid_t last_wait_event_ptid
Definition: lynx-low.c:44
lynx_thread_alive
static int lynx_thread_alive(ptid_t ptid)
Definition: lynx-low.c:584
lynx_regset_info::get_request
int get_request
Definition: lynx-low.h:26
lynx-low.h
limits.h
target.h
lynx_regset_info::size
int size
Definition: lynx-low.h:28
gdb_environ::envp
char ** envp() const
Definition: environ.c:166
perror_with_name
void perror_with_name(const char *string)
Definition: utils.c:57
remove_thread
void remove_thread(struct thread_info *thread)
Definition: inferiors.c:98
ptid_equal
int ptid_equal(const ptid_t &ptid1, const ptid_t &ptid2)
Definition: ptid.c:71
regcache_invalidate_pid
void regcache_invalidate_pid(int pid)
Definition: regcache.c:99
lynx_regset_info::set_request
int set_request
Definition: lynx-low.h:26
xmalloc
PTR xmalloc(size_t size)
Definition: common-utils.c:35
lynx_continue
static void lynx_continue(ptid_t ptid)
Definition: lynx-low.c:366
gdb_wait.h
WIFSIGNALED
#define WIFSIGNALED(w)
Definition: gdb_wait.h:48
lynx_wait
static ptid_t lynx_wait(ptid_t ptid, struct target_waitstatus *status, int options)
Definition: lynx-low.c:509
initialize_low
void initialize_low(void)
Definition: lynx-low.c:782
linux_target_ops::arch_setup
void(* arch_setup)(void)
Definition: linux-low.h:131
lynx_add_process
static struct process_info * lynx_add_process(int pid, int attached)
Definition: lynx-low.c:217
lynx_attach
static int lynx_attach(unsigned long pid)
Definition: lynx-low.c:313
lynx_join
static void lynx_join(int pid)
Definition: lynx-low.c:575
lynx_ptid_get_pid
static int lynx_ptid_get_pid(ptid_t ptid)
Definition: lynx-low.c:84
filestuff.h
lynx_fetch_registers
static void lynx_fetch_registers(struct regcache *regcache, int regno)
Definition: lynx-low.c:594
lynx_regset_info
Definition: lynx-low.h:23
program_args
static std::vector< char * > program_args
Definition: server.c:112
add_thread
struct thread_info * add_thread(ptid_t ptid, void *target_data)
Definition: inferiors.c:34
lynx_store_registers
static void lynx_store_registers(struct regcache *regcache, int regno)
Definition: lynx-low.c:619
using_threads
int using_threads
Definition: lynx-low.c:34
lynx_add_threads_after_attach
static void lynx_add_threads_after_attach(int pid)
Definition: lynx-low.c:278
error
void error(const char *fmt,...)
Definition: errors.c:38
CASE
#define CASE(X)
minus_one_ptid
ptid_t minus_one_ptid
Definition: ptid.c:26
common-inferior.h
lynx_read_memory
static int lynx_read_memory(CORE_ADDR memaddr, unsigned char *myaddr, int len)
Definition: lynx-low.c:651
strerror
char * strerror(int)
lynx_request_interrupt
static void lynx_request_interrupt(void)
Definition: lynx-low.c:725