* inftarg.c (child_create_inferior, child_attach,

child_mourn_inferior): collect unix child process stratum
	  functions which live below the target vector into this file to
	  facilitate host/target/native split.  Also, make them static.
	* inflow.c (child_mourn_inferior): removed.
	* infrun.c (child_create_inferior, child_attach): removed.
	  (resume): becomes global so that functions below the
	  target vector can find it.
	* inferior.h (resume): add prototype.
	  (child_mourn_inferior, child_create_inferior, child_attach):
	  remove prototypes.
This commit is contained in:
K. Richard Pixley 1992-09-25 19:19:08 +00:00
parent 050d45c5ea
commit 310cc57043
4 changed files with 352 additions and 304 deletions

View File

@ -1,5 +1,17 @@
Fri Sep 25 12:09:33 1992 K. Richard Pixley (rich@sendai.cygnus.com)
* inftarg.c (child_create_inferior, child_attach,
child_mourn_inferior): collect unix child process stratum
functions which live below the target vector into this file to
facilitate host/target/native split. Also, make them static.
* inflow.c (child_mourn_inferior): removed.
* infrun.c (child_create_inferior, child_attach): removed.
(resume): becomes global so that functions below the
target vector can find it.
* inferior.h (resume): add prototype.
(child_mourn_inferior, child_create_inferior, child_attach):
remove prototypes.
* xcoffexec.c (exec_ops): child_attach and child_create_inferior
replaced with find_default_attach and
find_default_create_inferior.

View File

@ -81,6 +81,11 @@ extern int inferior_pid;
extern char registers[];
/* Array of validity bits (one per register). Nonzero at position XXX_REGNUM
means that `registers' contains a valid copy of inferior register XXX. */
extern char register_valid[NUM_REGS];
extern void
clear_proceed_status PARAMS ((void));
@ -90,9 +95,6 @@ proceed PARAMS ((CORE_ADDR, int, int));
extern void
kill_inferior PARAMS ((void));
extern void
kill_inferior_fast PARAMS ((void));
extern void
generic_mourn_inferior PARAMS ((void));
@ -120,6 +122,9 @@ close_exec_file PARAMS ((void));
extern void
reopen_exec_file PARAMS ((void));
extern void
resume PARAMS ((int, int));
/* From misc files */
extern void
@ -131,9 +136,6 @@ fetch_inferior_registers PARAMS ((int));
extern void
solib_create_inferior_hook PARAMS ((void));
extern void
child_mourn_inferior PARAMS ((void));
extern void
child_terminal_info PARAMS ((char *, int));
@ -160,6 +162,13 @@ detach PARAMS ((int));
extern void
child_resume PARAMS ((int, int));
#ifndef PTRACE_ARG3_TYPE
#define PTRACE_ARG3_TYPE int /* Correct definition for most systems. */
#endif
extern int
call_ptrace PARAMS ((int, int, PTRACE_ARG3_TYPE, int));
/* From procfs.c */
#ifdef USE_PROC_FS
@ -191,12 +200,6 @@ new_tty_prefork PARAMS ((char *));
extern void
start_remote PARAMS ((void));
extern void
child_create_inferior PARAMS ((char *, char *, char **));
extern void
child_attach PARAMS ((char *, int));
extern void
normal_stop PARAMS ((void));

View File

