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