xref: /dragonfly/contrib/gdb-7/gdb/inf-ptrace.c (revision 74a8b0f5)
15796c8dcSSimon Schubert /* Low-level child interface to ptrace.
25796c8dcSSimon Schubert 
3a45ae5f8SJohn Marino    Copyright (C) 1988-2013 Free Software Foundation, Inc.
4a45ae5f8SJohn Marino 
55796c8dcSSimon Schubert    This file is part of GDB.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert    (at your option) any later version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155796c8dcSSimon Schubert    GNU General Public License for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
195796c8dcSSimon Schubert 
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "command.h"
225796c8dcSSimon Schubert #include "inferior.h"
235796c8dcSSimon Schubert #include "inflow.h"
245796c8dcSSimon Schubert #include "terminal.h"
255796c8dcSSimon Schubert #include "gdbcore.h"
265796c8dcSSimon Schubert #include "regcache.h"
275796c8dcSSimon Schubert 
285796c8dcSSimon Schubert #include "gdb_assert.h"
295796c8dcSSimon Schubert #include "gdb_string.h"
305796c8dcSSimon Schubert #include "gdb_ptrace.h"
315796c8dcSSimon Schubert #include "gdb_wait.h"
325796c8dcSSimon Schubert #include <signal.h>
335796c8dcSSimon Schubert 
345796c8dcSSimon Schubert #include "inf-ptrace.h"
355796c8dcSSimon Schubert #include "inf-child.h"
365796c8dcSSimon Schubert #include "gdbthread.h"
375796c8dcSSimon Schubert 
385796c8dcSSimon Schubert 
395796c8dcSSimon Schubert 
405796c8dcSSimon Schubert #ifdef PT_GET_PROCESS_STATE
415796c8dcSSimon Schubert 
425796c8dcSSimon Schubert static int
inf_ptrace_follow_fork(struct target_ops * ops,int follow_child)435796c8dcSSimon Schubert inf_ptrace_follow_fork (struct target_ops *ops, int follow_child)
445796c8dcSSimon Schubert {
455796c8dcSSimon Schubert   pid_t pid, fpid;
465796c8dcSSimon Schubert   ptrace_state_t pe;
475796c8dcSSimon Schubert 
485796c8dcSSimon Schubert   pid = ptid_get_pid (inferior_ptid);
495796c8dcSSimon Schubert 
505796c8dcSSimon Schubert   if (ptrace (PT_GET_PROCESS_STATE, pid,
515796c8dcSSimon Schubert 	       (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
525796c8dcSSimon Schubert     perror_with_name (("ptrace"));
535796c8dcSSimon Schubert 
545796c8dcSSimon Schubert   gdb_assert (pe.pe_report_event == PTRACE_FORK);
555796c8dcSSimon Schubert   fpid = pe.pe_other_pid;
565796c8dcSSimon Schubert 
575796c8dcSSimon Schubert   if (follow_child)
585796c8dcSSimon Schubert     {
595796c8dcSSimon Schubert       struct inferior *parent_inf, *child_inf;
605796c8dcSSimon Schubert       struct thread_info *tp;
615796c8dcSSimon Schubert 
625796c8dcSSimon Schubert       parent_inf = find_inferior_pid (pid);
635796c8dcSSimon Schubert 
645796c8dcSSimon Schubert       /* Add the child.  */
655796c8dcSSimon Schubert       child_inf = add_inferior (fpid);
665796c8dcSSimon Schubert       child_inf->attach_flag = parent_inf->attach_flag;
675796c8dcSSimon Schubert       copy_terminal_info (child_inf, parent_inf);
685796c8dcSSimon Schubert       child_inf->pspace = parent_inf->pspace;
69cf7f2e2dSJohn Marino       child_inf->aspace = parent_inf->aspace;
70cf7f2e2dSJohn Marino 
715796c8dcSSimon Schubert       /* Before detaching from the parent, remove all breakpoints from
725796c8dcSSimon Schubert 	 it.  */
735796c8dcSSimon Schubert       remove_breakpoints ();
745796c8dcSSimon Schubert 
755796c8dcSSimon Schubert       if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
765796c8dcSSimon Schubert 	perror_with_name (("ptrace"));
775796c8dcSSimon Schubert 
785796c8dcSSimon Schubert       /* Switch inferior_ptid out of the parent's way.  */
795796c8dcSSimon Schubert       inferior_ptid = pid_to_ptid (fpid);
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert       /* Delete the parent.  */
825796c8dcSSimon Schubert       detach_inferior (pid);
835796c8dcSSimon Schubert 
845796c8dcSSimon Schubert       add_thread_silent (inferior_ptid);
855796c8dcSSimon Schubert     }
865796c8dcSSimon Schubert   else
875796c8dcSSimon Schubert     {
885796c8dcSSimon Schubert       /* Breakpoints have already been detached from the child by
895796c8dcSSimon Schubert 	 infrun.c.  */
905796c8dcSSimon Schubert 
915796c8dcSSimon Schubert       if (ptrace (PT_DETACH, fpid, (PTRACE_TYPE_ARG3)1, 0) == -1)
925796c8dcSSimon Schubert 	perror_with_name (("ptrace"));
935796c8dcSSimon Schubert     }
945796c8dcSSimon Schubert 
955796c8dcSSimon Schubert   return 0;
965796c8dcSSimon Schubert }
975796c8dcSSimon Schubert 
985796c8dcSSimon Schubert #endif /* PT_GET_PROCESS_STATE */
995796c8dcSSimon Schubert 
1005796c8dcSSimon Schubert 
1015796c8dcSSimon Schubert /* Prepare to be traced.  */
1025796c8dcSSimon Schubert 
1035796c8dcSSimon Schubert static void
inf_ptrace_me(void)1045796c8dcSSimon Schubert inf_ptrace_me (void)
1055796c8dcSSimon Schubert {
1065796c8dcSSimon Schubert   /* "Trace me, Dr. Memory!"  */
1075796c8dcSSimon Schubert   ptrace (PT_TRACE_ME, 0, (PTRACE_TYPE_ARG3)0, 0);
1085796c8dcSSimon Schubert }
1095796c8dcSSimon Schubert 
1105796c8dcSSimon Schubert /* Start a new inferior Unix child process.  EXEC_FILE is the file to
1115796c8dcSSimon Schubert    run, ALLARGS is a string containing the arguments to the program.
1125796c8dcSSimon Schubert    ENV is the environment vector to pass.  If FROM_TTY is non-zero, be
1135796c8dcSSimon Schubert    chatty about it.  */
1145796c8dcSSimon Schubert 
1155796c8dcSSimon Schubert static void
inf_ptrace_create_inferior(struct target_ops * ops,char * exec_file,char * allargs,char ** env,int from_tty)1165796c8dcSSimon Schubert inf_ptrace_create_inferior (struct target_ops *ops,
1175796c8dcSSimon Schubert 			    char *exec_file, char *allargs, char **env,
1185796c8dcSSimon Schubert 			    int from_tty)
1195796c8dcSSimon Schubert {
1205796c8dcSSimon Schubert   int pid;
1215796c8dcSSimon Schubert 
1225796c8dcSSimon Schubert   /* Do not change either targets above or the same target if already present.
123c50c785cSJohn Marino      The reason is the target stack is shared across multiple inferiors.  */
124c50c785cSJohn Marino   int ops_already_pushed = target_is_pushed (ops);
125c50c785cSJohn Marino   struct cleanup *back_to = NULL;
126c50c785cSJohn Marino 
127c50c785cSJohn Marino   if (! ops_already_pushed)
128c50c785cSJohn Marino     {
129c50c785cSJohn Marino       /* Clear possible core file with its process_stratum.  */
130c50c785cSJohn Marino       push_target (ops);
131c50c785cSJohn Marino       back_to = make_cleanup_unpush_target (ops);
132c50c785cSJohn Marino     }
133c50c785cSJohn Marino 
134c50c785cSJohn Marino   pid = fork_inferior (exec_file, allargs, env, inf_ptrace_me, NULL,
1355796c8dcSSimon Schubert 		       NULL, NULL, NULL);
136a45ae5f8SJohn Marino 
1375796c8dcSSimon Schubert   if (! ops_already_pushed)
138c50c785cSJohn Marino     discard_cleanups (back_to);
139c50c785cSJohn Marino 
1405796c8dcSSimon Schubert   /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
1415796c8dcSSimon Schubert      be 1 or 2 depending on whether we're starting without or with a
1425796c8dcSSimon Schubert      shell.  */
1435796c8dcSSimon Schubert   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
1445796c8dcSSimon Schubert 
1455796c8dcSSimon Schubert   /* On some targets, there must be some explicit actions taken after
1465796c8dcSSimon Schubert      the inferior has been started up.  */
1475796c8dcSSimon Schubert   target_post_startup_inferior (pid_to_ptid (pid));
1485796c8dcSSimon Schubert }
1495796c8dcSSimon Schubert 
1505796c8dcSSimon Schubert #ifdef PT_GET_PROCESS_STATE
1515796c8dcSSimon Schubert 
1525796c8dcSSimon Schubert static void
inf_ptrace_post_startup_inferior(ptid_t pid)1535796c8dcSSimon Schubert inf_ptrace_post_startup_inferior (ptid_t pid)
1545796c8dcSSimon Schubert {
1555796c8dcSSimon Schubert   ptrace_event_t pe;
1565796c8dcSSimon Schubert 
1575796c8dcSSimon Schubert   /* Set the initial event mask.  */
1585796c8dcSSimon Schubert   memset (&pe, 0, sizeof pe);
1595796c8dcSSimon Schubert   pe.pe_set_event |= PTRACE_FORK;
1605796c8dcSSimon Schubert   if (ptrace (PT_SET_EVENT_MASK, ptid_get_pid (pid),
1615796c8dcSSimon Schubert 	      (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
1625796c8dcSSimon Schubert     perror_with_name (("ptrace"));
1635796c8dcSSimon Schubert }
1645796c8dcSSimon Schubert 
1655796c8dcSSimon Schubert #endif
1665796c8dcSSimon Schubert 
1675796c8dcSSimon Schubert /* Clean up a rotting corpse of an inferior after it died.  */
1685796c8dcSSimon Schubert 
1695796c8dcSSimon Schubert static void
inf_ptrace_mourn_inferior(struct target_ops * ops)1705796c8dcSSimon Schubert inf_ptrace_mourn_inferior (struct target_ops *ops)
1715796c8dcSSimon Schubert {
1725796c8dcSSimon Schubert   int status;
1735796c8dcSSimon Schubert 
1745796c8dcSSimon Schubert   /* Wait just one more time to collect the inferior's exit status.
1755796c8dcSSimon Schubert      Do not check whether this succeeds though, since we may be
1765796c8dcSSimon Schubert      dealing with a process that we attached to.  Such a process will
1775796c8dcSSimon Schubert      only report its exit status to its original parent.  */
1785796c8dcSSimon Schubert   waitpid (ptid_get_pid (inferior_ptid), &status, 0);
1795796c8dcSSimon Schubert 
1805796c8dcSSimon Schubert   generic_mourn_inferior ();
1815796c8dcSSimon Schubert 
1825796c8dcSSimon Schubert   if (!have_inferiors ())
1835796c8dcSSimon Schubert     unpush_target (ops);
1845796c8dcSSimon Schubert }
1855796c8dcSSimon Schubert 
1865796c8dcSSimon Schubert /* Attach to the process specified by ARGS.  If FROM_TTY is non-zero,
1875796c8dcSSimon Schubert    be chatty about it.  */
1885796c8dcSSimon Schubert 
1895796c8dcSSimon Schubert static void
inf_ptrace_attach(struct target_ops * ops,char * args,int from_tty)1905796c8dcSSimon Schubert inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty)
1915796c8dcSSimon Schubert {
1925796c8dcSSimon Schubert   char *exec_file;
1935796c8dcSSimon Schubert   pid_t pid;
1945796c8dcSSimon Schubert   struct inferior *inf;
1955796c8dcSSimon Schubert 
1965796c8dcSSimon Schubert   /* Do not change either targets above or the same target if already present.
197c50c785cSJohn Marino      The reason is the target stack is shared across multiple inferiors.  */
198c50c785cSJohn Marino   int ops_already_pushed = target_is_pushed (ops);
199c50c785cSJohn Marino   struct cleanup *back_to = NULL;
200c50c785cSJohn Marino 
201c50c785cSJohn Marino   pid = parse_pid_to_attach (args);
202cf7f2e2dSJohn Marino 
2035796c8dcSSimon Schubert   if (pid == getpid ())		/* Trying to masturbate?  */
2045796c8dcSSimon Schubert     error (_("I refuse to debug myself!"));
2055796c8dcSSimon Schubert 
2065796c8dcSSimon Schubert   if (! ops_already_pushed)
207c50c785cSJohn Marino     {
208c50c785cSJohn Marino       /* target_pid_to_str already uses the target.  Also clear possible core
209c50c785cSJohn Marino 	 file with its process_stratum.  */
210c50c785cSJohn Marino       push_target (ops);
211c50c785cSJohn Marino       back_to = make_cleanup_unpush_target (ops);
212c50c785cSJohn Marino     }
213c50c785cSJohn Marino 
214c50c785cSJohn Marino   if (from_tty)
2155796c8dcSSimon Schubert     {
2165796c8dcSSimon Schubert       exec_file = get_exec_file (0);
2175796c8dcSSimon Schubert 
2185796c8dcSSimon Schubert       if (exec_file)
2195796c8dcSSimon Schubert 	printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
2205796c8dcSSimon Schubert 			   target_pid_to_str (pid_to_ptid (pid)));
2215796c8dcSSimon Schubert       else
2225796c8dcSSimon Schubert 	printf_unfiltered (_("Attaching to %s\n"),
2235796c8dcSSimon Schubert 			   target_pid_to_str (pid_to_ptid (pid)));
2245796c8dcSSimon Schubert 
2255796c8dcSSimon Schubert       gdb_flush (gdb_stdout);
2265796c8dcSSimon Schubert     }
2275796c8dcSSimon Schubert 
2285796c8dcSSimon Schubert #ifdef PT_ATTACH
2295796c8dcSSimon Schubert   errno = 0;
2305796c8dcSSimon Schubert   ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
2315796c8dcSSimon Schubert   if (errno != 0)
2325796c8dcSSimon Schubert     perror_with_name (("ptrace"));
2335796c8dcSSimon Schubert #else
2345796c8dcSSimon Schubert   error (_("This system does not support attaching to a process"));
2355796c8dcSSimon Schubert #endif
2365796c8dcSSimon Schubert 
2375796c8dcSSimon Schubert   inf = current_inferior ();
238cf7f2e2dSJohn Marino   inferior_appeared (inf, pid);
239cf7f2e2dSJohn Marino   inf->attach_flag = 1;
2405796c8dcSSimon Schubert   inferior_ptid = pid_to_ptid (pid);
241cf7f2e2dSJohn Marino 
2425796c8dcSSimon Schubert   /* Always add a main thread.  If some target extends the ptrace
2435796c8dcSSimon Schubert      target, it should decorate the ptid later with more info.  */
2445796c8dcSSimon Schubert   add_thread_silent (inferior_ptid);
2455796c8dcSSimon Schubert 
2465796c8dcSSimon Schubert   if (! ops_already_pushed)
247c50c785cSJohn Marino     discard_cleanups (back_to);
248c50c785cSJohn Marino }
2495796c8dcSSimon Schubert 
2505796c8dcSSimon Schubert #ifdef PT_GET_PROCESS_STATE
2515796c8dcSSimon Schubert 
2525796c8dcSSimon Schubert static void
inf_ptrace_post_attach(int pid)2535796c8dcSSimon Schubert inf_ptrace_post_attach (int pid)
2545796c8dcSSimon Schubert {
2555796c8dcSSimon Schubert   ptrace_event_t pe;
2565796c8dcSSimon Schubert 
2575796c8dcSSimon Schubert   /* Set the initial event mask.  */
2585796c8dcSSimon Schubert   memset (&pe, 0, sizeof pe);
2595796c8dcSSimon Schubert   pe.pe_set_event |= PTRACE_FORK;
2605796c8dcSSimon Schubert   if (ptrace (PT_SET_EVENT_MASK, pid,
2615796c8dcSSimon Schubert 	      (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
2625796c8dcSSimon Schubert     perror_with_name (("ptrace"));
2635796c8dcSSimon Schubert }
2645796c8dcSSimon Schubert 
2655796c8dcSSimon Schubert #endif
2665796c8dcSSimon Schubert 
2675796c8dcSSimon Schubert /* Detach from the inferior, optionally passing it the signal
2685796c8dcSSimon Schubert    specified by ARGS.  If FROM_TTY is non-zero, be chatty about it.  */
2695796c8dcSSimon Schubert 
2705796c8dcSSimon Schubert static void
inf_ptrace_detach(struct target_ops * ops,char * args,int from_tty)2715796c8dcSSimon Schubert inf_ptrace_detach (struct target_ops *ops, char *args, int from_tty)
2725796c8dcSSimon Schubert {
2735796c8dcSSimon Schubert   pid_t pid = ptid_get_pid (inferior_ptid);
2745796c8dcSSimon Schubert   int sig = 0;
2755796c8dcSSimon Schubert 
2765796c8dcSSimon Schubert   if (from_tty)
2775796c8dcSSimon Schubert     {
2785796c8dcSSimon Schubert       char *exec_file = get_exec_file (0);
2795796c8dcSSimon Schubert       if (exec_file == 0)
2805796c8dcSSimon Schubert 	exec_file = "";
2815796c8dcSSimon Schubert       printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
2825796c8dcSSimon Schubert 			 target_pid_to_str (pid_to_ptid (pid)));
2835796c8dcSSimon Schubert       gdb_flush (gdb_stdout);
2845796c8dcSSimon Schubert     }
2855796c8dcSSimon Schubert   if (args)
2865796c8dcSSimon Schubert     sig = atoi (args);
2875796c8dcSSimon Schubert 
2885796c8dcSSimon Schubert #ifdef PT_DETACH
2895796c8dcSSimon Schubert   /* We'd better not have left any breakpoints in the program or it'll
2905796c8dcSSimon Schubert      die when it hits one.  Also note that this may only work if we
2915796c8dcSSimon Schubert      previously attached to the inferior.  It *might* work if we
2925796c8dcSSimon Schubert      started the process ourselves.  */
2935796c8dcSSimon Schubert   errno = 0;
2945796c8dcSSimon Schubert   ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, sig);
2955796c8dcSSimon Schubert   if (errno != 0)
2965796c8dcSSimon Schubert     perror_with_name (("ptrace"));
2975796c8dcSSimon Schubert #else
2985796c8dcSSimon Schubert   error (_("This system does not support detaching from a process"));
2995796c8dcSSimon Schubert #endif
3005796c8dcSSimon Schubert 
3015796c8dcSSimon Schubert   inferior_ptid = null_ptid;
3025796c8dcSSimon Schubert   detach_inferior (pid);
3035796c8dcSSimon Schubert 
3045796c8dcSSimon Schubert   if (!have_inferiors ())
3055796c8dcSSimon Schubert     unpush_target (ops);
3065796c8dcSSimon Schubert }
3075796c8dcSSimon Schubert 
3085796c8dcSSimon Schubert /* Kill the inferior.  */
3095796c8dcSSimon Schubert 
3105796c8dcSSimon Schubert static void
inf_ptrace_kill(struct target_ops * ops)3115796c8dcSSimon Schubert inf_ptrace_kill (struct target_ops *ops)
3125796c8dcSSimon Schubert {
3135796c8dcSSimon Schubert   pid_t pid = ptid_get_pid (inferior_ptid);
3145796c8dcSSimon Schubert   int status;
3155796c8dcSSimon Schubert 
3165796c8dcSSimon Schubert   if (pid == 0)
317*74a8b0f5SJohn Marino     return;
3185796c8dcSSimon Schubert 
3195796c8dcSSimon Schubert   ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3)0, 0);
3205796c8dcSSimon Schubert   waitpid (pid, &status, 0);
3215796c8dcSSimon Schubert 
3225796c8dcSSimon Schubert   target_mourn_inferior ();
3235796c8dcSSimon Schubert }
3245796c8dcSSimon Schubert 
3255796c8dcSSimon Schubert /* Stop the inferior.  */
3265796c8dcSSimon Schubert 
3275796c8dcSSimon Schubert static void
inf_ptrace_stop(ptid_t ptid)3285796c8dcSSimon Schubert inf_ptrace_stop (ptid_t ptid)
3295796c8dcSSimon Schubert {
3305796c8dcSSimon Schubert   /* Send a SIGINT to the process group.  This acts just like the user
3315796c8dcSSimon Schubert      typed a ^C on the controlling terminal.  Note that using a
3325796c8dcSSimon Schubert      negative process number in kill() is a System V-ism.  The proper
3335796c8dcSSimon Schubert      BSD interface is killpg().  However, all modern BSDs support the
3345796c8dcSSimon Schubert      System V interface too.  */
3355796c8dcSSimon Schubert   kill (-inferior_process_group (), SIGINT);
3365796c8dcSSimon Schubert }
3375796c8dcSSimon Schubert 
3385796c8dcSSimon Schubert /* Resume execution of thread PTID, or all threads if PTID is -1.  If
3395796c8dcSSimon Schubert    STEP is nonzero, single-step it.  If SIGNAL is nonzero, give it
3405796c8dcSSimon Schubert    that signal.  */
3415796c8dcSSimon Schubert 
3425796c8dcSSimon Schubert static void
inf_ptrace_resume(struct target_ops * ops,ptid_t ptid,int step,enum gdb_signal signal)3435796c8dcSSimon Schubert inf_ptrace_resume (struct target_ops *ops,
3445796c8dcSSimon Schubert 		   ptid_t ptid, int step, enum gdb_signal signal)
3455796c8dcSSimon Schubert {
3465796c8dcSSimon Schubert   pid_t pid = ptid_get_pid (ptid);
3475796c8dcSSimon Schubert   int request;
3485796c8dcSSimon Schubert 
3495796c8dcSSimon Schubert   if (pid == -1)
3505796c8dcSSimon Schubert     /* Resume all threads.  Traditionally ptrace() only supports
3515796c8dcSSimon Schubert        single-threaded processes, so simply resume the inferior.  */
3525796c8dcSSimon Schubert     pid = ptid_get_pid (inferior_ptid);
3535796c8dcSSimon Schubert 
3545796c8dcSSimon Schubert   if (catch_syscall_enabled () > 0)
3555796c8dcSSimon Schubert     request = PT_SYSCALL;
3565796c8dcSSimon Schubert   else
3575796c8dcSSimon Schubert     request = PT_CONTINUE;
3585796c8dcSSimon Schubert 
3595796c8dcSSimon Schubert   if (step)
3605796c8dcSSimon Schubert     {
3615796c8dcSSimon Schubert       /* If this system does not support PT_STEP, a higher level
3625796c8dcSSimon Schubert          function will have called single_step() to transmute the step
3635796c8dcSSimon Schubert          request into a continue request (by setting breakpoints on
3645796c8dcSSimon Schubert          all possible successor instructions), so we don't have to
3655796c8dcSSimon Schubert          worry about that here.  */
3665796c8dcSSimon Schubert       request = PT_STEP;
3675796c8dcSSimon Schubert     }
3685796c8dcSSimon Schubert 
3695796c8dcSSimon Schubert   /* An address of (PTRACE_TYPE_ARG3)1 tells ptrace to continue from
3705796c8dcSSimon Schubert      where it was.  If GDB wanted it to start some other way, we have
3715796c8dcSSimon Schubert      already written a new program counter value to the child.  */
3725796c8dcSSimon Schubert   errno = 0;
3735796c8dcSSimon Schubert   ptrace (request, pid, (PTRACE_TYPE_ARG3)1, gdb_signal_to_host (signal));
3745796c8dcSSimon Schubert   if (errno != 0)
3755796c8dcSSimon Schubert     perror_with_name (("ptrace"));
3765796c8dcSSimon Schubert }
3775796c8dcSSimon Schubert 
3785796c8dcSSimon Schubert /* Wait for the child specified by PTID to do something.  Return the
3795796c8dcSSimon Schubert    process ID of the child, or MINUS_ONE_PTID in case of error; store
3805796c8dcSSimon Schubert    the status in *OURSTATUS.  */
3815796c8dcSSimon Schubert 
3825796c8dcSSimon Schubert static ptid_t
inf_ptrace_wait(struct target_ops * ops,ptid_t ptid,struct target_waitstatus * ourstatus,int options)3835796c8dcSSimon Schubert inf_ptrace_wait (struct target_ops *ops,
3845796c8dcSSimon Schubert 		 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
3855796c8dcSSimon Schubert {
3865796c8dcSSimon Schubert   pid_t pid;
3875796c8dcSSimon Schubert   int status, save_errno;
3885796c8dcSSimon Schubert 
3895796c8dcSSimon Schubert   do
3905796c8dcSSimon Schubert     {
3915796c8dcSSimon Schubert       set_sigint_trap ();
3925796c8dcSSimon Schubert 
3935796c8dcSSimon Schubert       do
3945796c8dcSSimon Schubert 	{
3955796c8dcSSimon Schubert 	  pid = waitpid (ptid_get_pid (ptid), &status, 0);
3965796c8dcSSimon Schubert 	  save_errno = errno;
3975796c8dcSSimon Schubert 	}
3985796c8dcSSimon Schubert       while (pid == -1 && errno == EINTR);
3995796c8dcSSimon Schubert 
4005796c8dcSSimon Schubert       clear_sigint_trap ();
4015796c8dcSSimon Schubert 
4025796c8dcSSimon Schubert       if (pid == -1)
4035796c8dcSSimon Schubert 	{
4045796c8dcSSimon Schubert 	  fprintf_unfiltered (gdb_stderr,
4055796c8dcSSimon Schubert 			      _("Child process unexpectedly missing: %s.\n"),
4065796c8dcSSimon Schubert 			      safe_strerror (save_errno));
4075796c8dcSSimon Schubert 
4085796c8dcSSimon Schubert 	  /* Claim it exited with unknown signal.  */
4095796c8dcSSimon Schubert 	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
4105796c8dcSSimon Schubert 	  ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
4115796c8dcSSimon Schubert 	  return inferior_ptid;
4125796c8dcSSimon Schubert 	}
4135796c8dcSSimon Schubert 
4145796c8dcSSimon Schubert       /* Ignore terminated detached child processes.  */
4155796c8dcSSimon Schubert       if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
4165796c8dcSSimon Schubert 	pid = -1;
4175796c8dcSSimon Schubert     }
4185796c8dcSSimon Schubert   while (pid == -1);
4195796c8dcSSimon Schubert 
4205796c8dcSSimon Schubert #ifdef PT_GET_PROCESS_STATE
4215796c8dcSSimon Schubert   if (WIFSTOPPED (status))
4225796c8dcSSimon Schubert     {
4235796c8dcSSimon Schubert       ptrace_state_t pe;
4245796c8dcSSimon Schubert       pid_t fpid;
4255796c8dcSSimon Schubert 
4265796c8dcSSimon Schubert       if (ptrace (PT_GET_PROCESS_STATE, pid,
4275796c8dcSSimon Schubert 		  (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
4285796c8dcSSimon Schubert 	perror_with_name (("ptrace"));
4295796c8dcSSimon Schubert 
4305796c8dcSSimon Schubert       switch (pe.pe_report_event)
4315796c8dcSSimon Schubert 	{
4325796c8dcSSimon Schubert 	case PTRACE_FORK:
4335796c8dcSSimon Schubert 	  ourstatus->kind = TARGET_WAITKIND_FORKED;
4345796c8dcSSimon Schubert 	  ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid);
4355796c8dcSSimon Schubert 
4365796c8dcSSimon Schubert 	  /* Make sure the other end of the fork is stopped too.  */
4375796c8dcSSimon Schubert 	  fpid = waitpid (pe.pe_other_pid, &status, 0);
4385796c8dcSSimon Schubert 	  if (fpid == -1)
4395796c8dcSSimon Schubert 	    perror_with_name (("waitpid"));
4405796c8dcSSimon Schubert 
4415796c8dcSSimon Schubert 	  if (ptrace (PT_GET_PROCESS_STATE, fpid,
4425796c8dcSSimon Schubert 		      (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
4435796c8dcSSimon Schubert 	    perror_with_name (("ptrace"));
4445796c8dcSSimon Schubert 
4455796c8dcSSimon Schubert 	  gdb_assert (pe.pe_report_event == PTRACE_FORK);
4465796c8dcSSimon Schubert 	  gdb_assert (pe.pe_other_pid == pid);
4475796c8dcSSimon Schubert 	  if (fpid == ptid_get_pid (inferior_ptid))
4485796c8dcSSimon Schubert 	    {
4495796c8dcSSimon Schubert 	      ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid);
4505796c8dcSSimon Schubert 	      return pid_to_ptid (fpid);
4515796c8dcSSimon Schubert 	    }
4525796c8dcSSimon Schubert 
4535796c8dcSSimon Schubert 	  return pid_to_ptid (pid);
4545796c8dcSSimon Schubert 	}
4555796c8dcSSimon Schubert     }
4565796c8dcSSimon Schubert #endif
4575796c8dcSSimon Schubert 
4585796c8dcSSimon Schubert   store_waitstatus (ourstatus, status);
4595796c8dcSSimon Schubert   return pid_to_ptid (pid);
4605796c8dcSSimon Schubert }
4615796c8dcSSimon Schubert 
4625796c8dcSSimon Schubert /* Attempt a transfer all LEN bytes starting at OFFSET between the
4635796c8dcSSimon Schubert    inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer.
4645796c8dcSSimon Schubert    Return the number of bytes actually transferred.  */
4655796c8dcSSimon Schubert 
4665796c8dcSSimon Schubert static LONGEST
inf_ptrace_xfer_partial(struct target_ops * ops,enum target_object object,const char * annex,gdb_byte * readbuf,const gdb_byte * writebuf,ULONGEST offset,LONGEST len)4675796c8dcSSimon Schubert inf_ptrace_xfer_partial (struct target_ops *ops, enum target_object object,
4685796c8dcSSimon Schubert 			 const char *annex, gdb_byte *readbuf,
4695796c8dcSSimon Schubert 			 const gdb_byte *writebuf,
4705796c8dcSSimon Schubert 			 ULONGEST offset, LONGEST len)
4715796c8dcSSimon Schubert {
4725796c8dcSSimon Schubert   pid_t pid = ptid_get_pid (inferior_ptid);
4735796c8dcSSimon Schubert 
4745796c8dcSSimon Schubert   switch (object)
4755796c8dcSSimon Schubert     {
4765796c8dcSSimon Schubert     case TARGET_OBJECT_MEMORY:
4775796c8dcSSimon Schubert #ifdef PT_IO
4785796c8dcSSimon Schubert       /* OpenBSD 3.1, NetBSD 1.6 and FreeBSD 5.0 have a new PT_IO
4795796c8dcSSimon Schubert 	 request that promises to be much more efficient in reading
4805796c8dcSSimon Schubert 	 and writing data in the traced process's address space.  */
4815796c8dcSSimon Schubert       {
4825796c8dcSSimon Schubert 	struct ptrace_io_desc piod;
4835796c8dcSSimon Schubert 
4845796c8dcSSimon Schubert 	/* NOTE: We assume that there are no distinct address spaces
4855796c8dcSSimon Schubert 	   for instruction and data.  However, on OpenBSD 3.9 and
4865796c8dcSSimon Schubert 	   later, PIOD_WRITE_D doesn't allow changing memory that's
4875796c8dcSSimon Schubert 	   mapped read-only.  Since most code segments will be
4885796c8dcSSimon Schubert 	   read-only, using PIOD_WRITE_D will prevent us from
4895796c8dcSSimon Schubert 	   inserting breakpoints, so we use PIOD_WRITE_I instead.  */
4905796c8dcSSimon Schubert 	piod.piod_op = writebuf ? PIOD_WRITE_I : PIOD_READ_D;
4915796c8dcSSimon Schubert 	piod.piod_addr = writebuf ? (void *) writebuf : readbuf;
4925796c8dcSSimon Schubert 	piod.piod_offs = (void *) (long) offset;
4935796c8dcSSimon Schubert 	piod.piod_len = len;
4945796c8dcSSimon Schubert 
4955796c8dcSSimon Schubert 	errno = 0;
4965796c8dcSSimon Schubert 	if (ptrace (PT_IO, pid, (caddr_t)&piod, 0) == 0)
4975796c8dcSSimon Schubert 	  /* Return the actual number of bytes read or written.  */
4985796c8dcSSimon Schubert 	  return piod.piod_len;
4995796c8dcSSimon Schubert 	/* If the PT_IO request is somehow not supported, fallback on
5005796c8dcSSimon Schubert 	   using PT_WRITE_D/PT_READ_D.  Otherwise we will return zero
5015796c8dcSSimon Schubert 	   to indicate failure.  */
5025796c8dcSSimon Schubert 	if (errno != EINVAL)
5035796c8dcSSimon Schubert 	  return 0;
5045796c8dcSSimon Schubert       }
5055796c8dcSSimon Schubert #endif
5065796c8dcSSimon Schubert       {
5075796c8dcSSimon Schubert 	union
5085796c8dcSSimon Schubert 	{
5095796c8dcSSimon Schubert 	  PTRACE_TYPE_RET word;
5105796c8dcSSimon Schubert 	  gdb_byte byte[sizeof (PTRACE_TYPE_RET)];
5115796c8dcSSimon Schubert 	} buffer;
5125796c8dcSSimon Schubert 	ULONGEST rounded_offset;
5135796c8dcSSimon Schubert 	LONGEST partial_len;
5145796c8dcSSimon Schubert 
5155796c8dcSSimon Schubert 	/* Round the start offset down to the next long word
5165796c8dcSSimon Schubert 	   boundary.  */
5175796c8dcSSimon Schubert 	rounded_offset = offset & -(ULONGEST) sizeof (PTRACE_TYPE_RET);
5185796c8dcSSimon Schubert 
5195796c8dcSSimon Schubert 	/* Since ptrace will transfer a single word starting at that
5205796c8dcSSimon Schubert 	   rounded_offset the partial_len needs to be adjusted down to
5215796c8dcSSimon Schubert 	   that (remember this function only does a single transfer).
5225796c8dcSSimon Schubert 	   Should the required length be even less, adjust it down
5235796c8dcSSimon Schubert 	   again.  */
5245796c8dcSSimon Schubert 	partial_len = (rounded_offset + sizeof (PTRACE_TYPE_RET)) - offset;
5255796c8dcSSimon Schubert 	if (partial_len > len)
5265796c8dcSSimon Schubert 	  partial_len = len;
5275796c8dcSSimon Schubert 
5285796c8dcSSimon Schubert 	if (writebuf)
5295796c8dcSSimon Schubert 	  {
5305796c8dcSSimon Schubert 	    /* If OFFSET:PARTIAL_LEN is smaller than
5315796c8dcSSimon Schubert 	       ROUNDED_OFFSET:WORDSIZE then a read/modify write will
5325796c8dcSSimon Schubert 	       be needed.  Read in the entire word.  */
5335796c8dcSSimon Schubert 	    if (rounded_offset < offset
5345796c8dcSSimon Schubert 		|| (offset + partial_len
5355796c8dcSSimon Schubert 		    < rounded_offset + sizeof (PTRACE_TYPE_RET)))
5365796c8dcSSimon Schubert 	      /* Need part of initial word -- fetch it.  */
5375796c8dcSSimon Schubert 	      buffer.word = ptrace (PT_READ_I, pid,
5385796c8dcSSimon Schubert 				    (PTRACE_TYPE_ARG3)(uintptr_t)
5395796c8dcSSimon Schubert 				    rounded_offset, 0);
5405796c8dcSSimon Schubert 
5415796c8dcSSimon Schubert 	    /* Copy data to be written over corresponding part of
5425796c8dcSSimon Schubert 	       buffer.  */
5435796c8dcSSimon Schubert 	    memcpy (buffer.byte + (offset - rounded_offset),
5445796c8dcSSimon Schubert 		    writebuf, partial_len);
5455796c8dcSSimon Schubert 
5465796c8dcSSimon Schubert 	    errno = 0;
5475796c8dcSSimon Schubert 	    ptrace (PT_WRITE_D, pid,
5485796c8dcSSimon Schubert 		    (PTRACE_TYPE_ARG3)(uintptr_t)rounded_offset,
5495796c8dcSSimon Schubert 		    buffer.word);
5505796c8dcSSimon Schubert 	    if (errno)
5515796c8dcSSimon Schubert 	      {
5525796c8dcSSimon Schubert 		/* Using the appropriate one (I or D) is necessary for
5535796c8dcSSimon Schubert 		   Gould NP1, at least.  */
5545796c8dcSSimon Schubert 		errno = 0;
5555796c8dcSSimon Schubert 		ptrace (PT_WRITE_I, pid,
5565796c8dcSSimon Schubert 			(PTRACE_TYPE_ARG3)(uintptr_t)rounded_offset,
5575796c8dcSSimon Schubert 			buffer.word);
5585796c8dcSSimon Schubert 		if (errno)
5595796c8dcSSimon Schubert 		  return 0;
5605796c8dcSSimon Schubert 	      }
5615796c8dcSSimon Schubert 	  }
5625796c8dcSSimon Schubert 
5635796c8dcSSimon Schubert 	if (readbuf)
5645796c8dcSSimon Schubert 	  {
5655796c8dcSSimon Schubert 	    errno = 0;
5665796c8dcSSimon Schubert 	    buffer.word = ptrace (PT_READ_I, pid,
5675796c8dcSSimon Schubert 				  (PTRACE_TYPE_ARG3)(uintptr_t)rounded_offset,
5685796c8dcSSimon Schubert 				  0);
5695796c8dcSSimon Schubert 	    if (errno)
5705796c8dcSSimon Schubert 	      return 0;
5715796c8dcSSimon Schubert 	    /* Copy appropriate bytes out of the buffer.  */
5725796c8dcSSimon Schubert 	    memcpy (readbuf, buffer.byte + (offset - rounded_offset),
5735796c8dcSSimon Schubert 		    partial_len);
5745796c8dcSSimon Schubert 	  }
5755796c8dcSSimon Schubert 
5765796c8dcSSimon Schubert 	return partial_len;
5775796c8dcSSimon Schubert       }
5785796c8dcSSimon Schubert 
5795796c8dcSSimon Schubert     case TARGET_OBJECT_UNWIND_TABLE:
5805796c8dcSSimon Schubert       return -1;
5815796c8dcSSimon Schubert 
5825796c8dcSSimon Schubert     case TARGET_OBJECT_AUXV:
5835796c8dcSSimon Schubert #if defined (PT_IO) && defined (PIOD_READ_AUXV)
5845796c8dcSSimon Schubert       /* OpenBSD 4.5 has a new PIOD_READ_AUXV operation for the PT_IO
5855796c8dcSSimon Schubert 	 request that allows us to read the auxilliary vector.  Other
5865796c8dcSSimon Schubert 	 BSD's may follow if they feel the need to support PIE.  */
5875796c8dcSSimon Schubert       {
5885796c8dcSSimon Schubert 	struct ptrace_io_desc piod;
5895796c8dcSSimon Schubert 
5905796c8dcSSimon Schubert 	if (writebuf)
5915796c8dcSSimon Schubert 	  return -1;
5925796c8dcSSimon Schubert 	piod.piod_op = PIOD_READ_AUXV;
5935796c8dcSSimon Schubert 	piod.piod_addr = readbuf;
5945796c8dcSSimon Schubert 	piod.piod_offs = (void *) (long) offset;
5955796c8dcSSimon Schubert 	piod.piod_len = len;
5965796c8dcSSimon Schubert 
5975796c8dcSSimon Schubert 	errno = 0;
5985796c8dcSSimon Schubert 	if (ptrace (PT_IO, pid, (caddr_t)&piod, 0) == 0)
5995796c8dcSSimon Schubert 	  /* Return the actual number of bytes read or written.  */
6005796c8dcSSimon Schubert 	  return piod.piod_len;
6015796c8dcSSimon Schubert       }
6025796c8dcSSimon Schubert #endif
6035796c8dcSSimon Schubert       return -1;
6045796c8dcSSimon Schubert 
6055796c8dcSSimon Schubert     case TARGET_OBJECT_WCOOKIE:
6065796c8dcSSimon Schubert       return -1;
6075796c8dcSSimon Schubert 
6085796c8dcSSimon Schubert     default:
6095796c8dcSSimon Schubert       return -1;
6105796c8dcSSimon Schubert     }
6115796c8dcSSimon Schubert }
6125796c8dcSSimon Schubert 
6135796c8dcSSimon Schubert /* Return non-zero if the thread specified by PTID is alive.  */
6145796c8dcSSimon Schubert 
6155796c8dcSSimon Schubert static int
inf_ptrace_thread_alive(struct target_ops * ops,ptid_t ptid)6165796c8dcSSimon Schubert inf_ptrace_thread_alive (struct target_ops *ops, ptid_t ptid)
6175796c8dcSSimon Schubert {
6185796c8dcSSimon Schubert   /* ??? Is kill the right way to do this?  */
6195796c8dcSSimon Schubert   return (kill (ptid_get_pid (ptid), 0) != -1);
6205796c8dcSSimon Schubert }
6215796c8dcSSimon Schubert 
6225796c8dcSSimon Schubert /* Print status information about what we're accessing.  */
6235796c8dcSSimon Schubert 
6245796c8dcSSimon Schubert static void
inf_ptrace_files_info(struct target_ops * ignore)6255796c8dcSSimon Schubert inf_ptrace_files_info (struct target_ops *ignore)
6265796c8dcSSimon Schubert {
6275796c8dcSSimon Schubert   struct inferior *inf = current_inferior ();
6285796c8dcSSimon Schubert 
6295796c8dcSSimon Schubert   printf_filtered (_("\tUsing the running image of %s %s.\n"),
6305796c8dcSSimon Schubert 		   inf->attach_flag ? "attached" : "child",
6315796c8dcSSimon Schubert 		   target_pid_to_str (inferior_ptid));
6325796c8dcSSimon Schubert }
6335796c8dcSSimon Schubert 
6345796c8dcSSimon Schubert static char *
inf_ptrace_pid_to_str(struct target_ops * ops,ptid_t ptid)6355796c8dcSSimon Schubert inf_ptrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
6365796c8dcSSimon Schubert {
6375796c8dcSSimon Schubert   return normal_pid_to_str (ptid);
6385796c8dcSSimon Schubert }
6395796c8dcSSimon Schubert 
6405796c8dcSSimon Schubert #if defined (PT_IO) && defined (PIOD_READ_AUXV)
6415796c8dcSSimon Schubert 
6425796c8dcSSimon Schubert /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
6435796c8dcSSimon Schubert    Return 0 if *READPTR is already at the end of the buffer.
6445796c8dcSSimon Schubert    Return -1 if there is insufficient buffer for a whole entry.
6455796c8dcSSimon Schubert    Return 1 if an entry was read into *TYPEP and *VALP.  */
6465796c8dcSSimon Schubert 
6475796c8dcSSimon Schubert static int
inf_ptrace_auxv_parse(struct target_ops * ops,gdb_byte ** readptr,gdb_byte * endptr,CORE_ADDR * typep,CORE_ADDR * valp)6485796c8dcSSimon Schubert inf_ptrace_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
6495796c8dcSSimon Schubert 		       gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
6505796c8dcSSimon Schubert {
6515796c8dcSSimon Schubert   struct type *int_type = builtin_type (target_gdbarch ())->builtin_int;
6525796c8dcSSimon Schubert   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
6535796c8dcSSimon Schubert   const int sizeof_auxv_type = TYPE_LENGTH (int_type);
6545796c8dcSSimon Schubert   const int sizeof_auxv_val = TYPE_LENGTH (ptr_type);
6555796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
6565796c8dcSSimon Schubert   gdb_byte *ptr = *readptr;
6575796c8dcSSimon Schubert 
6585796c8dcSSimon Schubert   if (endptr == ptr)
6595796c8dcSSimon Schubert     return 0;
6605796c8dcSSimon Schubert 
6615796c8dcSSimon Schubert   if (endptr - ptr < 2 * sizeof_auxv_val)
6625796c8dcSSimon Schubert     return -1;
6635796c8dcSSimon Schubert 
6645796c8dcSSimon Schubert   *typep = extract_unsigned_integer (ptr, sizeof_auxv_type, byte_order);
6655796c8dcSSimon Schubert   ptr += sizeof_auxv_val;	/* Alignment.  */
6665796c8dcSSimon Schubert   *valp = extract_unsigned_integer (ptr, sizeof_auxv_val, byte_order);
6675796c8dcSSimon Schubert   ptr += sizeof_auxv_val;
6685796c8dcSSimon Schubert 
6695796c8dcSSimon Schubert   *readptr = ptr;
6705796c8dcSSimon Schubert   return 1;
6715796c8dcSSimon Schubert }
6725796c8dcSSimon Schubert 
6735796c8dcSSimon Schubert #endif
6745796c8dcSSimon Schubert 
6755796c8dcSSimon Schubert /* Create a prototype ptrace target.  The client can override it with
6765796c8dcSSimon Schubert    local methods.  */
6775796c8dcSSimon Schubert 
6785796c8dcSSimon Schubert struct target_ops *
inf_ptrace_target(void)6795796c8dcSSimon Schubert inf_ptrace_target (void)
6805796c8dcSSimon Schubert {
6815796c8dcSSimon Schubert   struct target_ops *t = inf_child_target ();
6825796c8dcSSimon Schubert 
6835796c8dcSSimon Schubert   t->to_attach = inf_ptrace_attach;
6845796c8dcSSimon Schubert   t->to_detach = inf_ptrace_detach;
6855796c8dcSSimon Schubert   t->to_resume = inf_ptrace_resume;
6865796c8dcSSimon Schubert   t->to_wait = inf_ptrace_wait;
6875796c8dcSSimon Schubert   t->to_files_info = inf_ptrace_files_info;
6885796c8dcSSimon Schubert   t->to_kill = inf_ptrace_kill;
6895796c8dcSSimon Schubert   t->to_create_inferior = inf_ptrace_create_inferior;
6905796c8dcSSimon Schubert #ifdef PT_GET_PROCESS_STATE
6915796c8dcSSimon Schubert   t->to_follow_fork = inf_ptrace_follow_fork;
6925796c8dcSSimon Schubert   t->to_post_startup_inferior = inf_ptrace_post_startup_inferior;
6935796c8dcSSimon Schubert   t->to_post_attach = inf_ptrace_post_attach;
6945796c8dcSSimon Schubert #endif
6955796c8dcSSimon Schubert   t->to_mourn_inferior = inf_ptrace_mourn_inferior;
6965796c8dcSSimon Schubert   t->to_thread_alive = inf_ptrace_thread_alive;
6975796c8dcSSimon Schubert   t->to_pid_to_str = inf_ptrace_pid_to_str;
6985796c8dcSSimon Schubert   t->to_stop = inf_ptrace_stop;
6995796c8dcSSimon Schubert   t->to_xfer_partial = inf_ptrace_xfer_partial;
7005796c8dcSSimon Schubert #if defined (PT_IO) && defined (PIOD_READ_AUXV)
7015796c8dcSSimon Schubert   t->to_auxv_parse = inf_ptrace_auxv_parse;
7025796c8dcSSimon Schubert #endif
7035796c8dcSSimon Schubert 
7045796c8dcSSimon Schubert   return t;
7055796c8dcSSimon Schubert }
7065796c8dcSSimon Schubert 
7075796c8dcSSimon Schubert 
7085796c8dcSSimon Schubert /* Pointer to a function that returns the offset within the user area
7095796c8dcSSimon Schubert    where a particular register is stored.  */
7105796c8dcSSimon Schubert static CORE_ADDR (*inf_ptrace_register_u_offset)(struct gdbarch *, int, int);
7115796c8dcSSimon Schubert 
7125796c8dcSSimon Schubert /* Fetch register REGNUM from the inferior.  */
7135796c8dcSSimon Schubert 
7145796c8dcSSimon Schubert static void
inf_ptrace_fetch_register(struct regcache * regcache,int regnum)7155796c8dcSSimon Schubert inf_ptrace_fetch_register (struct regcache *regcache, int regnum)
7165796c8dcSSimon Schubert {
7175796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_regcache_arch (regcache);
7185796c8dcSSimon Schubert   CORE_ADDR addr;
7195796c8dcSSimon Schubert   size_t size;
7205796c8dcSSimon Schubert   PTRACE_TYPE_RET *buf;
7215796c8dcSSimon Schubert   int pid, i;
7225796c8dcSSimon Schubert 
7235796c8dcSSimon Schubert   /* This isn't really an address, but ptrace thinks of it as one.  */
7245796c8dcSSimon Schubert   addr = inf_ptrace_register_u_offset (gdbarch, regnum, 0);
7255796c8dcSSimon Schubert   if (addr == (CORE_ADDR)-1
7265796c8dcSSimon Schubert       || gdbarch_cannot_fetch_register (gdbarch, regnum))
7275796c8dcSSimon Schubert     {
7285796c8dcSSimon Schubert       regcache_raw_supply (regcache, regnum, NULL);
7295796c8dcSSimon Schubert       return;
7305796c8dcSSimon Schubert     }
7315796c8dcSSimon Schubert 
7325796c8dcSSimon Schubert   /* Cater for systems like GNU/Linux, that implement threads as
7335796c8dcSSimon Schubert      separate processes.  */
7345796c8dcSSimon Schubert   pid = ptid_get_lwp (inferior_ptid);
7355796c8dcSSimon Schubert   if (pid == 0)
7365796c8dcSSimon Schubert     pid = ptid_get_pid (inferior_ptid);
7375796c8dcSSimon Schubert 
7385796c8dcSSimon Schubert   size = register_size (gdbarch, regnum);
7395796c8dcSSimon Schubert   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
7405796c8dcSSimon Schubert   buf = alloca (size);
7415796c8dcSSimon Schubert 
7425796c8dcSSimon Schubert   /* Read the register contents from the inferior a chunk at a time.  */
7435796c8dcSSimon Schubert   for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
7445796c8dcSSimon Schubert     {
7455796c8dcSSimon Schubert       errno = 0;
7465796c8dcSSimon Schubert       buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, 0);
7475796c8dcSSimon Schubert       if (errno != 0)
7485796c8dcSSimon Schubert 	error (_("Couldn't read register %s (#%d): %s."),
7495796c8dcSSimon Schubert 	       gdbarch_register_name (gdbarch, regnum),
7505796c8dcSSimon Schubert 	       regnum, safe_strerror (errno));
7515796c8dcSSimon Schubert 
7525796c8dcSSimon Schubert       addr += sizeof (PTRACE_TYPE_RET);
7535796c8dcSSimon Schubert     }
7545796c8dcSSimon Schubert   regcache_raw_supply (regcache, regnum, buf);
7555796c8dcSSimon Schubert }
7565796c8dcSSimon Schubert 
7575796c8dcSSimon Schubert /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
7585796c8dcSSimon Schubert    for all registers.  */
7595796c8dcSSimon Schubert 
7605796c8dcSSimon Schubert static void
inf_ptrace_fetch_registers(struct target_ops * ops,struct regcache * regcache,int regnum)7615796c8dcSSimon Schubert inf_ptrace_fetch_registers (struct target_ops *ops,
7625796c8dcSSimon Schubert 			    struct regcache *regcache, int regnum)
7635796c8dcSSimon Schubert {
7645796c8dcSSimon Schubert   if (regnum == -1)
7655796c8dcSSimon Schubert     for (regnum = 0;
7665796c8dcSSimon Schubert 	 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
7675796c8dcSSimon Schubert 	 regnum++)
7685796c8dcSSimon Schubert       inf_ptrace_fetch_register (regcache, regnum);
7695796c8dcSSimon Schubert   else
7705796c8dcSSimon Schubert     inf_ptrace_fetch_register (regcache, regnum);
7715796c8dcSSimon Schubert }
7725796c8dcSSimon Schubert 
7735796c8dcSSimon Schubert /* Store register REGNUM into the inferior.  */
7745796c8dcSSimon Schubert 
7755796c8dcSSimon Schubert static void
inf_ptrace_store_register(const struct regcache * regcache,int regnum)7765796c8dcSSimon Schubert inf_ptrace_store_register (const struct regcache *regcache, int regnum)
7775796c8dcSSimon Schubert {
7785796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_regcache_arch (regcache);
7795796c8dcSSimon Schubert   CORE_ADDR addr;
7805796c8dcSSimon Schubert   size_t size;
7815796c8dcSSimon Schubert   PTRACE_TYPE_RET *buf;
7825796c8dcSSimon Schubert   int pid, i;
7835796c8dcSSimon Schubert 
7845796c8dcSSimon Schubert   /* This isn't really an address, but ptrace thinks of it as one.  */
7855796c8dcSSimon Schubert   addr = inf_ptrace_register_u_offset (gdbarch, regnum, 1);
7865796c8dcSSimon Schubert   if (addr == (CORE_ADDR)-1
7875796c8dcSSimon Schubert       || gdbarch_cannot_store_register (gdbarch, regnum))
7885796c8dcSSimon Schubert     return;
7895796c8dcSSimon Schubert 
7905796c8dcSSimon Schubert   /* Cater for systems like GNU/Linux, that implement threads as
791      separate processes.  */
792   pid = ptid_get_lwp (inferior_ptid);
793   if (pid == 0)
794     pid = ptid_get_pid (inferior_ptid);
795 
796   size = register_size (gdbarch, regnum);
797   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
798   buf = alloca (size);
799 
800   /* Write the register contents into the inferior a chunk at a time.  */
801   regcache_raw_collect (regcache, regnum, buf);
802   for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
803     {
804       errno = 0;
805       ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, buf[i]);
806       if (errno != 0)
807 	error (_("Couldn't write register %s (#%d): %s."),
808 	       gdbarch_register_name (gdbarch, regnum),
809 	       regnum, safe_strerror (errno));
810 
811       addr += sizeof (PTRACE_TYPE_RET);
812     }
813 }
814 
815 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
816    this for all registers.  */
817 
818 static void
inf_ptrace_store_registers(struct target_ops * ops,struct regcache * regcache,int regnum)819 inf_ptrace_store_registers (struct target_ops *ops,
820 			    struct regcache *regcache, int regnum)
821 {
822   if (regnum == -1)
823     for (regnum = 0;
824 	 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
825 	 regnum++)
826       inf_ptrace_store_register (regcache, regnum);
827   else
828     inf_ptrace_store_register (regcache, regnum);
829 }
830 
831 /* Create a "traditional" ptrace target.  REGISTER_U_OFFSET should be
832    a function returning the offset within the user area where a
833    particular register is stored.  */
834 
835 struct target_ops *
inf_ptrace_trad_target(CORE_ADDR (* register_u_offset)(struct gdbarch *,int,int))836 inf_ptrace_trad_target (CORE_ADDR (*register_u_offset)
837 					(struct gdbarch *, int, int))
838 {
839   struct target_ops *t = inf_ptrace_target();
840 
841   gdb_assert (register_u_offset);
842   inf_ptrace_register_u_offset = register_u_offset;
843   t->to_fetch_registers = inf_ptrace_fetch_registers;
844   t->to_store_registers = inf_ptrace_store_registers;
845 
846   return t;
847 }
848