Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Tristan Gingold <gingold@adacore.com>
To: "gdb-patches@sourceware.org ml" <gdb-patches@sourceware.org>
Subject: [RFC] Support of Lion (darwin 11)
Date: Wed, 07 Sep 2011 13:09:00 -0000	[thread overview]
Message-ID: <E9D2564E-6E60-4938-B358-32B2DA122E08@adacore.com> (raw)

Hi,

with the latest mac OS X, executables are now pie by default and their load address is random.  This obviously needs to be considered by gdb, and the easiest method is to disable the randomization.

Contrary to other OS, this is done at exec (i.e. posix_spawn) time.  In order to use posix_spawn instead of exec, I added a parameter to fork_inferior.  But to do that, I first slightly changed the fork_inferior code to always use execvp.  I also did some cleanup in this function:  use alloca instead of xmalloc for argv to avoid a memory leak, and moved the code that allocate shell_command within the if (shell) block.  I also factorized the gdb_flush/_exit code used in case on error.

The remaining of the patch is somewhat trivial: adjusting all the calls of fork_inferior (I preferred to pass NULL instead of execvp, because the prototype of the later is somewhat not universal), and doing the real work for darwin.

No regressions on i386 GNU/Linux,
manually tested on Lion.

Ok for trunk ?

Tristan.

2011-09-07  Tristan Gingold  <gingold@adacore.com>

	* fork-child.c (fork_inferior): Add exec_fun parameter.
	Update comment.  Use alloca instead of xmalloc for argv.  Move
	len and shell_command declarations in the block where they are used.
	Call exec_fun or execvp.  Factorize some failure code.
	* inferior.h: Adjust prototype.
	* gnu-nat.c (gnu_create_inferior): Adjsut fork_inferior call.
	* inf-ttrace.c (inf_ttrace_create_inferior): Ditto.
	* inf-ptrace.c (inf_ptrace_create_inferior): Ditto.
	* procfs.c (procfs_create_inferior): Ditto.
	* darwin-nat.c (darwin_execvp): New function.
	(darwin_create_inferior): Use it.

diff --git a/gdb/fork-child.c b/gdb/fork-child.c
index bb173e7..ce947c4 100644
--- a/gdb/fork-child.c
+++ b/gdb/fork-child.c
@@ -115,6 +115,7 @@ escape_bang_in_quoted_argument (const char *shell_file)
    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.  SHELL_FILE is the shell file, or NULL if we should pick
+   one.  EXEC_FUN is the exec(2) function to use, or NULL for the default
    one.  */
 
 /* This function is NOT reentrant.  Some of the variables have been
@@ -123,12 +124,12 @@ escape_bang_in_quoted_argument (const char *shell_file)
 int
 fork_inferior (char *exec_file_arg, char *allargs, char **env,
 	       void (*traceme_fun) (void), void (*init_trace_fun) (int),
-	       void (*pre_trace_fun) (void), char *shell_file_arg)
+	       void (*pre_trace_fun) (void), char *shell_file_arg,
+               void (*exec_fun)(const char *file, char * const *argv,
+                                char * const *env))
 {
   int pid;
-  char *shell_command;
   static char default_shell_file[] = SHELL_FILE;
-  int len;
   /* 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
@@ -162,16 +163,6 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
       shell = 1;
     }
 
-  /* Multiplying the length of exec_file by 4 is to account for the
-     fact that it may expand when quoted; it is a worst-case number
-     based on every character being '.  */
-  len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;
-  if (exec_wrapper)
-    len += strlen (exec_wrapper) + 1;
-
-  shell_command = (char *) alloca (len);
-  shell_command[0] = '\0';
-
   if (!shell)
     {
       /* We're going to call execvp.  Create argument vector.
@@ -180,18 +171,29 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
 	 argument.  */
       int argc = (strlen (allargs) + 1) / 2 + 2;
 
-      argv = (char **) xmalloc (argc * sizeof (*argv));
+      argv = (char **) alloca (argc * sizeof (*argv));
       argv[0] = exec_file;
       breakup_args (allargs, &argv[1]);
     }
   else
     {
       /* We're going to call a shell.  */
-
+      char *shell_command;
+      int len;
       char *p;
       int need_to_quote;
       const int escape_bang = escape_bang_in_quoted_argument (shell_file);
 
+      /* Multiplying the length of exec_file by 4 is to account for the
+         fact that it may expand when quoted; it is a worst-case number
+         based on every character being '.  */
+      len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;
+      if (exec_wrapper)
+        len += strlen (exec_wrapper) + 1;
+
+      shell_command = (char *) alloca (len);
+      shell_command[0] = '\0';
+
       strcat (shell_command, "exec ");
 
       /* Add any exec wrapper.  That may be a program name with arguments, so
@@ -257,6 +259,16 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
 
       strcat (shell_command, " ");
       strcat (shell_command, allargs);
+
+      /* If we decided above to start up with a shell, we exec the
+	 shell, "-c" says to interpret the next arg as a shell command
+	 to execute, and this command is "exec <target-program>
+	 <args>".  */
+      argv = (char **) alloca (4 * sizeof (char *));
+      argv[0] = shell_file;
+      argv[1] = "-c";
+      argv[2] = shell_command;
+      argv[3] = (char *) 0;
     }
 
   /* On some systems an exec will fail if the executable is open.  */
