119370Spst/* Target-vector operations for controlling Unix child processes, for GDB.
2130803Smarcel
3130803Smarcel   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
4130803Smarcel   2000, 2002, 2003, 2004 Free Software Foundation, Inc.
5130803Smarcel
619370Spst   Contributed by Cygnus Support.
719370Spst
898944Sobrien   ## Contains temporary hacks..
946283Sdfr
1098944Sobrien   This file is part of GDB.
1119370Spst
1298944Sobrien   This program is free software; you can redistribute it and/or modify
1398944Sobrien   it under the terms of the GNU General Public License as published by
1498944Sobrien   the Free Software Foundation; either version 2 of the License, or
1598944Sobrien   (at your option) any later version.
1619370Spst
1798944Sobrien   This program is distributed in the hope that it will be useful,
1898944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1998944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2098944Sobrien   GNU General Public License for more details.
2119370Spst
2298944Sobrien   You should have received a copy of the GNU General Public License
2398944Sobrien   along with this program; if not, write to the Free Software
2498944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2598944Sobrien   Boston, MA 02111-1307, USA.  */
2619370Spst
2719370Spst#include "defs.h"
2898944Sobrien#include "frame.h"		/* required by inferior.h */
2919370Spst#include "inferior.h"
3019370Spst#include "target.h"
3119370Spst#include "gdbcore.h"
3219370Spst#include "command.h"
3346283Sdfr#include "gdb_stat.h"
3419370Spst#include <signal.h>
3519370Spst#include <sys/types.h>
3619370Spst#include <fcntl.h>
3719370Spst
3898944Sobrien#include "gdb_wait.h"
39130803Smarcel#include "inflow.h"
4046283Sdfr
4198944Sobrienextern struct symtab_and_line *child_enable_exception_callback (enum
4298944Sobrien								exception_event_kind,
4398944Sobrien								int);
4446283Sdfr
4598944Sobrienextern struct exception_event_record
4698944Sobrien  *child_get_current_exception_event (void);
4746283Sdfr
4898944Sobrienextern void _initialize_inftarg (void);
4946283Sdfr
5098944Sobrienstatic void child_prepare_to_store (void);
5146283Sdfr
5219370Spst#ifndef CHILD_WAIT
5398944Sobrienstatic ptid_t child_wait (ptid_t, struct target_waitstatus *);
5419370Spst#endif /* CHILD_WAIT */
5519370Spst
5646283Sdfr#if !defined(CHILD_POST_WAIT)
5798944Sobrienvoid child_post_wait (ptid_t, int);
5846283Sdfr#endif
5946283Sdfr
6098944Sobrienstatic void child_open (char *, int);
6119370Spst
6298944Sobrienstatic void child_files_info (struct target_ops *);
6319370Spst
6498944Sobrienstatic void child_detach (char *, int);
6519370Spst
6698944Sobrienstatic void child_attach (char *, int);
6719370Spst
6846283Sdfr#if !defined(CHILD_POST_ATTACH)
6998944Sobrienextern void child_post_attach (int);
7046283Sdfr#endif
7146283Sdfr
7298944Sobrienstatic void ptrace_me (void);
7319370Spst
7498944Sobrienstatic void ptrace_him (int);
7519370Spst
7698944Sobrienstatic void child_create_inferior (char *, char *, char **);
7719370Spst
7898944Sobrienstatic void child_mourn_inferior (void);
7919370Spst
8098944Sobrienstatic int child_can_run (void);
8119370Spst
8298944Sobrienstatic void child_stop (void);
8319370Spst
8446283Sdfr#ifndef CHILD_THREAD_ALIVE
8598944Sobrienint child_thread_alive (ptid_t);
8646283Sdfr#endif
8746283Sdfr
8898944Sobrienstatic void init_child_ops (void);
8946283Sdfr
9019370Spstextern char **environ;
9119370Spst
9246283Sdfrstruct target_ops child_ops;
9319370Spst
9446283Sdfrint child_suppress_run = 0;	/* Non-zero if inftarg should pretend not to
9546283Sdfr				   be a runnable target.  Used by targets
9646283Sdfr				   that can sit atop inftarg, such as HPUX
9746283Sdfr				   thread support.  */
9819370Spst
9919370Spst#ifndef CHILD_WAIT
10019370Spst
10119370Spst/* Wait for child to do something.  Return pid of child, or -1 in case
10219370Spst   of error; store status through argument pointer OURSTATUS.  */
10319370Spst
10498944Sobrienstatic ptid_t
10598944Sobrienchild_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
10619370Spst{
10719370Spst  int save_errno;
10819370Spst  int status;
10998944Sobrien  char *execd_pathname = NULL;
11098944Sobrien  int exit_status;
11198944Sobrien  int related_pid;
11298944Sobrien  int syscall_id;
11398944Sobrien  enum target_waitkind kind;
11498944Sobrien  int pid;
11519370Spst
11698944Sobrien  do
11798944Sobrien    {
11898944Sobrien      set_sigint_trap ();	/* Causes SIGINT to be passed on to the
11998944Sobrien				   attached process. */
12098944Sobrien      set_sigio_trap ();
12119370Spst
12298944Sobrien      pid = ptrace_wait (inferior_ptid, &status);
12346283Sdfr
12498944Sobrien      save_errno = errno;
12519370Spst
12698944Sobrien      clear_sigio_trap ();
12719370Spst
12898944Sobrien      clear_sigint_trap ();
12919370Spst
13098944Sobrien      if (pid == -1)
13198944Sobrien	{
13298944Sobrien	  if (save_errno == EINTR)
13398944Sobrien	    continue;
13446283Sdfr
13598944Sobrien	  fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
13698944Sobrien			      safe_strerror (save_errno));
13746283Sdfr
13898944Sobrien	  /* Claim it exited with unknown signal.  */
13998944Sobrien	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
14098944Sobrien	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
14198944Sobrien	  return pid_to_ptid (-1);
14298944Sobrien	}
14346283Sdfr
14498944Sobrien      /* Did it exit?
14598944Sobrien       */
14698944Sobrien      if (target_has_exited (pid, status, &exit_status))
14798944Sobrien	{
14898944Sobrien	  /* ??rehrauer: For now, ignore this. */
14998944Sobrien	  continue;
15098944Sobrien	}
15146283Sdfr
15298944Sobrien      if (!target_thread_alive (pid_to_ptid (pid)))
15398944Sobrien	{
15498944Sobrien	  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
15598944Sobrien	  return pid_to_ptid (pid);
15698944Sobrien	}
157130803Smarcel      } while (pid != PIDGET (inferior_ptid)); /* Some other child died or stopped */
15846283Sdfr
15919370Spst  store_waitstatus (ourstatus, status);
16098944Sobrien  return pid_to_ptid (pid);
16119370Spst}
16219370Spst#endif /* CHILD_WAIT */
16319370Spst
16446283Sdfr#if !defined(CHILD_POST_WAIT)
16546283Sdfrvoid
16698944Sobrienchild_post_wait (ptid_t ptid, int wait_status)
16746283Sdfr{
16846283Sdfr  /* This version of Unix doesn't require a meaningful "post wait"
16946283Sdfr     operation.
17098944Sobrien   */
17146283Sdfr}
17246283Sdfr#endif
17346283Sdfr
17498944Sobrien
17519370Spst#ifndef CHILD_THREAD_ALIVE
17619370Spst
17719370Spst/* Check to see if the given thread is alive.
17819370Spst
17919370Spst   FIXME: Is kill() ever the right way to do this?  I doubt it, but
18019370Spst   for now we're going to try and be compatable with the old thread
18119370Spst   code.  */
18246283Sdfrint
18398944Sobrienchild_thread_alive (ptid_t ptid)
18419370Spst{
18598944Sobrien  pid_t pid = PIDGET (ptid);
18698944Sobrien
18719370Spst  return (kill (pid, 0) != -1);
18819370Spst}
18919370Spst
19019370Spst#endif
19119370Spst
192130803Smarcel/* Attach to process PID, then initialize for debugging it.  */
193130803Smarcel
19419370Spststatic void
195130803Smarcelchild_attach (char *args, int from_tty)
19619370Spst{
19719370Spst  if (!args)
19819370Spst    error_no_arg ("process-id to attach");
19919370Spst
20019370Spst#ifndef ATTACH_DETACH
20119370Spst  error ("Can't attach to a process on this machine.");
20219370Spst#else
20319370Spst  {
20419370Spst    char *exec_file;
20519370Spst    int pid;
20646283Sdfr    char *dummy;
20719370Spst
20846283Sdfr    dummy = args;
20946283Sdfr    pid = strtol (args, &dummy, 0);
21046283Sdfr    /* Some targets don't set errno on errors, grrr! */
21146283Sdfr    if ((pid == 0) && (args == dummy))
21246283Sdfr      error ("Illegal process-id: %s\n", args);
21319370Spst
21498944Sobrien    if (pid == getpid ())	/* Trying to masturbate? */
21519370Spst      error ("I refuse to debug myself!");
21619370Spst
21719370Spst    if (from_tty)
21819370Spst      {
21919370Spst	exec_file = (char *) get_exec_file (0);
22019370Spst
221130803Smarcel	if (exec_file)
22246283Sdfr	  printf_unfiltered ("Attaching to program: %s, %s\n", exec_file,
22398944Sobrien			     target_pid_to_str (pid_to_ptid (pid)));
22498944Sobrien	else
225130803Smarcel	  printf_unfiltered ("Attaching to %s\n",
22698944Sobrien	                     target_pid_to_str (pid_to_ptid (pid)));
22719370Spst
22819370Spst	gdb_flush (gdb_stdout);
22919370Spst      }
23019370Spst
231130803Smarcel    attach (pid);
23246283Sdfr
23398944Sobrien    inferior_ptid = pid_to_ptid (pid);
23419370Spst    push_target (&child_ops);
23519370Spst  }
23698944Sobrien#endif /* ATTACH_DETACH */
23719370Spst}
23819370Spst
23946283Sdfr#if !defined(CHILD_POST_ATTACH)
24046283Sdfrvoid
24198944Sobrienchild_post_attach (int pid)
24246283Sdfr{
24346283Sdfr  /* This version of Unix doesn't require a meaningful "post attach"
24446283Sdfr     operation by a debugger.  */
24546283Sdfr}
24646283Sdfr#endif
24746283Sdfr
248130803Smarcel/* Take a program previously attached to and detaches it.
249130803Smarcel   The program resumes execution and will no longer stop
250130803Smarcel   on signals, etc.  We'd better not have left any breakpoints
251130803Smarcel   in the program or it'll die when it hits one.  For this
252130803Smarcel   to work, it may be necessary for the process to have been
253130803Smarcel   previously attached.  It *might* work if the program was
254130803Smarcel   started via the normal ptrace (PTRACE_TRACEME).  */
25546283Sdfr
25646283Sdfrstatic void
257130803Smarcelchild_detach (char *args, int from_tty)
25846283Sdfr{
25919370Spst#ifdef ATTACH_DETACH
26019370Spst  {
26119370Spst    int siggnal = 0;
262130803Smarcel    int pid = PIDGET (inferior_ptid);
26319370Spst
26419370Spst    if (from_tty)
26519370Spst      {
26619370Spst	char *exec_file = get_exec_file (0);
26719370Spst	if (exec_file == 0)
26819370Spst	  exec_file = "";
269130803Smarcel	printf_unfiltered ("Detaching from program: %s, %s\n", exec_file,
270130803Smarcel			   target_pid_to_str (pid_to_ptid (pid)));
27119370Spst	gdb_flush (gdb_stdout);
27219370Spst      }
27319370Spst    if (args)
27419370Spst      siggnal = atoi (args);
27519370Spst
276130803Smarcel    detach (siggnal);
277130803Smarcel
278130803Smarcel    inferior_ptid = null_ptid;
279130803Smarcel    unpush_target (&child_ops);
28019370Spst  }
28119370Spst#else
28219370Spst  error ("This version of Unix does not support detaching a process.");
28319370Spst#endif
28419370Spst}
28519370Spst
28619370Spst/* Get ready to modify the registers array.  On machines which store
28719370Spst   individual registers, this doesn't need to do anything.  On machines
28819370Spst   which store all the registers in one fell swoop, this makes sure
28919370Spst   that registers contains all the registers from the program being
29019370Spst   debugged.  */
29119370Spst
29219370Spststatic void
29398944Sobrienchild_prepare_to_store (void)
29419370Spst{
29519370Spst#ifdef CHILD_PREPARE_TO_STORE
29619370Spst  CHILD_PREPARE_TO_STORE ();
29719370Spst#endif
29819370Spst}
29919370Spst
30019370Spst/* Print status information about what we're accessing.  */
30119370Spst
30219370Spststatic void
30398944Sobrienchild_files_info (struct target_ops *ignore)
30419370Spst{
30519370Spst  printf_unfiltered ("\tUsing the running image of %s %s.\n",
30698944Sobrien      attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
30719370Spst}
30819370Spst
30919370Spststatic void
31098944Sobrienchild_open (char *arg, int from_tty)
31119370Spst{
31219370Spst  error ("Use the \"run\" command to start a Unix child process.");
31319370Spst}
31419370Spst
31519370Spst/* Stub function which causes the inferior that runs it, to be ptrace-able
31619370Spst   by its parent process.  */
31719370Spst
31819370Spststatic void
31998944Sobrienptrace_me (void)
32019370Spst{
32119370Spst  /* "Trace me, Dr. Memory!" */
32219370Spst  call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
32319370Spst}
32419370Spst
32519370Spst/* Stub function which causes the GDB that runs it, to start ptrace-ing
32619370Spst   the child process.  */
32719370Spst
32898944Sobrienstatic void
32998944Sobrienptrace_him (int pid)
33019370Spst{
33119370Spst  push_target (&child_ops);
33219370Spst
33346283Sdfr  /* On some targets, there must be some explicit synchronization
33446283Sdfr     between the parent and child processes after the debugger
33546283Sdfr     forks, and before the child execs the debuggee program.  This
33646283Sdfr     call basically gives permission for the child to exec.
33798944Sobrien   */
33846283Sdfr
33946283Sdfr  target_acknowledge_created_inferior (pid);
34046283Sdfr
34146283Sdfr  /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h,
34246283Sdfr   * and will be 1 or 2 depending on whether we're starting
34346283Sdfr   * without or with a shell.
34446283Sdfr   */
34519370Spst  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
34646283Sdfr
34746283Sdfr  /* On some targets, there must be some explicit actions taken after
34846283Sdfr     the inferior has been started up.
34998944Sobrien   */
35098944Sobrien  target_post_startup_inferior (pid_to_ptid (pid));
35119370Spst}
35219370Spst
35398944Sobrien/* Start an inferior Unix child process and sets inferior_ptid to its pid.
35419370Spst   EXEC_FILE is the file to run.
35519370Spst   ALLARGS is a string containing the arguments to the program.
35619370Spst   ENV is the environment vector to pass.  Errors reported with error().  */
35719370Spst
35819370Spststatic void
35998944Sobrienchild_create_inferior (char *exec_file, char *allargs, char **env)
36019370Spst{
36146283Sdfr#ifdef HPUXHPPA
36246283Sdfr  fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, pre_fork_inferior, NULL);
36346283Sdfr#else
36498944Sobrien  fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, NULL, NULL);
36546283Sdfr#endif
36619370Spst  /* We are at the first instruction we care about.  */
36719370Spst  /* Pedal to the metal... */
36819370Spst  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
36919370Spst}
37019370Spst
37146283Sdfr#if !defined(CHILD_POST_STARTUP_INFERIOR)
37246283Sdfrvoid
37398944Sobrienchild_post_startup_inferior (ptid_t ptid)
37446283Sdfr{
37546283Sdfr  /* This version of Unix doesn't require a meaningful "post startup inferior"
37646283Sdfr     operation by a debugger.
37798944Sobrien   */
37846283Sdfr}
37946283Sdfr#endif
38046283Sdfr
38146283Sdfr#if !defined(CHILD_ACKNOWLEDGE_CREATED_INFERIOR)
38246283Sdfrvoid
38398944Sobrienchild_acknowledge_created_inferior (int pid)
38446283Sdfr{
38546283Sdfr  /* This version of Unix doesn't require a meaningful "acknowledge created inferior"
38646283Sdfr     operation by a debugger.
38798944Sobrien   */
38846283Sdfr}
38946283Sdfr#endif
39046283Sdfr
39146283Sdfr
39246283Sdfr#if !defined(CHILD_INSERT_FORK_CATCHPOINT)
39346283Sdfrint
39498944Sobrienchild_insert_fork_catchpoint (int pid)
39546283Sdfr{
39646283Sdfr  /* This version of Unix doesn't support notification of fork events.  */
39746283Sdfr  return 0;
39846283Sdfr}
39946283Sdfr#endif
40046283Sdfr
40146283Sdfr#if !defined(CHILD_REMOVE_FORK_CATCHPOINT)
40246283Sdfrint
40398944Sobrienchild_remove_fork_catchpoint (int pid)
40446283Sdfr{
40546283Sdfr  /* This version of Unix doesn't support notification of fork events.  */
40646283Sdfr  return 0;
40746283Sdfr}
40846283Sdfr#endif
40946283Sdfr
41046283Sdfr#if !defined(CHILD_INSERT_VFORK_CATCHPOINT)
41146283Sdfrint
41298944Sobrienchild_insert_vfork_catchpoint (int pid)
41346283Sdfr{
41446283Sdfr  /* This version of Unix doesn't support notification of vfork events.  */
41546283Sdfr  return 0;
41646283Sdfr}
41746283Sdfr#endif
41846283Sdfr
41946283Sdfr#if !defined(CHILD_REMOVE_VFORK_CATCHPOINT)
42046283Sdfrint
42198944Sobrienchild_remove_vfork_catchpoint (int pid)
42246283Sdfr{
42346283Sdfr  /* This version of Unix doesn't support notification of vfork events.  */
42446283Sdfr  return 0;
42546283Sdfr}
42646283Sdfr#endif
42746283Sdfr
428130803Smarcel#if !defined(CHILD_FOLLOW_FORK)
42946283Sdfrint
430130803Smarcelchild_follow_fork (int follow_child)
43146283Sdfr{
432130803Smarcel  /* This version of Unix doesn't support following fork or vfork events.  */
43346283Sdfr  return 0;
43446283Sdfr}
43546283Sdfr#endif
43646283Sdfr
43746283Sdfr#if !defined(CHILD_INSERT_EXEC_CATCHPOINT)
43846283Sdfrint
43998944Sobrienchild_insert_exec_catchpoint (int pid)
44046283Sdfr{
44146283Sdfr  /* This version of Unix doesn't support notification of exec events.  */
44246283Sdfr  return 0;
44346283Sdfr}
44446283Sdfr#endif
44546283Sdfr
44646283Sdfr#if !defined(CHILD_REMOVE_EXEC_CATCHPOINT)
44746283Sdfrint
44898944Sobrienchild_remove_exec_catchpoint (int pid)
44946283Sdfr{
45046283Sdfr  /* This version of Unix doesn't support notification of exec events.  */
45146283Sdfr  return 0;
45246283Sdfr}
45346283Sdfr#endif
45446283Sdfr
45546283Sdfr#if !defined(CHILD_REPORTED_EXEC_EVENTS_PER_EXEC_CALL)
45646283Sdfrint
45798944Sobrienchild_reported_exec_events_per_exec_call (void)
45846283Sdfr{
45946283Sdfr  /* This version of Unix doesn't support notification of exec events.
46098944Sobrien   */
46146283Sdfr  return 1;
46246283Sdfr}
46346283Sdfr#endif
46446283Sdfr
46546283Sdfr#if !defined(CHILD_HAS_EXITED)
46646283Sdfrint
46798944Sobrienchild_has_exited (int pid, int wait_status, int *exit_status)
46846283Sdfr{
46946283Sdfr  if (WIFEXITED (wait_status))
47046283Sdfr    {
47146283Sdfr      *exit_status = WEXITSTATUS (wait_status);
47246283Sdfr      return 1;
47346283Sdfr    }
47446283Sdfr
47546283Sdfr  if (WIFSIGNALED (wait_status))
47646283Sdfr    {
47798944Sobrien      *exit_status = 0;		/* ?? Don't know what else to say here. */
47846283Sdfr      return 1;
47946283Sdfr    }
48046283Sdfr
48146283Sdfr  /* ?? Do we really need to consult the event state, too?  Assume the
48298944Sobrien     wait_state alone suffices.
48346283Sdfr   */
48446283Sdfr  return 0;
48546283Sdfr}
48646283Sdfr#endif
48746283Sdfr
48846283Sdfr
48919370Spststatic void
49098944Sobrienchild_mourn_inferior (void)
49119370Spst{
49219370Spst  unpush_target (&child_ops);
49319370Spst  generic_mourn_inferior ();
49419370Spst}
49519370Spst
49619370Spststatic int
49798944Sobrienchild_can_run (void)
49819370Spst{
49946283Sdfr  /* This variable is controlled by modules that sit atop inftarg that may layer
50046283Sdfr     their own process structure atop that provided here.  hpux-thread.c does
50146283Sdfr     this because of the Hpux user-mode level thread model.  */
50246283Sdfr
50346283Sdfr  return !child_suppress_run;
50419370Spst}
50519370Spst
50619370Spst/* Send a SIGINT to the process group.  This acts just like the user typed a
50719370Spst   ^C on the controlling terminal.
50819370Spst
50919370Spst   XXX - This may not be correct for all systems.  Some may want to use
51019370Spst   killpg() instead of kill (-pgrp). */
51119370Spst
51246283Sdfrstatic void
51398944Sobrienchild_stop (void)
51419370Spst{
51519370Spst  kill (-inferior_process_group, SIGINT);
51619370Spst}
51746283Sdfr
51846283Sdfr#if !defined(CHILD_ENABLE_EXCEPTION_CALLBACK)
51946283Sdfrstruct symtab_and_line *
52098944Sobrienchild_enable_exception_callback (enum exception_event_kind kind, int enable)
52146283Sdfr{
52246283Sdfr  return (struct symtab_and_line *) NULL;
52346283Sdfr}
52446283Sdfr#endif
52546283Sdfr
52646283Sdfr#if !defined(CHILD_GET_CURRENT_EXCEPTION_EVENT)
52746283Sdfrstruct exception_event_record *
52898944Sobrienchild_get_current_exception_event (void)
52946283Sdfr{
53046283Sdfr  return (struct exception_event_record *) NULL;
53146283Sdfr}
53246283Sdfr#endif
53346283Sdfr
53446283Sdfr
53546283Sdfr#if !defined(CHILD_PID_TO_EXEC_FILE)
53646283Sdfrchar *
53798944Sobrienchild_pid_to_exec_file (int pid)
53846283Sdfr{
53946283Sdfr  /* This version of Unix doesn't support translation of a process ID
54046283Sdfr     to the filename of the executable file.
54198944Sobrien   */
54246283Sdfr  return NULL;
54346283Sdfr}
54446283Sdfr#endif
54546283Sdfr
54646283Sdfrchar *
54798944Sobrienchild_core_file_to_sym_file (char *core)
54846283Sdfr{
54946283Sdfr  /* The target stratum for a running executable need not support
55046283Sdfr     this operation.
55198944Sobrien   */
55246283Sdfr  return NULL;
55346283Sdfr}
55446283Sdfr
555130803Smarcel/* Perform a partial transfer to/from the specified object.  For
556130803Smarcel   memory transfers, fall back to the old memory xfer functions.  */
557130803Smarcel
558130803Smarcelstatic LONGEST
559130803Smarcelchild_xfer_partial (struct target_ops *ops, enum target_object object,
560130803Smarcel		    const char *annex, void *readbuf,
561130803Smarcel		    const void *writebuf, ULONGEST offset, LONGEST len)
562130803Smarcel{
563130803Smarcel  switch (object)
564130803Smarcel    {
565130803Smarcel    case TARGET_OBJECT_MEMORY:
566130803Smarcel      if (readbuf)
567130803Smarcel	return child_xfer_memory (offset, readbuf, len, 0/*write*/,
568130803Smarcel				  NULL, ops);
569130803Smarcel      if (writebuf)
570130803Smarcel	return child_xfer_memory (offset, readbuf, len, 1/*write*/,
571130803Smarcel				  NULL, ops);
572130803Smarcel      return -1;
573130803Smarcel
574130803Smarcel    case TARGET_OBJECT_UNWIND_TABLE:
575130803Smarcel#ifndef NATIVE_XFER_UNWIND_TABLE
576130803Smarcel#define NATIVE_XFER_UNWIND_TABLE(OPS,OBJECT,ANNEX,WRITEBUF,READBUF,OFFSET,LEN) (-1)
577130803Smarcel#endif
578130803Smarcel      return NATIVE_XFER_UNWIND_TABLE (ops, object, annex, readbuf, writebuf,
579130803Smarcel				       offset, len);
580130803Smarcel
581130803Smarcel    case TARGET_OBJECT_AUXV:
582130803Smarcel#ifndef NATIVE_XFER_AUXV
583130803Smarcel#define NATIVE_XFER_AUXV(OPS,OBJECT,ANNEX,WRITEBUF,READBUF,OFFSET,LEN) (-1)
584130803Smarcel#endif
585130803Smarcel      return NATIVE_XFER_AUXV (ops, object, annex, readbuf, writebuf,
586130803Smarcel			       offset, len);
587130803Smarcel
588130803Smarcel    case TARGET_OBJECT_WCOOKIE:
589130803Smarcel#ifndef NATIVE_XFER_WCOOKIE
590130803Smarcel#define NATIVE_XFER_WCOOKIE(OPS,OBJECT,ANNEX,WRITEBUF,READBUF,OFFSET,LEN) (-1)
591130803Smarcel#endif
592130803Smarcel      return NATIVE_XFER_WCOOKIE (ops, object, annex, readbuf, writebuf,
593130803Smarcel				  offset, len);
594130803Smarcel
595131082Smarcel    case TARGET_OBJECT_DIRTY:
596132685Smarcel#ifndef NATIVE_XFER_DIRTY
597132685Smarcel#define NATIVE_XFER_DIRTY(OPS,OBJECT,ANNEX,WRITEBUF,READBUF,OFFSET,LEN) (-1)
598131082Smarcel#endif
599132685Smarcel      return NATIVE_XFER_DIRTY (ops, object, annex, readbuf, writebuf,
600131082Smarcel				offset, len);
601131082Smarcel
602130803Smarcel    default:
603130803Smarcel      return -1;
604130803Smarcel    }
605130803Smarcel}
606130803Smarcel
60798944Sobrien#if !defined(CHILD_PID_TO_STR)
60898944Sobrienchar *
60998944Sobrienchild_pid_to_str (ptid_t ptid)
61098944Sobrien{
61198944Sobrien  return normal_pid_to_str (ptid);
61298944Sobrien}
61398944Sobrien#endif
61446283Sdfr
61546283Sdfrstatic void
61698944Sobrieninit_child_ops (void)
61746283Sdfr{
61846283Sdfr  child_ops.to_shortname = "child";
61946283Sdfr  child_ops.to_longname = "Unix child process";
62046283Sdfr  child_ops.to_doc = "Unix child process (started by the \"run\" command).";
62146283Sdfr  child_ops.to_open = child_open;
62246283Sdfr  child_ops.to_attach = child_attach;
62346283Sdfr  child_ops.to_post_attach = child_post_attach;
62446283Sdfr  child_ops.to_detach = child_detach;
62546283Sdfr  child_ops.to_resume = child_resume;
62646283Sdfr  child_ops.to_wait = child_wait;
62746283Sdfr  child_ops.to_post_wait = child_post_wait;
62846283Sdfr  child_ops.to_fetch_registers = fetch_inferior_registers;
62946283Sdfr  child_ops.to_store_registers = store_inferior_registers;
63046283Sdfr  child_ops.to_prepare_to_store = child_prepare_to_store;
63146283Sdfr  child_ops.to_xfer_memory = child_xfer_memory;
632130803Smarcel  child_ops.to_xfer_partial = child_xfer_partial;
63346283Sdfr  child_ops.to_files_info = child_files_info;
63446283Sdfr  child_ops.to_insert_breakpoint = memory_insert_breakpoint;
63546283Sdfr  child_ops.to_remove_breakpoint = memory_remove_breakpoint;
63646283Sdfr  child_ops.to_terminal_init = terminal_init_inferior;
63746283Sdfr  child_ops.to_terminal_inferior = terminal_inferior;
63846283Sdfr  child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
639130803Smarcel  child_ops.to_terminal_save_ours = terminal_save_ours;
64046283Sdfr  child_ops.to_terminal_ours = terminal_ours;
64146283Sdfr  child_ops.to_terminal_info = child_terminal_info;
64246283Sdfr  child_ops.to_kill = kill_inferior;
64346283Sdfr  child_ops.to_create_inferior = child_create_inferior;
64446283Sdfr  child_ops.to_post_startup_inferior = child_post_startup_inferior;
64546283Sdfr  child_ops.to_acknowledge_created_inferior = child_acknowledge_created_inferior;
64646283Sdfr  child_ops.to_insert_fork_catchpoint = child_insert_fork_catchpoint;
64746283Sdfr  child_ops.to_remove_fork_catchpoint = child_remove_fork_catchpoint;
64846283Sdfr  child_ops.to_insert_vfork_catchpoint = child_insert_vfork_catchpoint;
64946283Sdfr  child_ops.to_remove_vfork_catchpoint = child_remove_vfork_catchpoint;
650130803Smarcel  child_ops.to_follow_fork = child_follow_fork;
65146283Sdfr  child_ops.to_insert_exec_catchpoint = child_insert_exec_catchpoint;
65246283Sdfr  child_ops.to_remove_exec_catchpoint = child_remove_exec_catchpoint;
65346283Sdfr  child_ops.to_reported_exec_events_per_exec_call = child_reported_exec_events_per_exec_call;
65446283Sdfr  child_ops.to_has_exited = child_has_exited;
65546283Sdfr  child_ops.to_mourn_inferior = child_mourn_inferior;
65646283Sdfr  child_ops.to_can_run = child_can_run;
65746283Sdfr  child_ops.to_thread_alive = child_thread_alive;
65898944Sobrien  child_ops.to_pid_to_str = child_pid_to_str;
65946283Sdfr  child_ops.to_stop = child_stop;
66046283Sdfr  child_ops.to_enable_exception_callback = child_enable_exception_callback;
66146283Sdfr  child_ops.to_get_current_exception_event = child_get_current_exception_event;
66246283Sdfr  child_ops.to_pid_to_exec_file = child_pid_to_exec_file;
66346283Sdfr  child_ops.to_stratum = process_stratum;
66446283Sdfr  child_ops.to_has_all_memory = 1;
66546283Sdfr  child_ops.to_has_memory = 1;
66646283Sdfr  child_ops.to_has_stack = 1;
66746283Sdfr  child_ops.to_has_registers = 1;
66846283Sdfr  child_ops.to_has_execution = 1;
66946283Sdfr  child_ops.to_magic = OPS_MAGIC;
67046283Sdfr}
67119370Spst
67298944Sobrien/* Take over the 'find_mapped_memory' vector from inftarg.c. */
673130803Smarcelextern void
674130803Smarcelinftarg_set_find_memory_regions (int (*func) (int (*) (CORE_ADDR,
675130803Smarcel						       unsigned long,
676130803Smarcel						       int, int, int,
67798944Sobrien						       void *),
67898944Sobrien					      void *))
67998944Sobrien{
68098944Sobrien  child_ops.to_find_memory_regions = func;
68198944Sobrien}
68298944Sobrien
68398944Sobrien/* Take over the 'make_corefile_notes' vector from inftarg.c. */
684130803Smarcelextern void
68598944Sobrieninftarg_set_make_corefile_notes (char * (*func) (bfd *, int *))
68698944Sobrien{
68798944Sobrien  child_ops.to_make_corefile_notes = func;
68898944Sobrien}
68998944Sobrien
69019370Spstvoid
69198944Sobrien_initialize_inftarg (void)
69219370Spst{
69319370Spst#ifdef HAVE_OPTIONAL_PROC_FS
69419370Spst  char procname[32];
69519370Spst  int fd;
69619370Spst
69719370Spst  /* If we have an optional /proc filesystem (e.g. under OSF/1),
69819370Spst     don't add ptrace support if we can access the running GDB via /proc.  */
69919370Spst#ifndef PROC_NAME_FMT
70019370Spst#define PROC_NAME_FMT "/proc/%05d"
70119370Spst#endif
70219370Spst  sprintf (procname, PROC_NAME_FMT, getpid ());
703130803Smarcel  fd = open (procname, O_RDONLY);
704130803Smarcel  if (fd >= 0)
70519370Spst    {
70619370Spst      close (fd);
70719370Spst      return;
70819370Spst    }
70919370Spst#endif
71019370Spst
71146283Sdfr  init_child_ops ();
71219370Spst  add_target (&child_ops);
71319370Spst}
714