This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Likely obsolete pieces of GDB


> > Tried a simple test with this version.  Tried to debug gdb itself.
> > Set a break on main and ran gdb with "-v".  The exterior gdb dumped
> > core.  The cause seems to be that the deprecated_child_ops struct
> > hasn't been initialized.  It looks like the stuff in inf-ptrace.c
> > needs to be merged into hpux-thread.c, or we need to setup
> > deprecated_child_ops.  Presumably, this was done at some point in
> > the past.
> 
> Is this worth fixing?  Obviously no one has used it lately.

Don't know but I probably would use it if it worked.  I hacked
on this a bit a couple of weeks ago.  I mainly pulled code from
inftarg.c with a bit of specialization for hpux.  It builds and
some stuff may work...

Dave
-- 
J. David Anglin                                  dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

Index: gdb/hpux-thread.c
===================================================================
RCS file: /cvs/src/src/gdb/hpux-thread.c,v
retrieving revision 1.32
diff -u -3 -p -r1.32 hpux-thread.c
--- gdb/hpux-thread.c	17 Dec 2005 22:34:01 -0000	1.32
+++ gdb/hpux-thread.c	1 Jan 2007 16:39:37 -0000
@@ -41,6 +41,7 @@
 #include <cma_deb_core.h>
 #include "gdbthread.h"
 #include "target.h"
+#include "command.h"
 #include "inferior.h"
 #include "regcache.h"
 #include <fcntl.h>
@@ -48,6 +49,9 @@
 #include "gdb_stat.h"
 #include "gdbcore.h"
 #include "hppa-tdep.h"
+#include "inflow.h"
+
+#include "gdb_ptrace.h"
 
 extern int child_suppress_run;
 
@@ -118,7 +122,8 @@ find_tcb (ptid_t ptid)
 
       tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
 
-      read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
+      read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb,
+		   sizeof cached_tcb);
 
       if (cached_tcb.header.type == cma__c_obj_tcb)
 	if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
@@ -138,18 +143,79 @@ find_tcb (ptid_t ptid)
 static void
 hpux_thread_open (char *arg, int from_tty)
 {
-  deprecated_child_ops.to_open (arg, from_tty);
+  error (_("Use the \"run\" command to start a Unix child process."));
+}
+
+/* Start debugging the process whose number is PID.  */
+
+static int
+hpux_attach (int pid)
+{
+  errno = 0;
+  ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3) 0, 0);
+  if (errno != 0)
+    perror_with_name (("ptrace"));
+  attach_flag = 1;
+  return pid;
 }
 
 /* Attach to process PID, then initialize for debugging it
    and wait for the trace-trap that results from attaching.  */
 
+/* XXX - might want to iterate over all the threads and register them. */
+
 static void
 hpux_thread_attach (char *args, int from_tty)
 {
-  deprecated_child_ops.to_attach (args, from_tty);
+  char *exec_file;
+  int pid;
+  char *dummy;
+
+  if (!args)
+    error_no_arg (_("process-id to attach"));
+
+  dummy = args;
+  pid = strtol (args, &dummy, 0);
+  /* Some targets don't set errno on errors, grrr! */
+  if ((pid == 0) && (args == dummy))
+      error (_("Illegal process-id: %s."), args);
+
+  if (pid == getpid ()) /* Trying to masturbate? */
+    error (_("I refuse to debug myself!"));
+
+  if (from_tty)
+    {
+      exec_file = (char *) get_exec_file (0);
+
+      if (exec_file)
+        printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
+                           target_pid_to_str (pid_to_ptid (pid)));
+      else
+        printf_unfiltered (_("Attaching to %s\n"),
+                           target_pid_to_str (pid_to_ptid (pid)));
+
+      gdb_flush (gdb_stdout);
+    }
+
+  hpux_attach (pid);
+
+  inferior_ptid = pid_to_ptid (pid);
+  push_target (&hpux_thread_ops);
+}
+
+/* Stop debugging the process whose number is PID and continue it with
+   signal number SIGNAL.  SIGNAL = 0 means just continue it.  */
+
+static void
+hpux_detach (int signal)
+{
+  int pid = PIDGET (inferior_ptid);
 
-  /* XXX - might want to iterate over all the threads and register them. */
+  errno = 0;
+  ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3) 1, signal);
+  if (errno != 0)
+    perror_with_name (("ptrace"));
+  attach_flag = 0;
 }
 
 /* Take a program previously attached to and detaches it.
@@ -163,7 +229,25 @@ hpux_thread_attach (char *args, int from
 static void
 hpux_thread_detach (char *args, int from_tty)
 {
-  deprecated_child_ops.to_detach (args, from_tty);
+  int siggnal = 0;
+  int pid = PIDGET (inferior_ptid);
+
+  if (from_tty)
+    {
+      char *exec_file = get_exec_file (0);
+      if (exec_file == 0)
+        exec_file = "";
+      printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
+                         target_pid_to_str (pid_to_ptid (pid)));
+      gdb_flush (gdb_stdout);
+    }
+  if (args)
+    siggnal = atoi (args);
+
+  hpux_detach (siggnal);
+
+  inferior_ptid = null_ptid;
+  unpush_target (&hpux_thread_ops);
 }
 
 /* Resume execution of process PID.  If STEP is nozero, then
@@ -172,6 +256,40 @@ hpux_thread_detach (char *args, int from
    for procfs.  */
 
 static void
