1 /* Copyright (C) 2009-2012 Free Software Foundation, Inc.
3 This file is part of GDB.
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.
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.
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/>. */
23 #include <sys/ptrace.h>
24 #include <sys/piddef.h> /* Provides PIDGET, TIDGET, BUILDPID, etc. */
26 #include <sys/ioctl.h>
27 #include <sys/types.h>
31 int using_threads
= 1;
33 /* Print a debug trace on standard output if debug_threads is set. */
36 lynx_debug (char *string
, ...)
43 va_start (args
, string
);
44 fprintf (stderr
, "DEBUG(lynx): ");
45 vfprintf (stderr
, string
, args
);
46 fprintf (stderr
, "\n");
50 /* Build a ptid_t given a PID and a LynxOS TID. */
53 lynx_ptid_build (int pid
, long tid
)
55 /* brobecker/2010-06-21: It looks like the LWP field in ptids
56 should be distinct for each thread (see write_ptid where it
57 writes the thread ID from the LWP). So instead of storing
58 the LynxOS tid in the tid field of the ptid, we store it in
60 return ptid_build (pid
, tid
, 0);
63 /* Return the process ID of the given PTID.
65 This function has little reason to exist, it's just a wrapper around
66 ptid_get_pid. But since we have a getter function for the lynxos
67 ptid, it feels cleaner to have a getter for the pid as well. */
70 lynx_ptid_get_pid (ptid_t ptid
)
72 return ptid_get_pid (ptid
);
75 /* Return the LynxOS tid of the given PTID. */
78 lynx_ptid_get_tid (ptid_t ptid
)
80 /* See lynx_ptid_build: The LynxOS tid is stored inside the lwp field
82 return ptid_get_lwp (ptid
);
85 /* For a given PTID, return the associated PID as known by the LynxOS
89 lynx_ptrace_pid_from_ptid (ptid_t ptid
)
91 return BUILDPID (lynx_ptid_get_pid (ptid
), lynx_ptid_get_tid (ptid
));
94 /* Return a string image of the ptrace REQUEST number. */
97 ptrace_request_to_str (int request
)
102 return "PTRACE_TRACEME";
104 case PTRACE_PEEKTEXT
:
105 return "PTRACE_PEEKTEXT";
107 case PTRACE_PEEKDATA
:
108 return "PTRACE_PEEKDATA";
110 case PTRACE_PEEKUSER
:
111 return "PTRACE_PEEKUSER";
113 case PTRACE_POKETEXT
:
114 return "PTRACE_POKETEXT";
116 case PTRACE_POKEDATA
:
117 return "PTRACE_POKEDATA";
119 case PTRACE_POKEUSER
:
120 return "PTRACE_POKEUSER";
123 return "PTRACE_CONT";
126 return "PTRACE_KILL";
128 case PTRACE_SINGLESTEP
:
129 return "PTRACE_SINGLESTEP";
132 return "PTRACE_ATTACH";
135 return "PTRACE_DETACH";
138 return "PTRACE_GETREGS";
141 return "PTRACE_SETREGS";
143 case PTRACE_GETFPREGS
:
144 return "PTRACE_GETFPREGS";
146 case PTRACE_SETFPREGS
:
147 return "PTRACE_SETFPREGS";
149 case PTRACE_READDATA
:
150 return "PTRACE_READDATA";
152 case PTRACE_WRITEDATA
:
153 return "PTRACE_WRITEDATA";
155 case PTRACE_READTEXT
:
156 return "PTRACE_READTEXT";
158 case PTRACE_WRITETEXT
:
159 return "PTRACE_WRITETEXT";
161 case PTRACE_GETFPAREGS
:
162 return "PTRACE_GETFPAREGS";
164 case PTRACE_SETFPAREGS
:
165 return "PTRACE_SETFPAREGS";
167 case PTRACE_GETWINDOW
:
168 return "PTRACE_GETWINDOW";
170 case PTRACE_SETWINDOW
:
171 return "PTRACE_SETWINDOW";
174 return "PTRACE_SYSCALL";
176 case PTRACE_DUMPCORE
:
177 return "PTRACE_DUMPCORE";
179 case PTRACE_SETWRBKPT
:
180 return "PTRACE_SETWRBKPT";
182 case PTRACE_SETACBKPT
:
183 return "PTRACE_SETACBKPT";
186 return "PTRACE_CLRBKPT";
188 case PTRACE_GET_UCODE
:
189 return "PTRACE_GET_UCODE";
193 return "PT_READ_GPR";
198 return "PT_WRITE_GPR";
203 return "PT_READ_FPR";
208 return "PT_WRITE_FPR";
213 return "PT_READ_VPR";
218 return "PT_WRITE_VPR";
221 #ifdef PTRACE_PEEKUSP
223 return "PTRACE_PEEKUSP";
226 #ifdef PTRACE_POKEUSP
228 return "PTRACE_POKEUSP";
231 case PTRACE_PEEKTHREAD
:
232 return "PTRACE_PEEKTHREAD";
234 case PTRACE_THREADUSER
:
235 return "PTRACE_THREADUSER";
238 return "PTRACE_FPREAD";
241 return "PTRACE_FPWRITE";
244 return "PTRACE_SETSIG";
246 case PTRACE_CONT_ONE
:
247 return "PTRACE_CONT_ONE";
249 case PTRACE_KILL_ONE
:
250 return "PTRACE_KILL_ONE";
252 case PTRACE_SINGLESTEP_ONE
:
253 return "PTRACE_SINGLESTEP_ONE";
255 case PTRACE_GETLOADINFO
:
256 return "PTRACE_GETLOADINFO";
258 case PTRACE_GETTRACESIG
:
259 return "PTRACE_GETTRACESIG";
261 #ifdef PTRACE_GETTHREADLIST
262 case PTRACE_GETTHREADLIST
:
263 return "PTRACE_GETTHREADLIST";
267 return "<unknown-request>";
270 /* A wrapper around ptrace that allows us to print debug traces of
271 ptrace calls if debug traces are activated. */
274 lynx_ptrace (int request
, ptid_t ptid
, int addr
, int data
, int addr2
)
277 const int pid
= lynx_ptrace_pid_from_ptid (ptid
);
281 fprintf (stderr
, "PTRACE (%s, pid=%d(pid=%d, tid=%d), addr=0x%x, "
282 "data=0x%x, addr2=0x%x)",
283 ptrace_request_to_str (request
), pid
, PIDGET (pid
), TIDGET (pid
),
285 result
= ptrace (request
, pid
, addr
, data
, addr2
);
288 fprintf (stderr
, " -> %d (=0x%x)\n", result
, result
);
294 /* Implement the create_inferior method of the target_ops vector. */
297 lynx_create_inferior (char *program
, char **allargs
)
301 lynx_debug ("lynx_create_inferior ()");
305 perror_with_name ("fork");
311 /* Switch child to its own process group so that signals won't
312 directly affect gdbserver. */
315 ioctl (0, TIOCSPGRP
, &pgrp
);
316 lynx_ptrace (PTRACE_TRACEME
, null_ptid
, 0, 0, 0);
317 execv (program
, allargs
);
318 fprintf (stderr
, "Cannot exec %s: %s.\n", program
, strerror (errno
));
323 add_process (pid
, 0);
324 /* Do not add the process thread just yet, as we do not know its tid.
325 We will add it later, during the wait for the STOP event corresponding
326 to the lynx_ptrace (PTRACE_TRACEME) call above. */
330 /* Implement the attach target_ops method. */
333 lynx_attach (unsigned long pid
)
335 ptid_t ptid
= lynx_ptid_build (pid
, 0);
337 if (lynx_ptrace (PTRACE_ATTACH
, ptid
, 0, 0, 0) != 0)
338 error ("Cannot attach to process %lu: %s (%d)\n", pid
,
339 strerror (errno
), errno
);
341 add_process (pid
, 1);
342 add_thread (ptid
, NULL
);
347 /* Implement the resume target_ops method. */
350 lynx_resume (struct thread_resume
*resume_info
, size_t n
)
352 ptid_t inferior_ptid
= thread_to_gdb_id (current_inferior
);
353 /* FIXME: Assume for now that n == 1. */
354 const int request
= (resume_info
[0].kind
== resume_step
355 ? PTRACE_SINGLESTEP
: PTRACE_CONT
);
356 const int signal
= resume_info
[0].sig
;
359 regcache_invalidate ();
360 ret
= lynx_ptrace (request
, inferior_ptid
, 1, signal
, 0);
363 /* Resume the execution of the given PTID. */
366 lynx_continue (ptid_t ptid
)
368 struct thread_resume resume_info
;
370 resume_info
.thread
= ptid
;
371 resume_info
.kind
= resume_continue
;
374 lynx_resume (&resume_info
, 1);
377 /* Remove all inferiors and associated threads. */
380 lynx_clear_inferiors (void)
382 /* We do not use private data, so nothing much to do except calling
387 /* A wrapper around waitpid that handles the various idiosyncrasies
388 of LynxOS' waitpid. */
391 lynx_waitpid (int pid
, int *stat_loc
)
397 ret
= waitpid (pid
, stat_loc
, WNOHANG
);
400 /* An ECHILD error is not indicative of a real problem.
401 It happens for instance while waiting for the inferior
402 to stop after attaching to it. */
404 perror_with_name ("waitpid (WNOHANG)");
408 /* No event with WNOHANG. See if there is one with WUNTRACED. */
409 ret
= waitpid (pid
, stat_loc
, WNOHANG
| WUNTRACED
);
412 /* An ECHILD error is not indicative of a real problem.
413 It happens for instance while waiting for the inferior
414 to stop after attaching to it. */
416 perror_with_name ("waitpid (WNOHANG|WUNTRACED)");
425 /* Implement the wait target_ops method. */
428 lynx_wait_1 (ptid_t ptid
, struct target_waitstatus
*status
, int options
)
435 if (ptid_equal (ptid
, minus_one_ptid
))
436 pid
= lynx_ptid_get_pid (thread_to_gdb_id (current_inferior
));
438 pid
= BUILDPID (lynx_ptid_get_pid (ptid
), lynx_ptid_get_tid (ptid
));
442 ret
= lynx_waitpid (pid
, &wstat
);
443 new_ptid
= lynx_ptid_build (ret
, ((union wait
*) &wstat
)->w_tid
);
445 /* If this is a new thread, then add it now. The reason why we do
446 this here instead of when handling new-thread events is because
447 we need to add the thread associated to the "main" thread - even
448 for non-threaded applications where the new-thread events are not
450 if (!find_thread_ptid (new_ptid
))
451 add_thread (new_ptid
, NULL
);
453 if (WIFSTOPPED (wstat
))
455 status
->kind
= TARGET_WAITKIND_STOPPED
;
456 status
->value
.integer
= gdb_signal_from_host (WSTOPSIG (wstat
));
457 lynx_debug ("process stopped with signal: %d",
458 status
->value
.integer
);
460 else if (WIFEXITED (wstat
))
462 status
->kind
= TARGET_WAITKIND_EXITED
;
463 status
->value
.integer
= WEXITSTATUS (wstat
);
464 lynx_debug ("process exited with code: %d", status
->value
.integer
);
466 else if (WIFSIGNALED (wstat
))
468 status
->kind
= TARGET_WAITKIND_SIGNALLED
;
469 status
->value
.integer
= gdb_signal_from_host (WTERMSIG (wstat
));
470 lynx_debug ("process terminated with code: %d",
471 status
->value
.integer
);
475 /* Not sure what happened if we get here, or whether we can
476 in fact get here. But if we do, handle the event the best
478 status
->kind
= TARGET_WAITKIND_STOPPED
;
479 status
->value
.integer
= gdb_signal_from_host (0);
480 lynx_debug ("unknown event ????");
483 /* SIGTRAP events are generated for situations other than single-step/
484 breakpoint events (Eg. new-thread events). Handle those other types
485 of events, and resume the execution if necessary. */
486 if (status
->kind
== TARGET_WAITKIND_STOPPED
487 && status
->value
.integer
== GDB_SIGNAL_TRAP
)
489 const int realsig
= lynx_ptrace (PTRACE_GETTRACESIG
, new_ptid
, 0, 0, 0);
491 lynx_debug ("(realsig = %d)", realsig
);
495 /* We just added the new thread above. No need to do anything
496 further. Just resume the execution again. */
497 lynx_continue (ptid
);
501 remove_thread (find_thread_ptid (new_ptid
));
502 lynx_continue (ptid
);
510 /* A wrapper around lynx_wait_1 that also prints debug traces when
511 such debug traces have been activated. */
514 lynx_wait (ptid_t ptid
, struct target_waitstatus
*status
, int options
)
518 lynx_debug ("lynx_wait (pid = %d, tid = %ld)",
519 lynx_ptid_get_pid (ptid
), lynx_ptid_get_tid (ptid
));
520 new_ptid
= lynx_wait_1 (ptid
, status
, options
);
521 lynx_debug (" -> (pid=%d, tid=%ld, status->kind = %d)",
522 lynx_ptid_get_pid (new_ptid
), lynx_ptid_get_tid (new_ptid
),
527 /* Implement the kill target_ops method. */
532 ptid_t ptid
= lynx_ptid_build (pid
, 0);
533 struct target_waitstatus status
;
534 struct process_info
*process
;
536 process
= find_process_pid (pid
);
540 lynx_ptrace (PTRACE_KILL
, ptid
, 0, 0, 0);
541 lynx_wait (ptid
, &status
, 0);
542 the_target
->mourn (process
);
546 /* Implement the detach target_ops method. */
549 lynx_detach (int pid
)
551 ptid_t ptid
= lynx_ptid_build (pid
, 0);
552 struct process_info
*process
;
554 process
= find_process_pid (pid
);
558 lynx_ptrace (PTRACE_DETACH
, ptid
, 0, 0, 0);
559 the_target
->mourn (process
);
563 /* Implement the mourn target_ops method. */
566 lynx_mourn (struct process_info
*proc
)
568 lynx_clear_inferiors ();
571 /* Implement the join target_ops method. */
576 /* The PTRACE_DETACH is sufficient to detach from the process.
577 So no need to do anything extra. */
580 /* Implement the thread_alive target_ops method. */
583 lynx_thread_alive (ptid_t ptid
)
585 /* The list of threads is updated at the end of each wait, so it
586 should be up to date. No need to re-fetch it. */
587 return (find_thread_ptid (ptid
) != NULL
);
590 /* Implement the fetch_registers target_ops method. */
593 lynx_fetch_registers (struct regcache
*regcache
, int regno
)
595 struct lynx_regset_info
*regset
= lynx_target_regsets
;
596 ptid_t inferior_ptid
= thread_to_gdb_id (current_inferior
);
598 lynx_debug ("lynx_fetch_registers (regno = %d)", regno
);
600 while (regset
->size
>= 0)
605 buf
= xmalloc (regset
->size
);
606 res
= lynx_ptrace (regset
->get_request
, inferior_ptid
, (int) buf
, 0, 0);
609 regset
->store_function (regcache
, buf
);
615 /* Implement the store_registers target_ops method. */
618 lynx_store_registers (struct regcache
*regcache
, int regno
)
620 struct lynx_regset_info
*regset
= lynx_target_regsets
;
621 ptid_t inferior_ptid
= thread_to_gdb_id (current_inferior
);
623 lynx_debug ("lynx_store_registers (regno = %d)", regno
);
625 while (regset
->size
>= 0)
630 buf
= xmalloc (regset
->size
);
631 res
= lynx_ptrace (regset
->get_request
, inferior_ptid
, (int) buf
, 0, 0);
634 /* Then overlay our cached registers on that. */
635 regset
->fill_function (regcache
, buf
);
636 /* Only now do we write the register set. */
637 res
= lynx_ptrace (regset
->set_request
, inferior_ptid
, (int) buf
,
647 /* Implement the read_memory target_ops method. */
650 lynx_read_memory (CORE_ADDR memaddr
, unsigned char *myaddr
, int len
)
652 /* On LynxOS, memory reads needs to be performed in chunks the size
653 of int types, and they should also be aligned accordingly. */
655 const int xfer_size
= sizeof (buf
);
656 CORE_ADDR addr
= memaddr
& -(CORE_ADDR
) xfer_size
;
657 ptid_t inferior_ptid
= thread_to_gdb_id (current_inferior
);
659 while (addr
< memaddr
+ len
)
666 skip
= memaddr
- addr
;
667 if (addr
+ xfer_size
> memaddr
+ len
)
668 truncate
= addr
+ xfer_size
- memaddr
- len
;
669 buf
= lynx_ptrace (PTRACE_PEEKTEXT
, inferior_ptid
, addr
, 0, 0);
672 memcpy (myaddr
+ (addr
- memaddr
) + skip
, (gdb_byte
*) &buf
+ skip
,
673 xfer_size
- skip
- truncate
);
680 /* Implement the write_memory target_ops method. */
683 lynx_write_memory (CORE_ADDR memaddr
, const unsigned char *myaddr
, int len
)
685 /* On LynxOS, memory writes needs to be performed in chunks the size
686 of int types, and they should also be aligned accordingly. */
688 const int xfer_size
= sizeof (buf
);
689 CORE_ADDR addr
= memaddr
& -(CORE_ADDR
) xfer_size
;
690 ptid_t inferior_ptid
= thread_to_gdb_id (current_inferior
);
692 while (addr
< memaddr
+ len
)
698 skip
= memaddr
- addr
;
699 if (addr
+ xfer_size
> memaddr
+ len
)
700 truncate
= addr
+ xfer_size
- memaddr
- len
;
701 if (skip
> 0 || truncate
> 0)
702 /* We need to read the memory at this address in order to preserve
703 the data that we are not overwriting. */
704 lynx_read_memory (addr
, (unsigned char *) &buf
, xfer_size
);
707 memcpy ((gdb_byte
*) &buf
+ skip
, myaddr
+ (addr
- memaddr
) + skip
,
708 xfer_size
- skip
- truncate
);
710 lynx_ptrace (PTRACE_POKETEXT
, inferior_ptid
, addr
, buf
, 0);
719 /* Implement the kill_request target_ops method. */
722 lynx_request_interrupt (void)
724 ptid_t inferior_ptid
= thread_to_gdb_id (current_inferior
);
726 kill (lynx_ptid_get_pid (inferior_ptid
), SIGINT
);
729 /* The LynxOS target_ops vector. */
731 static struct target_ops lynx_target_ops
= {
732 lynx_create_inferior
,
741 lynx_fetch_registers
,
742 lynx_store_registers
,
743 NULL
, /* prepare_to_access_memory */
744 NULL
, /* done_accessing_memory */
747 NULL
, /* look_up_symbols */
748 lynx_request_interrupt
,
749 NULL
, /* read_auxv */
750 NULL
, /* insert_point */
751 NULL
, /* remove_point */
752 NULL
, /* stopped_by_watchpoint */
753 NULL
, /* stopped_data_address */
754 NULL
, /* read_offsets */
755 NULL
, /* get_tls_address */
756 NULL
, /* qxfer_spu */
757 NULL
, /* hostio_last_error */
758 NULL
, /* qxfer_osdata */
759 NULL
, /* qxfer_siginfo */
760 NULL
, /* supports_non_stop */
762 NULL
, /* start_non_stop */
763 NULL
, /* supports_multi_process */
764 NULL
, /* handle_monitor_command */
768 initialize_low (void)
770 set_target_ops (&lynx_target_ops
);
771 the_low_target
.arch_setup ();