2013-10-01 Jan-Benedict Glaw <jbglaw@lug-owl.de>
[deliverable/binutils-gdb.git] / gdb / gdbserver / lynx-low.c
CommitLineData
28e7fd62 1/* Copyright (C) 2009-2013 Free Software Foundation, Inc.
8ed54b31
JB
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>
1adfc54d 23#include <sys/ptrace.h>
8ed54b31
JB
24#include <sys/piddef.h> /* Provides PIDGET, TIDGET, BUILDPID, etc. */
25#include <unistd.h>
26#include <sys/ioctl.h>
27#include <sys/types.h>
8bdce1ff 28#include "gdb_wait.h"
8ed54b31 29#include <signal.h>
602e3198 30#include "filestuff.h"
8ed54b31
JB
31
32int using_threads = 1;
33
3aee8918
PA
34const struct target_desc *lynx_tdesc;
35
d631c5a7
JB
36/* Per-process private data. */
37
38struct process_info_private
39{
40 /* The PTID obtained from the last wait performed on this process.
41 Initialized to null_ptid until the first wait is performed. */
42 ptid_t last_wait_event_ptid;
43};
44
8ed54b31
JB
45/* Print a debug trace on standard output if debug_threads is set. */
46
47static void
48lynx_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
64static ptid_t
65lynx_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
81static int
82lynx_ptid_get_pid (ptid_t ptid)
83{
84 return ptid_get_pid (ptid);
85}
86
87/* Return the LynxOS tid of the given PTID. */
88
89static long
90lynx_ptid_get_tid (ptid_t ptid)
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
100static int
101lynx_ptrace_pid_from_ptid (ptid_t ptid)
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
108static char *
109ptrace_request_to_str (int request)
110{
4039cf45 111#define CASE(X) case X: return #X
8ed54b31
JB
112 switch (request)
113 {
4039cf45
JB
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);
8ed54b31 144#ifdef PT_READ_GPR
4039cf45 145 CASE(PT_READ_GPR);
8ed54b31
JB
146#endif
147#ifdef PT_WRITE_GPR
4039cf45 148 CASE(PT_WRITE_GPR);
8ed54b31
JB
149#endif
150#ifdef PT_READ_FPR
4039cf45 151 CASE(PT_READ_FPR);
8ed54b31
JB
152#endif
153#ifdef PT_WRITE_FPR
4039cf45 154 CASE(PT_WRITE_FPR);
8ed54b31 155#endif
8ed54b31 156#ifdef PT_READ_VPR
4039cf45 157 CASE(PT_READ_VPR);
8ed54b31
JB
158#endif
159#ifdef PT_WRITE_VPR
4039cf45 160 CASE(PT_WRITE_VPR);
8ed54b31
JB
161#endif
162#ifdef PTRACE_PEEKUSP
4039cf45 163 CASE(PTRACE_PEEKUSP);
8ed54b31
JB
164#endif
165#ifdef PTRACE_POKEUSP
4039cf45 166 CASE(PTRACE_POKEUSP);
8ed54b31 167#endif
4039cf45
JB
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);
78cbc024 178#ifdef PTRACE_GETTHREADLIST
4039cf45 179 CASE(PTRACE_GETTHREADLIST);
78cbc024 180#endif
8ed54b31 181 }
4039cf45
JB
182#undef CASE
183
8ed54b31
JB
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
190static int
191lynx_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
d631c5a7
JB
211/* Call add_process with the given parameters, and initializes
212 the process' private data. */
213
214static struct process_info *
215lynx_add_process (int pid, int attached)
216{
217 struct process_info *proc;
218
219 proc = add_process (pid, attached);
3aee8918 220 proc->tdesc = lynx_tdesc;
d631c5a7
JB
221 proc->private = xcalloc (1, sizeof (*proc->private));
222 proc->private->last_wait_event_ptid = null_ptid;
223
224 return proc;
225}
226
8ed54b31
JB
227/* Implement the create_inferior method of the target_ops vector. */
228
229static int
230lynx_create_inferior (char *program, char **allargs)
231{
8ed54b31
JB
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
602e3198
JK
244 close_most_fds ();
245
8ed54b31
JB
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
d631c5a7 258 lynx_add_process (pid, 0);
8ed54b31
JB
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/* Implement the attach target_ops method. */
266
267static int
268lynx_attach (unsigned long pid)
269{
8ed54b31
JB
270 ptid_t ptid = lynx_ptid_build (pid, 0);
271
272 if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0)
273 error ("Cannot attach to process %lu: %s (%d)\n", pid,
274 strerror (errno), errno);
275
d631c5a7 276 lynx_add_process (pid, 1);
8ed54b31
JB
277 add_thread (ptid, NULL);
278
279 return 0;
280}
281
282/* Implement the resume target_ops method. */
283
284static void
285lynx_resume (struct thread_resume *resume_info, size_t n)
286{
8ed54b31 287 /* FIXME: Assume for now that n == 1. */
3f6e77ef 288 ptid_t ptid = resume_info[0].thread;
8ed54b31
JB
289 const int request = (resume_info[0].kind == resume_step
290 ? PTRACE_SINGLESTEP : PTRACE_CONT);
291 const int signal = resume_info[0].sig;
8ed54b31 292
58794e1a 293 /* If given a minus_one_ptid, then try using the current_process'
d631c5a7
JB
294 private->last_wait_event_ptid. On most LynxOS versions,
295 using any of the process' thread works well enough, but
296 LynxOS 178 is a little more sensitive, and triggers some
297 unexpected signals (Eg SIG61) when we resume the inferior
298 using a different thread. */
299 if (ptid_equal (ptid, minus_one_ptid))
300 ptid = current_process()->private->last_wait_event_ptid;
301
58794e1a
JB
302 /* The ptid might still be minus_one_ptid; this can happen between
303 the moment we create the inferior or attach to a process, and
304 the moment we resume its execution for the first time. It is
305 fine to use the current_inferior's ptid in those cases. */
3f6e77ef
JB
306 if (ptid_equal (ptid, minus_one_ptid))
307 ptid = thread_to_gdb_id (current_inferior);
308
8ed54b31 309 regcache_invalidate ();
9044dee2
JB
310
311 errno = 0;
3f6e77ef 312 lynx_ptrace (request, ptid, 1, signal, 0);
9044dee2
JB
313 if (errno)
314 perror_with_name ("ptrace");
8ed54b31
JB
315}
316
317/* Resume the execution of the given PTID. */
318
319static void
320lynx_continue (ptid_t ptid)
321{
322 struct thread_resume resume_info;
323
324 resume_info.thread = ptid;
325 resume_info.kind = resume_continue;
326 resume_info.sig = 0;
327
328 lynx_resume (&resume_info, 1);
329}
330
8ed54b31
JB
331/* A wrapper around waitpid that handles the various idiosyncrasies
332 of LynxOS' waitpid. */
333
334static int
335lynx_waitpid (int pid, int *stat_loc)
336{
337 int ret = 0;
338
339 while (1)
340 {
341 ret = waitpid (pid, stat_loc, WNOHANG);
342 if (ret < 0)
343 {
344 /* An ECHILD error is not indicative of a real problem.
345 It happens for instance while waiting for the inferior
346 to stop after attaching to it. */
347 if (errno != ECHILD)
348 perror_with_name ("waitpid (WNOHANG)");
349 }
350 if (ret > 0)
351 break;
352 /* No event with WNOHANG. See if there is one with WUNTRACED. */
353 ret = waitpid (pid, stat_loc, WNOHANG | WUNTRACED);
354 if (ret < 0)
355 {
356 /* An ECHILD error is not indicative of a real problem.
357 It happens for instance while waiting for the inferior
358 to stop after attaching to it. */
359 if (errno != ECHILD)
360 perror_with_name ("waitpid (WNOHANG|WUNTRACED)");
361 }
362 if (ret > 0)
363 break;
364 usleep (1000);
365 }
366 return ret;
367}
368
369/* Implement the wait target_ops method. */
370
371static ptid_t
372lynx_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options)
373{
374 int pid;
375 int ret;
376 int wstat;
377 ptid_t new_ptid;
378
379 if (ptid_equal (ptid, minus_one_ptid))
380 pid = lynx_ptid_get_pid (thread_to_gdb_id (current_inferior));
381 else
382 pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
383
384retry:
385
386 ret = lynx_waitpid (pid, &wstat);
387 new_ptid = lynx_ptid_build (ret, ((union wait *) &wstat)->w_tid);
d631c5a7 388 find_process_pid (ret)->private->last_wait_event_ptid = new_ptid;
8ed54b31
JB
389
390 /* If this is a new thread, then add it now. The reason why we do
391 this here instead of when handling new-thread events is because
392 we need to add the thread associated to the "main" thread - even
393 for non-threaded applications where the new-thread events are not
394 generated. */
395 if (!find_thread_ptid (new_ptid))
8b93d60f
JB
396 {
397 lynx_debug ("New thread: (pid = %d, tid = %d)",
398 lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid));
399 add_thread (new_ptid, NULL);
400 }
8ed54b31
JB
401
402 if (WIFSTOPPED (wstat))
403 {
404 status->kind = TARGET_WAITKIND_STOPPED;
2ea28649 405 status->value.integer = gdb_signal_from_host (WSTOPSIG (wstat));
8ed54b31
JB
406 lynx_debug ("process stopped with signal: %d",
407 status->value.integer);
408 }
409 else if (WIFEXITED (wstat))
410 {
411 status->kind = TARGET_WAITKIND_EXITED;
412 status->value.integer = WEXITSTATUS (wstat);
413 lynx_debug ("process exited with code: %d", status->value.integer);
414 }
415 else if (WIFSIGNALED (wstat))
416 {
417 status->kind = TARGET_WAITKIND_SIGNALLED;
2ea28649 418 status->value.integer = gdb_signal_from_host (WTERMSIG (wstat));
8ed54b31
JB
419 lynx_debug ("process terminated with code: %d",
420 status->value.integer);
421 }
422 else
423 {
424 /* Not sure what happened if we get here, or whether we can
425 in fact get here. But if we do, handle the event the best
426 we can. */
427 status->kind = TARGET_WAITKIND_STOPPED;
2ea28649 428 status->value.integer = gdb_signal_from_host (0);
8ed54b31
JB
429 lynx_debug ("unknown event ????");
430 }
431
432 /* SIGTRAP events are generated for situations other than single-step/
433 breakpoint events (Eg. new-thread events). Handle those other types
434 of events, and resume the execution if necessary. */
435 if (status->kind == TARGET_WAITKIND_STOPPED
a493e3e2 436 && status->value.integer == GDB_SIGNAL_TRAP)
8ed54b31
JB
437 {
438 const int realsig = lynx_ptrace (PTRACE_GETTRACESIG, new_ptid, 0, 0, 0);
439
440 lynx_debug ("(realsig = %d)", realsig);
441 switch (realsig)
442 {
443 case SIGNEWTHREAD:
444 /* We just added the new thread above. No need to do anything
445 further. Just resume the execution again. */
3f6e77ef 446 lynx_continue (new_ptid);
8ed54b31
JB
447 goto retry;
448
449 case SIGTHREADEXIT:
450 remove_thread (find_thread_ptid (new_ptid));
3f6e77ef 451 lynx_continue (new_ptid);
8ed54b31
JB
452 goto retry;
453 }
454 }
455
456 return new_ptid;
457}
458
459/* A wrapper around lynx_wait_1 that also prints debug traces when
460 such debug traces have been activated. */
461
462static ptid_t
463lynx_wait (ptid_t ptid, struct target_waitstatus *status, int options)
464{
465 ptid_t new_ptid;
466
467 lynx_debug ("lynx_wait (pid = %d, tid = %ld)",
468 lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
469 new_ptid = lynx_wait_1 (ptid, status, options);
470 lynx_debug (" -> (pid=%d, tid=%ld, status->kind = %d)",
471 lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid),
472 status->kind);
473 return new_ptid;
474}
475
476/* Implement the kill target_ops method. */
477
478static int
479lynx_kill (int pid)
480{
481 ptid_t ptid = lynx_ptid_build (pid, 0);
482 struct target_waitstatus status;
483 struct process_info *process;
484
485 process = find_process_pid (pid);
486 if (process == NULL)
487 return -1;
488
489 lynx_ptrace (PTRACE_KILL, ptid, 0, 0, 0);
490 lynx_wait (ptid, &status, 0);
491 the_target->mourn (process);
492 return 0;
493}
494
495/* Implement the detach target_ops method. */
496
497static int
498lynx_detach (int pid)
499{
500 ptid_t ptid = lynx_ptid_build (pid, 0);
501 struct process_info *process;
502
503 process = find_process_pid (pid);
504 if (process == NULL)
505 return -1;
506
507 lynx_ptrace (PTRACE_DETACH, ptid, 0, 0, 0);
508 the_target->mourn (process);
509 return 0;
510}
511
512/* Implement the mourn target_ops method. */
513
514static void
515lynx_mourn (struct process_info *proc)
516{
d631c5a7
JB
517 /* Free our private data. */
518 free (proc->private);
519 proc->private = NULL;
520
521 clear_inferiors ();
8ed54b31
JB
522}
523
524/* Implement the join target_ops method. */
525
526static void
527lynx_join (int pid)
528{
529 /* The PTRACE_DETACH is sufficient to detach from the process.
530 So no need to do anything extra. */
531}
532
533/* Implement the thread_alive target_ops method. */
534
535static int
536lynx_thread_alive (ptid_t ptid)
537{
538 /* The list of threads is updated at the end of each wait, so it
539 should be up to date. No need to re-fetch it. */
540 return (find_thread_ptid (ptid) != NULL);
541}
542
543/* Implement the fetch_registers target_ops method. */
544
545static void
546lynx_fetch_registers (struct regcache *regcache, int regno)
547{
548 struct lynx_regset_info *regset = lynx_target_regsets;
549 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
550
551 lynx_debug ("lynx_fetch_registers (regno = %d)", regno);
552
553 while (regset->size >= 0)
554 {
555 char *buf;
556 int res;
557
558 buf = xmalloc (regset->size);
559 res = lynx_ptrace (regset->get_request, inferior_ptid, (int) buf, 0, 0);
560 if (res < 0)
561 perror ("ptrace");
562 regset->store_function (regcache, buf);
563 free (buf);
564 regset++;
565 }
566}
567
568/* Implement the store_registers target_ops method. */
569
570static void
571lynx_store_registers (struct regcache *regcache, int regno)
572{
573 struct lynx_regset_info *regset = lynx_target_regsets;
574 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
575
576 lynx_debug ("lynx_store_registers (regno = %d)", regno);
577
578 while (regset->size >= 0)
579 {
580 char *buf;
581 int res;
582
583 buf = xmalloc (regset->size);
584 res = lynx_ptrace (regset->get_request, inferior_ptid, (int) buf, 0, 0);
585 if (res == 0)
586 {
587 /* Then overlay our cached registers on that. */
588 regset->fill_function (regcache, buf);
589 /* Only now do we write the register set. */
590 res = lynx_ptrace (regset->set_request, inferior_ptid, (int) buf,
591 0, 0);
592 }
593 if (res < 0)
594 perror ("ptrace");
595 free (buf);
596 regset++;
597 }
598}
599
600/* Implement the read_memory target_ops method. */
601
602static int
603lynx_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
604{
605 /* On LynxOS, memory reads needs to be performed in chunks the size
606 of int types, and they should also be aligned accordingly. */
607 int buf;
608 const int xfer_size = sizeof (buf);
609 CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
610 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
611
612 while (addr < memaddr + len)
613 {
614 int skip = 0;
615 int truncate = 0;
616
617 errno = 0;
618 if (addr < memaddr)
619 skip = memaddr - addr;
620 if (addr + xfer_size > memaddr + len)
621 truncate = addr + xfer_size - memaddr - len;
622 buf = lynx_ptrace (PTRACE_PEEKTEXT, inferior_ptid, addr, 0, 0);
623 if (errno)
624 return errno;
625 memcpy (myaddr + (addr - memaddr) + skip, (gdb_byte *) &buf + skip,
626 xfer_size - skip - truncate);
627 addr += xfer_size;
628 }
629
630 return 0;
631}
632
633/* Implement the write_memory target_ops method. */
634
635static int
636lynx_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
637{
638 /* On LynxOS, memory writes needs to be performed in chunks the size
639 of int types, and they should also be aligned accordingly. */
640 int buf;
641 const int xfer_size = sizeof (buf);
642 CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
643 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
644
645 while (addr < memaddr + len)
646 {
647 int skip = 0;
648 int truncate = 0;
649
650 if (addr < memaddr)
651 skip = memaddr - addr;
652 if (addr + xfer_size > memaddr + len)
653 truncate = addr + xfer_size - memaddr - len;
654 if (skip > 0 || truncate > 0)
655 /* We need to read the memory at this address in order to preserve
656 the data that we are not overwriting. */
657 lynx_read_memory (addr, (unsigned char *) &buf, xfer_size);
658 if (errno)
659 return errno;
660 memcpy ((gdb_byte *) &buf + skip, myaddr + (addr - memaddr) + skip,
661 xfer_size - skip - truncate);
662 errno = 0;
663 lynx_ptrace (PTRACE_POKETEXT, inferior_ptid, addr, buf, 0);
664 if (errno)
665 return errno;
666 addr += xfer_size;
667 }
668
669 return 0;
670}
671
672/* Implement the kill_request target_ops method. */
673
674static void
675lynx_request_interrupt (void)
676{
677 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
678
679 kill (lynx_ptid_get_pid (inferior_ptid), SIGINT);
680}
681
682/* The LynxOS target_ops vector. */
683
684static struct target_ops lynx_target_ops = {
685 lynx_create_inferior,
686 lynx_attach,
687 lynx_kill,
688 lynx_detach,
689 lynx_mourn,
690 lynx_join,
691 lynx_thread_alive,
692 lynx_resume,
693 lynx_wait,
694 lynx_fetch_registers,
695 lynx_store_registers,
696 NULL, /* prepare_to_access_memory */
697 NULL, /* done_accessing_memory */
698 lynx_read_memory,
699 lynx_write_memory,
700 NULL, /* look_up_symbols */
701 lynx_request_interrupt,
702 NULL, /* read_auxv */
703 NULL, /* insert_point */
704 NULL, /* remove_point */
705 NULL, /* stopped_by_watchpoint */
706 NULL, /* stopped_data_address */
707 NULL, /* read_offsets */
708 NULL, /* get_tls_address */
709 NULL, /* qxfer_spu */
710 NULL, /* hostio_last_error */
711 NULL, /* qxfer_osdata */
712 NULL, /* qxfer_siginfo */
713 NULL, /* supports_non_stop */
714 NULL, /* async */
715 NULL, /* start_non_stop */
716 NULL, /* supports_multi_process */
717 NULL, /* handle_monitor_command */
718};
719
720void
721initialize_low (void)
722{
723 set_target_ops (&lynx_target_ops);
724 the_low_target.arch_setup ();
725}
726
This page took 0.308718 seconds and 4 git commands to generate.