+hpux_child_resume (ptid_t ptid, int step, enum target_signal signal)
+{
+  int request = PT_CONTINUE;
+  int pid = PIDGET (ptid);
+
+  if (pid == -1)
+    /* Resume all threads.  */
+    /* I think this only gets used in the non-threaded case, where "resume
+       all threads" and "resume inferior_ptid" are the same.  */
+    pid = PIDGET (inferior_ptid);
+
+  if (step)
+    {
+      /* If this system does not support PT_STEP, a higher level
+         function will have called single_step() to transmute the step
+         request into a continue request (by setting breakpoints on
+         all possible successor instructions), so we don't have to
+         worry about that here.  */
+
+      gdb_assert (!SOFTWARE_SINGLE_STEP_P ());
+      request = PT_STEP;
+    }
+
+  /* An address of (PTRACE_TYPE_ARG3)1 tells ptrace to continue from
+     where it was.  If GDB wanted it to start some other way, we have
+     already written a new PC value to the child.  */
+
+  errno = 0;
+  ptrace (request, pid, (PTRACE_TYPE_ARG3)1, target_signal_to_host (signal));
+  if (errno != 0)
+    perror_with_name (("ptrace"));
+}
+
+static void
 hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
 {
   struct cleanup *old_chain;
@@ -190,13 +308,76 @@ hpux_thread_resume (ptid_t ptid, int ste
     }
 #endif
 
-  deprecated_child_ops.to_resume (ptid, step, signo);
+  hpux_child_resume (ptid, step, signo);
 
   cached_thread = 0;
 
   do_cleanups (old_chain);
 }
 
+/* Wait for child to do something.  Return pid of child, or -1 in case
+   of error; store status through argument pointer OURSTATUS.  */
+
+static ptid_t
+child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
+{
+  int save_errno;
+  int status;
+  char *execd_pathname = NULL;
+  int exit_status;
+  int syscall_id;
+  enum target_waitkind kind;
+  int pid;
+
+  do
+    {
+      set_sigint_trap ();       /* Causes SIGINT to be passed on to the
+                                   attached process. */
+      set_sigio_trap ();
+
+      pid = wait (&status);
+
+      save_errno = errno;
+
+      clear_sigio_trap ();
+
+      clear_sigint_trap ();
+
+      if (pid == -1)
+        {
+          if (save_errno == EINTR)
+            continue;
+
+          fprintf_unfiltered (gdb_stderr, 
+			      "Child process unexpectedly missing: %s.\n",
+                              safe_strerror (save_errno));
+
+          /* Claim it exited with unknown signal.  */
+          ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+          ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+          return pid_to_ptid (-1);
+        }
+
+      /* Did it exit?
+       */
+      if (target_has_exited (pid, status, &exit_status))
+        {
+          /* ??rehrauer: For now, ignore this. */
+          continue;
+        }
+
+      if (!target_thread_alive (pid_to_ptid (pid)))
+        {
+          ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+          return pid_to_ptid (pid);
+        }
+      } while (pid != PIDGET (inferior_ptid)); /* Some other child died or stopp
+ed */
+
+  store_waitstatus (ourstatus, status);
+  return pid_to_ptid (pid);
+}
+
 /* Wait for any threads to stop.  We may have to convert PID from a thread id
    to a LWP id, and vice versa on the way out.  */
 
