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