@ -1,4 +1,6 @@
/* Start (run) and stop the inferior process, for GDB.
/* Target independent code for starting (run) and stoping an inferior
process.
Copyright 1986, 1987, 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
@ -110,7 +112,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "wait.h"
#include "gdbcore.h"
#include "command.h"
#include "terminal.h" /* For #ifdef TIOCGPGRP and new_tty */
#include "target.h"
#include <signal.h>
@ -122,13 +123,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/file.h>
#endif
#ifdef SET_STACK_LIMIT_HUGE
#include <sys/time.h>
#include <sys/resource.h>
extern int original_stack_limit;
#endif /* SET_STACK_LIMIT_HUGE */
/* Prototypes for local functions */
static void
@ -149,14 +143,9 @@ remove_step_breakpoint PARAMS ((void));
static void
insert_step_breakpoint PARAMS ((void));
static void
resume PARAMS ((int, int));
static void
resume_cleanups PARAMS ((int));
extern char **environ;
extern struct target_ops child_ops; /* In inftarg.c */
/* Sigtramp is a routine that the kernel calls (which then calls the
@ -323,7 +312,7 @@ resume_cleanups (arg)
STEP nonzero if we should step (zero to continue instead).
SIG is the signal to give the inferior (zero for none). */
static void
void
resume (step, sig)
int step;
int sig;
@ -470,222 +459,6 @@ static CORE_ADDR prev_func_start;
static char *prev_func_name;
/* Start an inferior Unix child process and sets inferior_pid to its pid.
EXEC_FILE is the file to run.
ALLARGS is a string containing the arguments to the program.
ENV is the environment vector to pass. Errors reported with error(). */
#ifndef SHELL_FILE
#define SHELL_FILE "/bin/sh"
#endif
void
child_create_inferior (exec_file, allargs, env)
char *exec_file;
char *allargs;
char **env;
{
int pid;
char *shell_command;
char *shell_file;
static char default_shell_file[] = SHELL_FILE;
int len;
int pending_execs;
/* Set debug_fork then attach to the child while it sleeps, to debug. */
static int debug_fork = 0;
/* This is set to the result of setpgrp, which if vforked, will be visible
to you in the parent process. It's only used by humans for debugging. */
static int debug_setpgrp = 657473;
char **save_our_env;
/* The user might want tilde-expansion, and in general probably wants
the program to behave the same way as if run from
his/her favorite shell. So we let the shell run it for us.
FIXME, this should probably search the local environment (as
modified by the setenv command), not the env gdb inherited. */
shell_file = getenv ("SHELL");
if (shell_file == NULL)
shell_file = default_shell_file;
len = 5 + strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop*/ 10;
/* If desired, concat something onto the front of ALLARGS.
SHELL_COMMAND is the result. */
#ifdef SHELL_COMMAND_CONCAT
shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + len);
strcpy (shell_command, SHELL_COMMAND_CONCAT);
#else
shell_command = (char *) alloca (len);
shell_command[0] = '\0';
#endif
strcat (shell_command, "exec ");
strcat (shell_command, exec_file);
strcat (shell_command, " ");
strcat (shell_command, allargs);
/* exec is said to fail if the executable is open. */
close_exec_file ();
/* Retain a copy of our environment variables, since the child will
replace the value of environ and if we're vforked, we have to
restore it. */
save_our_env = environ;
/* Tell the terminal handling subsystem what tty we plan to run on;
it will just record the information for later. */
new_tty_prefork (inferior_io_terminal);
/* It is generally good practice to flush any possible pending stdio
output prior to doing a fork, to avoid the possibility of both the
parent and child flushing the same data after the fork. */
fflush (stdout);
fflush (stderr);
#if defined(USG) && !defined(HAVE_VFORK)
pid = fork ();
#else
if (debug_fork)
pid = fork ();
else
pid = vfork ();
#endif
if (pid < 0)
perror_with_name ("vfork");
if (pid == 0)
{
if (debug_fork)
sleep (debug_fork);
#ifdef TIOCGPGRP
/* Run inferior in a separate process group. */
#ifdef NEED_POSIX_SETPGID
debug_setpgrp = setpgid (0, 0);
#else
#if defined(USG) && !defined(SETPGRP_ARGS)
debug_setpgrp = setpgrp ();
#else
debug_setpgrp = setpgrp (getpid (), getpid ());
#endif /* USG */
#endif /* NEED_POSIX_SETPGID */
if (debug_setpgrp == -1)
perror("setpgrp failed in child");
#endif /* TIOCGPGRP */
#ifdef SET_STACK_LIMIT_HUGE
/* Reset the stack limit back to what it was. */
{
struct rlimit rlim;
getrlimit (RLIMIT_STACK, &rlim);
rlim.rlim_cur = original_stack_limit;
setrlimit (RLIMIT_STACK, &rlim);
}
#endif /* SET_STACK_LIMIT_HUGE */
/* Ask the tty subsystem to switch to the one we specified earlier
(or to share the current terminal, if none was specified). */
new_tty ();
/* Changing the signal handlers for the inferior after
a vfork can also change them for the superior, so we don't mess
with signals here. See comments in
initialize_signals for how we get the right signal handlers
for the inferior. */
#ifdef USE_PROC_FS
/* Use SVR4 /proc interface */
proc_set_exec_trap ();
#else
/* "Trace me, Dr. Memory!" */
call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
#endif
/* There is no execlpe call, so we have to set the environment
for our child in the global variable. If we've vforked, this
clobbers the parent, but environ is restored a few lines down
in the parent. By the way, yes we do need to look down the
path to find $SHELL. Rich Pixley says so, and I agree. */
environ = env;
execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
safe_strerror (errno));
fflush (stderr);
_exit (0177);
}
/* Restore our environment in case a vforked child clob'd it. */
environ = save_our_env;
/* Now that we have a child process, make it our target. */
push_target (&child_ops);
#ifdef CREATE_INFERIOR_HOOK
CREATE_INFERIOR_HOOK (pid);
#endif
/* The process was started by the fork that created it,
but it will have stopped one instruction after execing the shell.
Here we must get it up to actual execution of the real program. */
inferior_pid = pid; /* Needed for wait_for_inferior stuff below */
clear_proceed_status ();
/* We will get a trace trap after one instruction.
Continue it automatically. Eventually (after shell does an exec)
it will get another trace trap. Then insert breakpoints and continue. */
#ifdef START_INFERIOR_TRAPS_EXPECTED
pending_execs = START_INFERIOR_TRAPS_EXPECTED;
#else
pending_execs = 2;
#endif
init_wait_for_inferior ();
/* Set up the "saved terminal modes" of the inferior
based on what modes we are starting it with. */
target_terminal_init ();
/* Install inferior's terminal modes. */
target_terminal_inferior ();
while (1)
{
stop_soon_quietly = 1; /* Make wait_for_inferior be quiet */
wait_for_inferior ();
if (stop_signal != SIGTRAP)
{
/* Let shell child handle its own signals in its own way */
/* FIXME, what if child has exit()ed? Must exit loop somehow */
resume (0, stop_signal);
}
else
{
/* We handle SIGTRAP, however; it means child did an exec. */
if (0 == --pending_execs)
break;
resume (0, 0); /* Just make it go on */
}
}
stop_soon_quietly = 0;
/* We are now in the child process of interest, having exec'd the
correct program, and are poised at the first instruction of the
new program. */
#ifdef SOLIB_CREATE_INFERIOR_HOOK
SOLIB_CREATE_INFERIOR_HOOK (pid);
#endif
/* Pedal to the metal. Away we go. */
proceed ((CORE_ADDR) -1, 0, 0);
}
/* Start remote-debugging of a machine over a serial link. */
void
@ -717,64 +490,6 @@ init_wait_for_inferior ()
}
/* Attach to process PID, then initialize for debugging it
and wait for the trace-trap that results from attaching. */
void
child_attach (args, from_tty)
char *args;
int from_tty;
{
char *exec_file;
int pid;
dont_repeat();
if (!args)
error_no_arg ("process-id to attach");
#ifndef ATTACH_DETACH
error ("Can't attach to a process on this machine.");
#else
pid = atoi (args);
if (pid == getpid()) /* Trying to masturbate? */
error ("I refuse to debug myself!");
if (target_has_execution)
{
if (query ("A program is being debugged already. Kill it? "))
target_kill ();
else
error ("Inferior not killed.");
}
exec_file = (char *) get_exec_file (1);
if (from_tty)
{
printf ("Attaching program: %s pid %d\n",
exec_file, pid);
fflush (stdout);
}
attach (pid);
inferior_pid = pid;
push_target (&child_ops);
mark_breakpoints_out ();
target_terminal_init ();
clear_proceed_status ();
stop_soon_quietly = 1;
/*proceed (-1, 0, -2);*/
target_terminal_inferior ();
wait_for_inferior ();
#ifdef SOLIB_ADD
SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
#endif
normal_stop ();
#endif /* ATTACH_DETACH */
}
/* Wait for control to return from inferior to debugger.
If inferior gets a signal, we may decide to start it up again

View File

@ -1,6 +1,6 @@
/* Subroutines for handling an "inferior" (child) process as a target
for debugging, in GDB.
Copyright 1990, 1991 Free Software Foundation, Inc.
/* This file inplements the host independent child process statum.
Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB.
@ -26,6 +26,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "wait.h"
#include "gdbcore.h"
#include "ieee-float.h" /* Required by REGISTER_CONVERT_TO_XXX */
#include "terminal.h" /* For #ifdef TIOCGPGRP and new_tty */
#include <signal.h>
#ifdef SET_STACK_LIMIT_HUGE
#include <sys/time.h>
#include <sys/resource.h>
extern int original_stack_limit;
#endif /* SET_STACK_LIMIT_HUGE */
static void
child_prepare_to_store PARAMS ((void));
@ -42,6 +52,17 @@ child_files_info PARAMS ((struct target_ops *));
static void
child_detach PARAMS ((char *, int));
static void
child_attach PARAMS ((char *, int));
static void
child_create_inferior PARAMS ((char *, char *, char **));
static void
child_mourn_inferior PARAMS ((void));
extern char **environ;
/* Forward declaration */
extern struct target_ops child_ops;
@ -71,6 +92,68 @@ child_wait (status)
}
/* Attach to process PID, then initialize for debugging it
and wait for the trace-trap that results from attaching. */
static void
child_attach (args, from_tty)
char *args;
int from_tty;
{
char *exec_file;
int pid;
dont_repeat();
if (!args)
error_no_arg ("process-id to attach");
#ifndef ATTACH_DETACH
error ("Can't attach to a process on this machine.");
#else
pid = atoi (args);
if (pid == getpid()) /* Trying to masturbate? */
error ("I refuse to debug myself!");
if (target_has_execution)
{
if (query ("A program is being debugged already. Kill it? "))
target_kill ();
else
error ("Inferior not killed.");
}
if (from_tty)
{
exec_file = (char *) get_exec_file (0);
if (exec_file)
printf ("Attaching program `%s', pid %d\n", exec_file, pid);
else
printf ("Attaching pid %d\n", pid);
fflush (stdout);
}
attach (pid);
inferior_pid = pid;
push_target (&child_ops);
mark_breakpoints_out ();
target_terminal_init ();
clear_proceed_status ();
stop_soon_quietly = 1;
/*proceed (-1, 0, -2);*/
target_terminal_inferior ();
wait_for_inferior ();
#ifdef SOLIB_ADD
SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
#endif
normal_stop ();
#endif /* ATTACH_DETACH */
}
/*
* child_detach()
* takes a program previously attached to and detaches it.
@ -143,6 +226,240 @@ child_open (arg, from_tty)
error ("Use the \"run\" command to start a Unix child process.");
}
/* Start an inferior Unix child process and sets inferior_pid to its pid.
EXEC_FILE is the file to run.
ALLARGS is a string containing the arguments to the program.
ENV is the environment vector to pass. Errors reported with error(). */
#ifndef SHELL_FILE
#define SHELL_FILE "/bin/sh"
#endif
static void
child_create_inferior (exec_file, allargs, env)
char *exec_file;
char *allargs;
char **env;
{
int pid;
char *shell_command;
char *shell_file;
static char default_shell_file[] = SHELL_FILE;
int len;
int pending_execs;
/* Set debug_fork then attach to the child while it sleeps, to debug. */
static int debug_fork = 0;
/* This is set to the result of setpgrp, which if vforked, will be visible
to you in the parent process. It's only used by humans for debugging. */
static int debug_setpgrp = 657473;
char **save_our_env;
/* If no exec file handed to us, get it from the exec-file command -- with
a good, common error message if none is specified. */
if (exec_file == 0)
exec_file = get_exec_file(1);
/* The user might want tilde-expansion, and in general probably wants
the program to behave the same way as if run from
his/her favorite shell. So we let the shell run it for us.
FIXME, this should probably search the local environment (as
modified by the setenv command), not the env gdb inherited. */
shell_file = getenv ("SHELL");
if (shell_file == NULL)
shell_file = default_shell_file;
len = 5 + strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop*/ 10;
/* If desired, concat something onto the front of ALLARGS.
SHELL_COMMAND is the result. */
#ifdef SHELL_COMMAND_CONCAT
shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + len);
strcpy (shell_command, SHELL_COMMAND_CONCAT);
#else
shell_command = (char *) alloca (len);
shell_command[0] = '\0';
#endif
strcat (shell_command, "exec ");
strcat (shell_command, exec_file);
strcat (shell_command, " ");
strcat (shell_command, allargs);
/* exec is said to fail if the executable is open. */
close_exec_file ();
/* Retain a copy of our environment variables, since the child will
replace the value of environ and if we're vforked, we have to
restore it. */
save_our_env = environ;
/* Tell the terminal handling subsystem what tty we plan to run on;
it will just record the information for later. */
new_tty_prefork (inferior_io_terminal);
/* It is generally good practice to flush any possible pending stdio
output prior to doing a fork, to avoid the possibility of both the
parent and child flushing the same data after the fork. */
fflush (stdout);
fflush (stderr);
#if defined(USG) && !defined(HAVE_VFORK)
pid = fork ();
#else
if (debug_fork)
pid = fork ();
else
pid = vfork ();
#endif
if (pid < 0)
perror_with_name ("vfork");
if (pid == 0)
{
if (debug_fork)
sleep (debug_fork);
#ifdef TIOCGPGRP
/* Run inferior in a separate process group. */
#ifdef NEED_POSIX_SETPGID
debug_setpgrp = setpgid (0, 0);
#else
#if defined(USG) && !defined(SETPGRP_ARGS)
debug_setpgrp = setpgrp ();
#else
debug_setpgrp = setpgrp (getpid (), getpid ());
#endif /* USG */
#endif /* NEED_POSIX_SETPGID */
if (debug_setpgrp == -1)
perror("setpgrp failed in child");
#endif /* TIOCGPGRP */
#ifdef SET_STACK_LIMIT_HUGE
/* Reset the stack limit back to what it was. */
{
struct rlimit rlim;
getrlimit (RLIMIT_STACK, &rlim);
rlim.rlim_cur = original_stack_limit;
setrlimit (RLIMIT_STACK, &rlim);
}
#endif /* SET_STACK_LIMIT_HUGE */
/* Ask the tty subsystem to switch to the one we specified earlier
(or to share the current terminal, if none was specified). */
new_tty ();
/* Changing the signal handlers for the inferior after
a vfork can also change them for the superior, so we don't mess
with signals here. See comments in
initialize_signals for how we get the right signal handlers
for the inferior. */
#ifdef USE_PROC_FS
/* Use SVR4 /proc interface */
proc_set_exec_trap ();
#else
/* "Trace me, Dr. Memory!" */
call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
#endif
/* There is no execlpe call, so we have to set the environment
for our child in the global variable. If we've vforked, this
clobbers the parent, but environ is restored a few lines down
in the parent. By the way, yes we do need to look down the
path to find $SHELL. Rich Pixley says so, and I agree. */
environ = env;
execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
safe_strerror (errno));
fflush (stderr);
_exit (0177);
}
/* Restore our environment in case a vforked child clob'd it. */
environ = save_our_env;
/* Now that we have a child process, make it our target. */
push_target (&child_ops);
#ifdef CREATE_INFERIOR_HOOK
CREATE_INFERIOR_HOOK (pid);
#endif
/* The process was started by the fork that created it,
but it will have stopped one instruction after execing the shell.
Here we must get it up to actual execution of the real program. */
inferior_pid = pid; /* Needed for wait_for_inferior stuff below */
clear_proceed_status ();
/* We will get a trace trap after one instruction.
Continue it automatically. Eventually (after shell does an exec)
it will get another trace trap. Then insert breakpoints and continue. */
#ifdef START_INFERIOR_TRAPS_EXPECTED
pending_execs = START_INFERIOR_TRAPS_EXPECTED;
#else
pending_execs = 2;
#endif
init_wait_for_inferior ();
/* Set up the "saved terminal modes" of the inferior
based on what modes we are starting it with. */
target_terminal_init ();
/* Install inferior's terminal modes. */
target_terminal_inferior ();
while (1)
{
stop_soon_quietly = 1; /* Make wait_for_inferior be quiet */
wait_for_inferior ();
if (stop_signal != SIGTRAP)
{
/* Let shell child handle its own signals in its own way */
/* FIXME, what if child has exit()ed? Must exit loop somehow */
resume (0, stop_signal);
}
else
{
/* We handle SIGTRAP, however; it means child did an exec. */
if (0 == --pending_execs)
break;
resume (0, 0); /* Just make it go on */
}
}
stop_soon_quietly = 0;
/* We are now in the child process of interest, having exec'd the
correct program, and are poised at the first instruction of the
new program. */
#ifdef SOLIB_CREATE_INFERIOR_HOOK
SOLIB_CREATE_INFERIOR_HOOK (pid);
#endif
/* Pedal to the metal. Away we go. */
proceed ((CORE_ADDR) -1, 0, 0);
}
static void
child_mourn_inferior ()
{
unpush_target (&child_ops);
generic_mourn_inferior ();
}
static int
child_can_run ()
{
return(1);
}
struct target_ops child_ops = {
"child", /* to_shortname */
"Unix child process", /* to_longname */
@ -170,6 +487,7 @@ struct target_ops child_ops = {
0, /* to_lookup_symbol */
child_create_inferior, /* to_create_inferior */
child_mourn_inferior, /* to_mourn_inferior */
child_can_run, /* to_can_run */
process_stratum, /* to_stratum */
0, /* to_next */
1, /* to_has_all_memory */