@@ -213,7 +394,7 @@ hpux_thread_wait (ptid_t ptid, struct ta
   if (!ptid_equal (ptid, minus_one_ptid))
     ptid = main_ptid;
 
-  rtnval = deprecated_child_ops.to_wait (ptid, ourstatus);
+  rtnval = child_wait (ptid, ourstatus);
 
   rtnval = find_active_thread ();
 
@@ -248,6 +429,84 @@ static char regmap[] =
   -1, -1, -1, -1, -1, -1, -1, -1,	/* fr28 -> fr31 */
 };
 
+#define REGISTER_U_ADDR(addr, blockend, regno)                          \
+{ addr = (int)(blockend) + regno;}
+
+/* U_REGS_OFFSET is the offset of the registers within the u area.  */
+#define U_REGS_OFFSET 0
+
+/* Return the address in the core dump or inferior of register REGNO.
+   BLOCKEND is the address of the end of the user structure.  */
+
+static CORE_ADDR
+hpux_register_addr (int regno, CORE_ADDR blockend)
+{
+  int addr;
+
+  if (regno < 0 || regno >= NUM_REGS)
+    error ("Invalid register number %d.", regno);
+
+  REGISTER_U_ADDR (addr, blockend, regno);
+
+  return addr;
+}
+
+/* Fetch register REGNUM from the inferior.  */
+
+static void
+fetch_register (int regnum)
+{
+  CORE_ADDR addr;
+  size_t size;
+  PTRACE_TYPE_RET *buf;
+  int tid, i;
+
+  if (CANNOT_FETCH_REGISTER (regnum))
+    {
+      regcache_raw_supply (current_regcache, regnum, NULL);
+      return;
+    }
+
+  /* GNU/Linux LWP ID's are process ID's.  */
+  tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
+
+  /* This isn't really an address.  But ptrace thinks of it as one.  */
+  addr = hpux_register_addr (regnum, U_REGS_OFFSET);
+  size = register_size (current_gdbarch, regnum);
+
+  gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
+  buf = alloca (size);
+
+  /* Read the register contents from the inferior a chuck at the time.  */
+  for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+    {
+      errno = 0;
+      buf[i] = ptrace (PT_READ_U, tid, (PTRACE_TYPE_ARG3) addr, 0);
+      if (errno != 0)
+        error (_("Couldn't read register %s (#%d): %s."),
+	       REGISTER_NAME (regnum),
+               regnum, safe_strerror (errno));
+
+      addr += sizeof (PTRACE_TYPE_RET);
+    }
+  regcache_raw_supply (current_regcache, regnum, buf);
+}
+
+/* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
+   for all registers.  */
+
+static void
+hpux_fetch_inferior_registers (int regnum)
+{
+  if (regnum == -1)
+    for (regnum = 0; regnum < NUM_REGS; regnum++)
+      fetch_register (regnum);
+  else
+    fetch_register (regnum);
+}
+
 static void
 hpux_thread_fetch_registers (int regno)
 {
@@ -264,7 +523,7 @@ hpux_thread_fetch_registers (int regno)
 
   if (tcb_ptr->state == cma__c_state_running)
     {
-      deprecated_child_ops.to_fetch_registers (regno);
+      hpux_fetch_inferior_registers (regno);
 
       do_cleanups (old_chain);
 
@@ -285,7 +544,7 @@ hpux_thread_fetch_registers (int regno)
   for (regno = first_regno; regno <= last_regno; regno++)
     {
       if (regmap[regno] == -1)
-	deprecated_child_ops.to_fetch_registers (regno);
+	hpux_fetch_inferior_registers (regno);
       else
 	{
 	  unsigned char buf[MAX_REGISTER_SIZE];
@@ -310,6 +569,58 @@ hpux_thread_fetch_registers (int regno)
   do_cleanups (old_chain);
 }
 
+/* Store register REGNUM into the inferior.  */
+
+static void
+store_register (int regnum)
+{
+  CORE_ADDR addr;
+  size_t size;
+  PTRACE_TYPE_RET *buf;
+  int tid, i;
+
+  if (CANNOT_STORE_REGISTER (regnum))
+    return;
+
+  /* GNU/Linux LWP ID's are process ID's.  */
+  tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
+
+  /* This isn't really an address.  But ptrace thinks of it as one.  */
+  addr = hpux_register_addr (regnum, U_REGS_OFFSET);
+  size = register_size (current_gdbarch, regnum);
+
+  gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
+  buf = alloca (size);
+
+  /* Write the register contents into the inferior a chunk at the time.  */
+  regcache_raw_collect (current_regcache, regnum, buf);
+  for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+    {
+      errno = 0;
+      ptrace (PT_WRITE_U, tid, (PTRACE_TYPE_ARG3) addr, buf[i]);
+      if (errno != 0)
+        error (_("Couldn't write register %s (#%d): %s."),
+               REGISTER_NAME (regnum), regnum, safe_strerror (errno));
+
+      addr += sizeof (PTRACE_TYPE_RET);
+    }
+}
+
+/* Store register REGNUM back into the inferior.  If REGNUM is -1, do
+   this for all registers (including the floating point registers).  */
+
+static void
+hpux_store_inferior_registers (int regnum)
+{
+  if (regnum == -1)
+    for (regnum = 0; regnum < NUM_REGS; regnum++)
+      store_register (regnum);
+  else
+    store_register (regnum);
+}
+
 static void
 hpux_thread_store_registers (int regno)
 {
@@ -326,7 +637,7 @@ hpux_thread_store_registers (int regno)
 
   if (tcb_ptr->state == cma__c_state_running)
     {
-      deprecated_child_ops.to_store_registers (regno);
+      hpux_store_inferior_registers (regno);
 
       do_cleanups (old_chain);
 
@@ -347,7 +658,7 @@ hpux_thread_store_registers (int regno)
   for (regno = first_regno; regno <= last_regno; regno++)
     {
       if (regmap[regno] == -1)
-	deprecated_child_ops.to_store_registers (regno);
+	hpux_store_inferior_registers (regno);
       else
 	{
 	  unsigned char buf[MAX_REGISTER_SIZE];
@@ -356,7 +667,7 @@ hpux_thread_store_registers (int regno)
 	  sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
 
 	  if (regno == HPPA_FLAGS_REGNUM)
-	    deprecated_child_ops.to_store_registers (regno);	/* Let lower layer handle this... */
+	    hpux_store_inferior_registers (regno);
 	  else if (regno == HPPA_SP_REGNUM)
 	    {
 	      regcache_raw_read (current_regcache, regno, buf);
@@ -392,11 +703,148 @@ hpux_thread_store_registers (int regno)
 static void
 hpux_thread_prepare_to_store (void)
 {
-  deprecated_child_ops.to_prepare_to_store ();
+#ifdef CHILD_PREPARE_TO_STORE
+  CHILD_PREPARE_TO_STORE ();
+#endif
 }
 
+/* Set an upper limit on alloca.  */
+#ifndef GDB_MAX_ALLOCA
+#define GDB_MAX_ALLOCA 0x1000
+#endif
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR to
+   debugger memory starting at MYADDR.  Copy to inferior if WRITE is
+   nonzero.  TARGET is ignored.
+
+   Returns the length copied, which is either the LEN argument or
+   zero.  This xfer function does not do partial moves, since
+   deprecated_child_ops doesn't allow memory operations to cross below
+   us in the target stack anyway.  */
+
 static int
-hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
+hpux_child_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
+			struct mem_attrib *attrib, struct target_ops *target)
+{
+  int i;
+  /* Round starting address down to longword boundary.  */
+  CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
+  /* Round ending address up; get number of longwords that makes.  */
+  int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
+               / sizeof (PTRACE_TYPE_RET));
+  int alloc = count * sizeof (PTRACE_TYPE_RET);
+  PTRACE_TYPE_RET *buffer;
+  struct cleanup *old_chain = NULL;
+
+#ifdef PT_IO
+  /* OpenBSD 3.1, NetBSD 1.6 and FreeBSD 5.0 have a new PT_IO request
+     that promises to be much more efficient in reading and writing
+     data in the traced process's address space.  */
+
+  {
+    struct ptrace_io_desc piod;
+
+    /* NOTE: We assume that there are no distinct address spaces for
+       instruction and data.  */
+    piod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D;
+    piod.piod_offs = (void *) memaddr;
+    piod.piod_addr = myaddr;
+    piod.piod_len = len;
+
+    if (ptrace (PT_IO, PIDGET (inferior_ptid), (caddr_t) &piod, 0) == -1)
+      {
+        /* If the PT_IO request is somehow not supported, fallback on
+           using PT_WRITE_D/PT_READ_D.  Otherwise we will return zero
+           to indicate failure.  */
+        if (errno != EINVAL)
+          return 0;
+      }
+    else
+      {
+        /* Return the actual number of bytes read or written.  */
+        return piod.piod_len;
+      }
+  }
+#endif
+
+  /* Allocate buffer of that many longwords.  */
+  if (len < GDB_MAX_ALLOCA)
+    {
+      buffer = (PTRACE_TYPE_RET *) alloca (alloc);
+    }
+  else
+    {
+      buffer = (PTRACE_TYPE_RET *) xmalloc (alloc);
+      old_chain = make_cleanup (xfree, buffer);
+    }
+
+  if (write)
+    {
+      /* Fill start and end extra bytes of buffer with existing memory
+         data.  */
+      if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET))
+        {
+          /* Need part of initial word -- fetch it.  */
+          buffer[0] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
+                              (PTRACE_TYPE_ARG3) addr, 0);
+        }
+
+      if (count > 1)            /* FIXME, avoid if even boundary.  */
+        {
+          buffer[count - 1] =
+            ptrace (PT_READ_I, PIDGET (inferior_ptid),
+                    ((PTRACE_TYPE_ARG3)
+                     (addr + (count - 1) * sizeof (PTRACE_TYPE_RET))), 0);
+        }
+
+      /* Copy data to be written over corresponding part of buffer.  */
+      memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
+              myaddr, len);
+
+      /* Write the entire buffer.  */
+      for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
+        {
+          errno = 0;
+          ptrace (PT_WRITE_D, PIDGET (inferior_ptid),
+                  (PTRACE_TYPE_ARG3) addr, buffer[i]);
+          if (errno)
+            {
+              /* Using the appropriate one (I or D) is necessary for
+                 Gould NP1, at least.  */
+              errno = 0;
+              ptrace (PT_WRITE_I, PIDGET (inferior_ptid),
+                      (PTRACE_TYPE_ARG3) addr, buffer[i]);
+            }
+          if (errno)
+            return 0;
+        }
+    }
+  else
+    {
+      /* Read all the longwords.  */
+      for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
+        {
+          errno = 0;
+          buffer[i] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
+                              (PTRACE_TYPE_ARG3) addr, 0);
+          if (errno)
+            return 0;
+          QUIT;
+        }
+
+      /* Copy appropriate bytes out of the buffer.  */
+      memcpy (myaddr,
+              (char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
+              len);
+    }
+
+  if (old_chain != NULL)
+    do_cleanups (old_chain);
+  return len;
+}
+
+static int
+hpux_thread_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len,
 			 int dowrite, struct mem_attrib *attribs,
 			 struct target_ops *target)
 {
@@ -408,7 +856,7 @@ hpux_thread_xfer_memory (CORE_ADDR memad
   inferior_ptid = main_ptid;
 
   retval = 
-    deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
+    hpux_child_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
 
   do_cleanups (old_chain);
 
@@ -420,13 +868,40 @@ hpux_thread_xfer_memory (CORE_ADDR memad
 static void
 hpux_thread_files_info (struct target_ops *ignore)
 {
-  deprecated_child_ops.to_files_info (ignore);
+  printf_unfiltered (_("\tUsing the running image of %s %s.\n"),
+      attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
+}
+
+/* NOTE: cagney/2004-09-12: Instead of definining this macro, code
+   should call inf_ptrace_target to get a basic ptrace target and then
+   locally update any necessary methods.  See ppcnbsd-nat.c.  */
+
+static void
+hpux_kill_inferior (void)
+{
+  int status;
+  int pid =  PIDGET (inferior_ptid);
+
+  if (pid == 0)
+    return;
+
+  /* This once used to call "kill" to kill the inferior just in case
+     the inferior was still running.  As others have noted in the past
+     (kingdon) there shouldn't be any way to get here if the inferior
+     is still running -- else there's a major problem elsewere in gdb
+     and it needs to be fixed.
+
+     The kill call causes problems under hpux10, so it's been removed;
+     if this causes problems we'll deal with them as they arise.  */
+  ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3) 0, 0);
+  wait (&status);
+  target_mourn_inferior ();
 }
 
 static void
 hpux_thread_kill_inferior (void)
 {
-  deprecated_child_ops.to_kill ();
+  hpux_kill_inferior ();
 }
 
 static void
@@ -435,13 +910,63 @@ hpux_thread_notice_signals (ptid_t ptid)
   deprecated_child_ops.to_notice_signals (ptid);
 }
 
+/* Stub function which causes the inferior that runs it, to be ptrace-able
+   by its parent process.  */
+
+static void
+ptrace_me (void)
+{
+  /* "Trace me, Dr. Memory!" */
+  ptrace (0, 0, (PTRACE_TYPE_ARG3) 0, 0);
+}
+
+/* Stub function which causes the GDB that runs it, to start ptrace-ing
+   the child process.  */
+
+static void
+ptrace_him (int pid)
+{
+  push_target (&deprecated_child_ops);
+
+  /* On some targets, there must be some explicit synchronization
+     between the parent and child processes after the debugger
+     forks, and before the child execs the debuggee program.  This
+     call basically gives permission for the child to exec.
+   */
+
+  target_acknowledge_created_inferior (pid);
+
+  /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h,
+   * and will be 1 or 2 depending on whether we're starting
+   * without or with a shell.
+   */
+  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+
+  /* On some targets, there must be some explicit actions taken after
+     the inferior has been started up.
+   */
+  target_post_startup_inferior (pid_to_ptid (pid));
+}
+
+/* Start an inferior Unix child process and sets inferior_ptid 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().  */
+
+static void
+child_create_inferior (char *exec_file, char *allargs, char **env,
+                       int from_tty)
+{
+  fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, NULL, NULL);
+}
+
 /* Fork an inferior process, and start debugging it with /proc.  */
 
 static void
 hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
 			     int from_tty)
 {
-  deprecated_child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
+  child_create_inferior (exec_file, allargs, env, from_tty);
 
   if (hpux_thread_active)
     {
@@ -505,7 +1030,8 @@ quit:
 static void
 hpux_thread_mourn_inferior (void)
 {
-  deprecated_child_ops.to_mourn_inferior ();
+  unpush_target (&hpux_thread_ops);
+  generic_mourn_inferior ();
 }
 
 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
@@ -522,10 +1048,22 @@ hpux_thread_alive (ptid_t ptid)
   return 1;
 }
 
+/* Send a SIGINT to the process group.  This acts just like the user typed a
+   ^C on the controlling terminal.
+
+   XXX - This may not be correct for all systems.  Some may want to use
+   killpg() instead of kill (-pgrp). */
+
+static void
+child_stop (void)
+{
+  kill (-inferior_process_group, SIGINT);
+}
+
 static void
 hpux_thread_stop (void)
 {
-  deprecated_child_ops.to_stop ();
+  child_stop ();
 }
 
 /* Convert a pid to printable form. */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]