@@ -348,29 +360,21 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
          path to find $SHELL.  Rich Pixley says so, and I agree.  */
       environ = env;
 
-      /* If we decided above to start up with a shell, we exec the
-	 shell, "-c" says to interpret the next arg as a shell command
-	 to execute, and this command is "exec <target-program>
-	 <args>".  */
+      if (exec_fun != NULL)
+        (*exec_fun) (argv[0], argv, env);
+      else
+        execvp (argv[0], argv);
+
+      /* If we get here, it's an error.  */
       if (shell)
 	{
-	  execlp (shell_file, shell_file, "-c", shell_command, (char *) 0);
-
-	  /* If we get here, it's an error.  */
 	  fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file,
 			      safe_strerror (errno));
-	  gdb_flush (gdb_stderr);
-	  _exit (0177);
 	}
       else
 	{
-	  /* Otherwise, we directly exec the target program with
-	     execvp.  */
 	  int i;
 
-	  execvp (exec_file, argv);
-
-	  /* If we get here, it's an error.  */
 	  safe_strerror (errno);
 	  fprintf_unfiltered (gdb_stderr, "Cannot exec %s ", exec_file);
 
@@ -383,9 +387,9 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
 	      i++;
 	    }
 	  fprintf_unfiltered (gdb_stderr, ".\n");
-	  gdb_flush (gdb_stderr);
-	  _exit (0177);
 	}
+      gdb_flush (gdb_stderr);
+      _exit (0177);
     }
 
   /* Restore our environment in case a vforked child clob'd it.  */
diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c
index 7269694..32f78be 100644
--- a/gdb/gnu-nat.c
+++ b/gdb/gnu-nat.c
@@ -2114,7 +2114,8 @@ gnu_create_inferior (struct target_ops *ops,
 
   inf_debug (inf, "creating inferior");
 
-  pid = fork_inferior (exec_file, allargs, env, trace_me, NULL, NULL, NULL);
+  pid = fork_inferior (exec_file, allargs, env, trace_me,
+                       NULL, NULL, NULL, NULL);
 
   /* Attach to the now stopped child, which is actually a shell...  */
   inf_debug (inf, "attaching to child: %d", pid);
diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c
index b5e1744..110e825 100644
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -134,7 +134,7 @@ inf_ptrace_create_inferior (struct target_ops *ops,
     }
 
   pid = fork_inferior (exec_file, allargs, env, inf_ptrace_me, NULL,
-		       NULL, NULL);
+		       NULL, NULL, NULL);
 
   if (! ops_already_pushed)
     discard_cleanups (back_to);
diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c
index ab075db..0ab6580 100644
--- a/gdb/inf-ttrace.c
+++ b/gdb/inf-ttrace.c
@@ -650,7 +650,7 @@ inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file,
   gdb_assert (inf_ttrace_vfork_ppid == -1);
 
   pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL,
