From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29898 invoked by alias); 7 Sep 2011 12:29:11 -0000 Received: (qmail 29885 invoked by uid 22791); 7 Sep 2011 12:29:08 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL,BAYES_00,TW_CL,TW_RG X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (194.98.77.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 07 Sep 2011 12:28:53 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 19E15CB02B5 for ; Wed, 7 Sep 2011 14:28:54 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CotbMulFTHB2 for ; Wed, 7 Sep 2011 14:28:43 +0200 (CEST) Received: from ulanbator.act-europe.fr (ulanbator.act-europe.fr [10.10.1.67]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id C879FCB0232 for ; Wed, 7 Sep 2011 14:28:43 +0200 (CEST) From: Tristan Gingold Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Subject: [RFC] Support of Lion (darwin 11) Date: Wed, 07 Sep 2011 13:09:00 -0000 Message-Id: To: "gdb-patches@sourceware.org ml" Mime-Version: 1.0 (Apple Message framework v1244.3) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-09/txt/msg00116.txt.bz2 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 ord= er 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 alway= s use execvp. I also did some cleanup in this function: use alloca instea= d of xmalloc for argv to avoid a memory leak, and moved the code that alloc= ate shell_command within the if (shell) block. I also factorized the gdb_f= lush/_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 prot= otype 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 * 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. */ =20 /* This function is NOT reentrant. Some of the variables have been @@ -123,12 +124,12 @@ escape_bang_in_quoted_argument (const char *shell_fil= e) 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[] =3D SHELL_FILE; - int len; /* Set debug_fork then attach to the child while it sleeps, to debug. */ static int debug_fork =3D 0; /* This is set to the result of setpgrp, which if vforked, will be visib= le @@ -162,16 +163,6 @@ fork_inferior (char *exec_file_arg, char *allargs, cha= r **env, shell =3D 1; } =20 - /* 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 =3D 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop *= / 12; - if (exec_wrapper) - len +=3D strlen (exec_wrapper) + 1; - - shell_command =3D (char *) alloca (len); - shell_command[0] =3D '\0'; - if (!shell) { /* We're going to call execvp. Create argument vector. @@ -180,18 +171,29 @@ fork_inferior (char *exec_file_arg, char *allargs, ch= ar **env, argument. */ int argc =3D (strlen (allargs) + 1) / 2 + 2; =20 - argv =3D (char **) xmalloc (argc * sizeof (*argv)); + argv =3D (char **) alloca (argc * sizeof (*argv)); argv[0] =3D 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 =3D escape_bang_in_quoted_argument (shell_file= ); =20 + /* 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 =3D 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*sl= op */ 12; + if (exec_wrapper) + len +=3D strlen (exec_wrapper) + 1; + + shell_command =3D (char *) alloca (len); + shell_command[0] =3D '\0'; + strcat (shell_command, "exec "); =20 /* 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, cha= r **env, =20 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 + ". */ + argv =3D (char **) alloca (4 * sizeof (char *)); + argv[0] =3D shell_file; + argv[1] =3D "-c"; + argv[2] =3D shell_command; + argv[3] =3D (char *) 0; } =20 /* On some systems an exec will fail if the executable is open. */ @@ -348,29 +360,21 @@ fork_inferior (char *exec_file_arg, char *allargs, ch= ar **env, path to find $SHELL. Rich Pixley says so, and I agree. */ environ =3D env; =20 - /* 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 - ". */ + if (exec_fun !=3D 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; =20 - execvp (exec_file, argv); - - /* If we get here, it's an error. */ safe_strerror (errno); fprintf_unfiltered (gdb_stderr, "Cannot exec %s ", exec_file); =20 @@ -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); } =20 /* 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, =20 inf_debug (inf, "creating inferior"); =20 - pid =3D fork_inferior (exec_file, allargs, env, trace_me, NULL, NULL, NU= LL); + pid =3D fork_inferior (exec_file, allargs, env, trace_me, + NULL, NULL, NULL, NULL); =20 /* 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, } =20 pid =3D fork_inferior (exec_file, allargs, env, inf_ptrace_me, NULL, - NULL, NULL); + NULL, NULL, NULL); =20 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, cha= r *exec_file, gdb_assert (inf_ttrace_vfork_ppid =3D=3D -1); =20 pid =3D fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL, - inf_ttrace_prepare, NULL); + inf_ttrace_prepare, NULL, NULL); =20 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); =20 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 *)); =20 =20 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, } =20 pid =3D fork_inferior (exec_file, allargs, env, procfs_set_exec_trap, - NULL, NULL, shell_file); + NULL, NULL, shell_file, NULL); =20 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 #include #include +#include =20 #include #include @@ -1507,12 +1508,47 @@ darwin_ptrace_him (int pid) } =20 static void +darwin_execvp (const char *file, char * const argv[], char * const env[]) +{ + posix_spawnattr_t attr; + short flags; + int retval; + + retval =3D posix_spawnattr_init (&attr); + if (retval !=3D 0) + { + warning ("Couldn't initialize attributes for posix_spawn, error: %d", + retval); + return; + } + + /* Do like execve: replace the image. */ + flags =3D 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 |=3D _POSIX_SPAWN_DISABLE_ASLR; + retval =3D posix_spawnattr_setflags (&attr, flags); + if (retval !=3D 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); =20 /* Return now in case of error. */ if (ptid_equal (inferior_ptid, null_ptid))