-		       inf_ttrace_prepare, NULL);
+		       inf_ttrace_prepare, NULL, NULL);
 
   inf_ttrace_him (ops, pid);
 }
diff --git a/gdb/inferior.h b/gdb/inferior.h
index cf747a6..f5794fe 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -189,7 +189,9 @@ extern void terminal_init_inferior_with_pgrp (int pgrp);
 
 extern int fork_inferior (char *, char *, char **,
 			  void (*)(void),
-			  void (*)(int), void (*)(void), char *);
+			  void (*)(int), void (*)(void), char *,
+                          void (*)(const char *,
+                                   char * const *, char * const *));
 
 
 extern void startup_inferior (int);
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 917e122..871dd47 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -4915,7 +4915,7 @@ procfs_create_inferior (struct target_ops *ops, char *exec_file,
     }
 
   pid = fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
-		       NULL, NULL, shell_file);
+		       NULL, NULL, shell_file, NULL);
 
   procfs_init_inferior (ops, pid);
 }
diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c
index 06a1558..4e5eb42 100644
--- a/gdb/darwin-nat.c
+++ b/gdb/darwin-nat.c
@@ -53,6 +53,7 @@
 #include <sys/proc.h>
 #include <libproc.h>
 #include <sys/syscall.h>
+#include <spawn.h>
 
 #include <mach/mach_error.h>
 #include <mach/mach_vm.h>
@@ -1507,12 +1508,47 @@ darwin_ptrace_him (int pid)
 }
 
 static void
+darwin_execvp (const char *file, char * const argv[], char * const env[])
+{
+  posix_spawnattr_t attr;
+  short flags;
+  int retval;
+
+  retval = posix_spawnattr_init (&attr);
+  if (retval != 0)
+    {
+      warning ("Couldn't initialize attributes for posix_spawn, error: %d",
+               retval);
+      return;
+    }
+
+  /* Do like execve: replace the image.  */
+  flags = POSIX_SPAWN_SETEXEC;
+
+  /* Disable ASLR.  The constant doesn't look to be available outside the
+     kernel include files.  */
+#ifndef _POSIX_SPAWN_DISABLE_ASLR
+#define _POSIX_SPAWN_DISABLE_ASLR	0x0100
+#endif
+  flags |= _POSIX_SPAWN_DISABLE_ASLR;
+  retval = posix_spawnattr_setflags (&attr, flags);
+  if (retval != 0)
+    {
+      warning ("Couldn't set the posix_spawn flags, error: %d",
+               retval);
+      return;
+    }
+
+  posix_spawnp (NULL, argv[0], NULL, &attr, argv, env);
+}
+
+static void
 darwin_create_inferior (struct target_ops *ops, char *exec_file,
 			char *allargs, char **env, int from_tty)
 {
   /* Do the hard work.  */
   fork_inferior (exec_file, allargs, env, darwin_ptrace_me, darwin_ptrace_him,
-		 darwin_pre_ptrace, NULL);
+		 darwin_pre_ptrace, NULL, darwin_execvp);
 
   /* Return now in case of error.  */
   if (ptid_equal (inferior_ptid, null_ptid))


             reply	other threads:[~2011-09-07 12:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-07 13:09 Tristan Gingold [this message]
2011-09-07 13:14 ` Pedro Alves
2011-09-07 13:28   ` Pedro Alves
2011-09-07 13:47   ` Tristan Gingold
2011-09-16 13:20   ` [RFA] Preliminary work in fork_inferior Tristan Gingold
2011-09-16 14:38     ` Pedro Alves
2011-09-16 14:52       ` Tristan Gingold
2011-09-16 15:28         ` Pedro Alves
2011-09-16 18:25           ` Tristan Gingold
2011-09-16 14:47     ` Abhijit Halder
2011-09-16 14:55       ` Tristan Gingold

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E9D2564E-6E60-4938-B358-32B2DA122E08@adacore.com \
    --to=gingold@adacore.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox