[rfc,v2,rfa-doc] Disable address space randomization with remote targets

Message ID 201110051832.p95IWuVb029968@d06av02.portsmouth.uk.ibm.com
State Accepted
Headers show

Commit Message

Ulrich Weigand Oct. 5, 2011, 6:32 p.m.
Pedro Alves wrote:
> On Friday 30 September 2011 14:17:08, Ulrich Weigand wrote:
> 
> > As to the remote command for extended mode, I'm not completely sure what
> > the best way to trigger that from within GDB should be.  Should we promote
> > "set disable-randomization" from being a Linux-specific command to the
> > generic level, and have its value passed to the target by remote.c?
> 
> Yes.  This came up recently for (native) Darwin/OSX too.  That target now
> always  disables ASR, and it'd be good to give the user the option
> to re-enable it.
> 
> >  Or else a new QDisableRandomization packet that affects all subsequent
> >  vRun commands?
> 
> I think that's the best.  It's kind of similar to "set disconnected-tracing"
> and "set circular-trace-buffer".

The following patch implements support along these lines.  Does this
look reasonable?

Tested on i386-linux.

Bye,
Ulrich


ChangeLog:

	* inferior.h (disable_randomization): Declare.
	* infrun.c (disable_randomization): New global variable.
	(show_disable_randomization): New function.
	(set_disable_randomization): Likewise.
	(_initialize_infrun): Install set/show disable-randomization
	commands.
	* linux-nat.c (disable_randomization): Remove.
	(show_disable_randomization): Likewise.
	(set_disable_randomization): Likewise.
	(_initialize_linux_nat): No longer install set/show
	disable-randomization commands here.
	(linux_nat_supports_disable_randomization): New function.
	(linux_nat_add_target): Install it.
	* remote.c (PACKET_QDisableRandomization): New enum value.
	(remote_protocol_packets): Support QDisableRandomization.
	(_initialize_remote): Likewise.
	(remote_supports_disable_randomization): New function.
	(init_remote_ops): Install it.
	(extended_remote_supports_disable_randomization): New function.
	(init_extended_remote_ops): Install it.
	(extended_remote_disable_randomization): New function.
	(extended_remote_create_inferior_1): Call it.
	* target.h (struct target_ops): Add to_supports_disable_randomization.
	(target_supports_disable_randomization): Add prototype.
	* target.c (target_supports_disable_randomization): New function.
	(find_default_supports_disable_randomization): Likewise.
	(init_dummy_target): Install it.

doc/
	* gdb.texinfo (Starting your Program): "set disable-randomization"
	is no longer Linux-specific.
	(Remote Configuration): Document "set remote
	disable-randomization-packet".
	(General Query Packets): Document "QDisableRandomization" packet
	and add it to "qSupported" list.

gdbserver/
	* configure.ac: Check support for personality routine.
	* configure: Regenerate.
	* config.in: Likewise.
	* linux-low.c: Include <sys/personality.h>.
	Define ADDR_NO_RANDOMIZE if necessary.
	(linux_create_inferior): Disable address space randomization when
	forking inferior, if requested.
	(linux_supports_disable_randomization): New function.
	(linux_target_ops): Install it.
	* server.h (disable_randomization): Declare.
	* server.c (disable_randomization): New global variable.
	(handle_general_set): Handle QDisableRandomization.
	(handle_query): Likewise for qSupported.
	(main): Support --disable-randomization and --no-disable-randomization
	command line arguments.
	* target.h (struct target_ops): Add supports_disable_randomization.
	(target_supports_disable_randomization): New macro.

Comments

Eli Zaretskii Oct. 5, 2011, 6:43 p.m. | #1
> Date: Wed, 5 Oct 2011 20:32:56 +0200 (CEST)
> From: "Ulrich Weigand" <uweigand@de.ibm.com>
> Cc: gdb-patches@sourceware.org, jan.kratochvil@redhat.com (Jan Kratochvil),        patches@linaro.org
> 
> -The virtual address space randomization is implemented only on @sc{gnu}/Linux.
> -It protects the programs against some kinds of security attacks.  In these
> +On targets where it is available, virtual address space randomization
> +protects the programs against some kinds of security attacks.  In these
                                 ^^^^^^^^^^
"certain kinds"

> +Some target operating systems will randomize the inferior process'
> +virtual address space as a security feature, but provide a feature

It is better to say "randomize the virtual address space of the
inferior process", then you won't have the "issue" with "ss's".

> +to disable such randomization, e.g. to allow for a more deterministic
                                  ^^^^
"e.g.@:", to hint TeX not to typeset this as an end of a sentence.

The documentation part is okay with these changes.
Tom Tromey Oct. 5, 2011, 8:10 p.m. | #2
>>>>> "Ulrich" == Ulrich Weigand <uweigand@de.ibm.com> writes:

Ulrich> The following patch implements support along these lines.  Does this
Ulrich> look reasonable?

FWIW, I read through the patch, and I didn't see any red flags.

Tom
Pedro Alves Oct. 6, 2011, 1:25 p.m. | #3
On Wednesday 05 October 2011 19:32:56, Ulrich Weigand wrote:

> The following patch implements support along these lines.  Does this
> look reasonable?

It does, thanks.

Patch

Index: gdb/inferior.h
===================================================================
RCS file: /cvs/src/src/gdb/inferior.h,v
retrieving revision 1.163
diff -u -p -r1.163 inferior.h
--- gdb/inferior.h	22 Sep 2011 10:22:28 -0000	1.163
+++ gdb/inferior.h	5 Oct 2011 17:18:15 -0000
@@ -124,6 +124,10 @@  extern int non_stop;
    detached depends on 'set follow-fork-mode' setting.  */
 extern int detach_fork;
 
+/* When set (default), the target should attempt to disable the operating
+   system's address space randomization feature when starting an inferior.  */
+extern int disable_randomization;
+
 extern void generic_mourn_inferior (void);
 
 extern void terminal_save_ours (void);
Index: gdb/infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.507
diff -u -p -r1.507 infrun.c
--- gdb/infrun.c	22 Sep 2011 02:58:31 -0000	1.507
+++ gdb/infrun.c	5 Oct 2011 17:18:17 -0000
@@ -147,6 +147,37 @@  show_debug_infrun (struct ui_file *file,
   fprintf_filtered (file, _("Inferior debugging is %s.\n"), value);
 }
 
+
+/* Support for disabling address space randomization.  */
+
+int disable_randomization = 1;
+
+static void
+show_disable_randomization (struct ui_file *file, int from_tty,
+			    struct cmd_list_element *c, const char *value)
+{
+  if (target_supports_disable_randomization ())
+    fprintf_filtered (file,
+		      _("Disabling randomization of debuggee's "
+			"virtual address space is %s.\n"),
+		      value);
+  else
+    fputs_filtered (_("Disabling randomization of debuggee's "
+		      "virtual address space is unsupported on\n"
+		      "this platform.\n"), file);
+}
+
+static void
+set_disable_randomization (char *args, int from_tty,
+			   struct cmd_list_element *c)
+{
+  if (!target_supports_disable_randomization ())
+    error (_("Disabling randomization of debuggee's "
+	     "virtual address space is unsupported on\n"
+	     "this platform."));
+}
+
+
 /* If the program uses ELF-style shared libraries, then calls to
    functions in shared libraries go through stubs, which live in a
    table called the PLT (Procedure Linkage Table).  The first time the
@@ -7232,6 +7263,19 @@  Show whether gdb will detach the child o
 Tells gdb whether to detach the child of a fork."),
 			   NULL, NULL, &setlist, &showlist);
 
+  /* Set/show disable address space randomization mode.  */
+
+  add_setshow_boolean_cmd ("disable-randomization", class_support,
+			   &disable_randomization, _("\
+Set disabling of debuggee's virtual address space randomization."), _("\
+Show disabling of debuggee's virtual address space randomization."), _("\
+When this mode is on (which is the default), randomization of the virtual\n\
+address space is disabled.  Standalone programs run with the randomization\n\
+enabled by default on some platforms."),
+			   &set_disable_randomization,
+			   &show_disable_randomization,
+			   &setlist, &showlist);
+
   /* ptid initializations */
   inferior_ptid = null_ptid;
   target_last_wait_ptid = minus_one_ptid;
Index: gdb/linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-nat.c,v
retrieving revision 1.215
diff -u -p -r1.215 linux-nat.c
--- gdb/linux-nat.c	9 Sep 2011 19:27:50 -0000	1.215
+++ gdb/linux-nat.c	5 Oct 2011 17:18:18 -0000
@@ -200,35 +200,6 @@  show_debug_linux_nat (struct ui_file *fi
 		    value);
 }
 
-static int disable_randomization = 1;
-
-static void
-show_disable_randomization (struct ui_file *file, int from_tty,
-			    struct cmd_list_element *c, const char *value)
-{
-#ifdef HAVE_PERSONALITY
-  fprintf_filtered (file,
-		    _("Disabling randomization of debuggee's "
-		      "virtual address space is %s.\n"),
-		    value);
-#else /* !HAVE_PERSONALITY */
-  fputs_filtered (_("Disabling randomization of debuggee's "
-		    "virtual address space is unsupported on\n"
-		    "this platform.\n"), file);
-#endif /* !HAVE_PERSONALITY */
-}
-
-static void
-set_disable_randomization (char *args, int from_tty,
-			   struct cmd_list_element *c)
-{
-#ifndef HAVE_PERSONALITY
-  error (_("Disabling randomization of debuggee's "
-	   "virtual address space is unsupported on\n"
-	   "this platform."));
-#endif /* !HAVE_PERSONALITY */
-}
-
 struct simple_pid_list
 {
   int pid;
@@ -5308,6 +5279,16 @@  linux_nat_supports_multi_process (void)
   return linux_multi_process;
 }
 
+static int
+linux_nat_supports_disable_randomization (void)
+{
+#ifdef HAVE_PERSONALITY
+  return 1;
+#else
+  return 0;
+#endif
+}
+
 static int async_terminal_is_ours = 1;
 
 /* target_terminal_inferior implementation.  */
@@ -5677,6 +5658,9 @@  linux_nat_add_target (struct target_ops 
 
   t->to_supports_multi_process = linux_nat_supports_multi_process;
 
+  t->to_supports_disable_randomization
+    = linux_nat_supports_disable_randomization;
+
   t->to_core_of_thread = linux_nat_core_of_thread;
 
   /* We don't change the stratum; this target will sit at
@@ -5762,17 +5746,6 @@  Enables printf debugging output."),
   sigdelset (&suspend_mask, SIGCHLD);
 
   sigemptyset (&blocked_mask);
-
-  add_setshow_boolean_cmd ("disable-randomization", class_support,
-			   &disable_randomization, _("\
-Set disabling of debuggee's virtual address space randomization."), _("\
-Show disabling of debuggee's virtual address space randomization."), _("\
-When this mode is on (which is the default), randomization of the virtual\n\
-address space is disabled.  Standalone programs run with the randomization\n\
-enabled by default on some platforms."),
-			   &set_disable_randomization,
-			   &show_disable_randomization,
-			   &setlist, &showlist);
 }
 
 
Index: gdb/remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.463
diff -u -p -r1.463 remote.c
--- gdb/remote.c	14 Sep 2011 12:26:29 -0000	1.463
+++ gdb/remote.c	5 Oct 2011 17:18:19 -0000
@@ -1263,6 +1263,7 @@  enum {
   PACKET_TracepointSource,
   PACKET_QAllow,
   PACKET_qXfer_fdpic,
+  PACKET_QDisableRandomization,
   PACKET_MAX
 };
 
@@ -3761,6 +3762,8 @@  static struct protocol_feature remote_pr
     remote_enable_disable_tracepoint_feature, -1 },
   { "qXfer:fdpic:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_fdpic },
+  { "QDisableRandomization", PACKET_DISABLE, remote_supported_packet,
+    PACKET_QDisableRandomization },
 };
 
 static char *remote_support_xml;
@@ -7484,6 +7487,28 @@  extended_remote_mourn (struct target_ops
 }
 
 static int
+extended_remote_supports_disable_randomization (void)
+{
+  return (remote_protocol_packets[PACKET_QDisableRandomization].support
+	  == PACKET_ENABLE);
+}
+
+static void
+extended_remote_disable_randomization (int val)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *reply;
+
+  sprintf (rs->buf, "QDisableRandomization:%x", val);
+  putpkt (rs->buf);
+  reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
+  if (*reply == '\0')
+    error (_("Target does not support QDisableRandomization."));
+  if (strcmp (reply, "OK") != 0)
+    error (_("Bogus QDisableRandomization reply from target: %s"), reply);
+}
+
+static int
 extended_remote_run (char *args)
 {
   struct remote_state *rs = get_remote_state ();
@@ -7559,6 +7584,10 @@  extended_remote_create_inferior_1 (char 
   if (target_can_async_p ())
     target_async (inferior_event_handler, 0);
 
+  /* Disable address space randomization if requested (and supported).  */
+  if (extended_remote_supports_disable_randomization ())
+    extended_remote_disable_randomization (disable_randomization);
+
   /* Now restart the remote server.  */
   if (extended_remote_run (args) == -1)
     {
@@ -9665,6 +9694,13 @@  remote_supports_non_stop (void)
 }
 
 static int
+remote_supports_disable_randomization (void)
+{
+  /* Only supported in extended mode.  */
+  return 0;
+}
+
+static int
 remote_supports_multi_process (void)
 {
   struct remote_state *rs = get_remote_state ();
@@ -10420,6 +10456,8 @@  Specify the serial device it is connecte
   remote_ops.to_terminal_ours = remote_terminal_ours;
   remote_ops.to_supports_non_stop = remote_supports_non_stop;
   remote_ops.to_supports_multi_process = remote_supports_multi_process;
+  remote_ops.to_supports_disable_randomization
+    = remote_supports_disable_randomization;
   remote_ops.to_supports_enable_disable_tracepoint = remote_supports_enable_disable_tracepoint;
   remote_ops.to_trace_init = remote_trace_init;
   remote_ops.to_download_tracepoint = remote_download_tracepoint;
@@ -10472,6 +10510,8 @@  Specify the serial device it is connecte
   extended_remote_ops.to_detach = extended_remote_detach;
   extended_remote_ops.to_attach = extended_remote_attach;
   extended_remote_ops.to_kill = extended_remote_kill;
+  extended_remote_ops.to_supports_disable_randomization
+    = extended_remote_supports_disable_randomization;
 }
 
 static int
@@ -10944,6 +10984,9 @@  Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_fdpic],
 			 "qXfer:fdpic:read", "read-fdpic-loadmap", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_QDisableRandomization],
+			 "QDisableRandomization", "disable-randomization", 0);
+
   /* Keep the old ``set remote Z-packet ...'' working.  Each individual
      Z sub-packet has its own set and show commands, but users may
      have sets to this variable in their .gdbinit files (or in their
Index: gdb/target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.285
diff -u -p -r1.285 target.c
--- gdb/target.c	6 Jun 2011 12:47:07 -0000	1.285
+++ gdb/target.c	5 Oct 2011 17:18:20 -0000
@@ -3013,6 +3013,28 @@  target_supports_non_stop (void)
   return 0;
 }
 
+static int
+find_default_supports_disable_randomization (void)
+{
+  struct target_ops *t;
+
+  t = find_default_run_target (NULL);
+  if (t && t->to_supports_disable_randomization)
+    return (t->to_supports_disable_randomization) ();
+  return 0;
+}
+
+int
+target_supports_disable_randomization (void)
+{
+  struct target_ops *t;
+
+  for (t = &current_target; t != NULL; t = t->beneath)
+    if (t->to_supports_disable_randomization)
+      return t->to_supports_disable_randomization ();
+
+  return 0;
+}
 
 char *
 target_get_osdata (const char *type)
@@ -3257,6 +3279,8 @@  init_dummy_target (void)
   dummy_target.to_can_async_p = find_default_can_async_p;
   dummy_target.to_is_async_p = find_default_is_async_p;
   dummy_target.to_supports_non_stop = find_default_supports_non_stop;
+  dummy_target.to_supports_disable_randomization
+    = find_default_supports_disable_randomization;
   dummy_target.to_pid_to_str = dummy_pid_to_str;
   dummy_target.to_stratum = dummy_stratum;
   dummy_target.to_find_memory_regions = dummy_find_memory_regions;
Index: gdb/target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.212
diff -u -p -r1.212 target.h
--- gdb/target.h	27 Sep 2011 15:30:18 -0000	1.212
+++ gdb/target.h	5 Oct 2011 17:18:20 -0000
@@ -653,6 +653,9 @@  struct target_ops
        experiment is running?  */
     int (*to_supports_enable_disable_tracepoint) (void);
 
+    /* Does this target support disabling address space randomization?  */
+    int (*to_supports_disable_randomization) (void);
+
     /* Determine current architecture of thread PTID.
 
        The target is supposed to determine the architecture of the code where
@@ -888,6 +891,10 @@  struct address_space *target_thread_addr
 #define	target_supports_multi_process()	\
      (*current_target.to_supports_multi_process) ()
 
+/* Returns true if this target can disable address space randomization.  */
+
+int target_supports_disable_randomization (void);
+
 /* Returns true if this target can enable and disable tracepoints
    while a trace experiment is running.  */
 
Index: gdb/doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.868
diff -u -p -r1.868 gdb.texinfo
--- gdb/doc/gdb.texinfo	4 Oct 2011 08:04:11 -0000	1.868
+++ gdb/doc/gdb.texinfo	5 Oct 2011 17:18:27 -0000
@@ -2044,8 +2044,8 @@  randomization of the virtual address spa
 is useful for multiple debugging sessions to make the execution better
 reproducible and memory addresses reusable across debugging sessions.
 
-This feature is implemented only on @sc{gnu}/Linux.  You can get the same
-behavior using
+This feature is implemented only on certain targets, including @sc{gnu}/Linux.
+On @sc{gnu}/Linux you can get the same behavior using
 
 @smallexample
 (@value{GDBP}) set exec-wrapper setarch `uname -m` -R
@@ -2059,8 +2059,8 @@  disappears when you run the program unde
 as @sc{gnu}/Linux, which do that for stand-alone programs.  Use @kbd{set
 disable-randomization off} to try to reproduce such elusive bugs.
 
-The virtual address space randomization is implemented only on @sc{gnu}/Linux.
-It protects the programs against some kinds of security attacks.  In these
+On targets where it is available, virtual address space randomization
+protects the programs against some kinds of security attacks.  In these
 cases the attacker needs to know the exact location of a concrete executable
 code.  Randomizing its location makes it impossible to inject jumps misusing
 a code at its expected addresses.
@@ -16906,6 +16906,10 @@  are:
 @item @code{traceframe-info}
 @tab @code{qXfer:traceframe-info:read}
 @tab Traceframe info
+
+@item @code{disable-randomization}
+@tab @code{QDisableRandomization}
+@tab @code{set disable-randomization}
 @end multitable
 
 @node Remote Stub
@@ -33523,6 +33527,38 @@  An error (such as memory fault)
 The specified memory region's checksum is @var{crc32}.
 @end table
 
+@item QDisableRandomization:@var{value}
+@cindex disable address space randomization, remote request
+@cindex @samp{QDisableRandomization} packet
+Some target operating systems will randomize the inferior process'
+virtual address space as a security feature, but provide a feature
+to disable such randomization, e.g. to allow for a more deterministic
+debugging experience.  On such systems, this packet with a @var{value}
+of 1 directs the target to disable address space randomization for
+processes subsequently started via @samp{vRun} packets, while a packet
+with a @var{value} of 0 tells the target to enable address space
+randomization.
+
+This packet is only available in extended mode (@pxref{extended mode}).
+
+Reply:
+@table @samp
+@item OK
+The request succeeded.
+
+@item E @var{nn}
+An error occurred.  @var{nn} are hex digits.
+
+@item
+An empty reply indicates that @samp{QDisableRandomization} is not supported
+by the stub.
+@end table
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+This should only be done on targets that actually support disabling
+address space randomization.
+
 @item qfThreadInfo
 @itemx qsThreadInfo
 @cindex list active threads, remote request
@@ -34026,6 +34062,11 @@  These are the currently defined stub fea
 @tab @samp{-}
 @tab No
 
+@item @samp{QDisableRandomization}
+@tab No
+@tab @samp{-}
+@tab No
+
 @item @samp{EnableDisableTracepoints}
 @tab No
 @tab @samp{-}
@@ -34143,6 +34184,9 @@  the source form of tracepoint definition
 @item QAllow
 The remote stub understands the @samp{QAllow} packet.
 
+@item QDisableRandomization
+The remote stub understands the @samp{QDisableRandomization} packet.
+
 @item StaticTracepoint
 @cindex static tracepoints, in remote protocol
 The remote stub supports static tracepoints.
Index: gdb/gdbserver/config.in
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/config.in,v
retrieving revision 1.32
diff -u -p -r1.32 config.in
--- gdb/gdbserver/config.in	21 Jul 2011 23:46:12 -0000	1.32
+++ gdb/gdbserver/config.in	5 Oct 2011 17:18:27 -0000
@@ -18,6 +18,10 @@ 
 /* Define to 1 if you have the <arpa/inet.h> header file. */
 #undef HAVE_ARPA_INET_H
 
+/* Define to 1 if you have the declaration of `ADDR_NO_RANDOMIZE', and to 0 if
+   you don't. */
+#undef HAVE_DECL_ADDR_NO_RANDOMIZE
+
 /* Define to 1 if you have the declaration of `memmem', and to 0 if you don't.
    */
 #undef HAVE_DECL_MEMMEM
@@ -96,6 +100,9 @@ 
 /* Define to 1 if you have the <netinet/tcp.h> header file. */
 #undef HAVE_NETINET_TCP_H
 
+/* Define if you support the personality syscall. */
+#undef HAVE_PERSONALITY
+
 /* Define to 1 if you have the `pread' function. */
 #undef HAVE_PREAD
 
Index: gdb/gdbserver/configure
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/configure,v
retrieving revision 1.60
diff -u -p -r1.60 configure
--- gdb/gdbserver/configure	21 Jul 2011 23:46:12 -0000	1.60
+++ gdb/gdbserver/configure	5 Oct 2011 17:18:28 -0000
@@ -5066,6 +5066,80 @@  fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 CFLAGS="$saved_cflags"
 
+ac_fn_c_check_decl "$LINENO" "ADDR_NO_RANDOMIZE" "ac_cv_have_decl_ADDR_NO_RANDOMIZE" "#include <sys/personality.h>
+"
+if test "x$ac_cv_have_decl_ADDR_NO_RANDOMIZE" = x""yes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_ADDR_NO_RANDOMIZE $ac_have_decl
+_ACEOF
+
+
+if test "$cross_compiling" = yes; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/personality.h>
+int
+main ()
+{
+
+#      if !HAVE_DECL_ADDR_NO_RANDOMIZE
+#       define ADDR_NO_RANDOMIZE 0x0040000
+#      endif
+       /* Test the flag could be set and stays set.  */
+       personality (personality (0xffffffff) | ADDR_NO_RANDOMIZE);
+       if (!(personality (personality (0xffffffff)) & ADDR_NO_RANDOMIZE))
+           return 1
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  gdbsrv_cv_have_personality=true
+else
+  gdbsrv_cv_have_personality=false
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/personality.h>
+int
+main ()
+{
+
+#      if !HAVE_DECL_ADDR_NO_RANDOMIZE
+#       define ADDR_NO_RANDOMIZE 0x0040000
+#      endif
+       /* Test the flag could be set and stays set.  */
+       personality (personality (0xffffffff) | ADDR_NO_RANDOMIZE);
+       if (!(personality (personality (0xffffffff)) & ADDR_NO_RANDOMIZE))
+           return 1
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  gdbsrv_cv_have_personality=true
+else
+  gdbsrv_cv_have_personality=false
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+if $gdbsrv_cv_have_personality
+then
+
+$as_echo "#define HAVE_PERSONALITY 1" >>confdefs.h
+
+fi
+
 
 IPA_DEPFILES=""
 extra_libraries=""
Index: gdb/gdbserver/configure.ac
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/configure.ac,v
retrieving revision 1.47
diff -u -p -r1.47 configure.ac
--- gdb/gdbserver/configure.ac	21 Jul 2011 23:46:12 -0000	1.47
+++ gdb/gdbserver/configure.ac	5 Oct 2011 17:18:28 -0000
@@ -358,6 +358,29 @@  AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]),
 	        	[gdbsrv_cv_have_visibility_hidden=no])
 CFLAGS="$saved_cflags"
 
+dnl Check if we can disable the virtual address space randomization.
+dnl The functionality of setarch -R.
+AC_CHECK_DECLS([ADDR_NO_RANDOMIZE],,, [#include <sys/personality.h>])
+define([PERSONALITY_TEST], [AC_LANG_PROGRAM([#include <sys/personality.h>], [
+#      if !HAVE_DECL_ADDR_NO_RANDOMIZE
+#       define ADDR_NO_RANDOMIZE 0x0040000
+#      endif
+       /* Test the flag could be set and stays set.  */
+       personality (personality (0xffffffff) | ADDR_NO_RANDOMIZE);
+       if (!(personality (personality (0xffffffff)) & ADDR_NO_RANDOMIZE))
+           return 1])])
+AC_RUN_IFELSE([PERSONALITY_TEST],
+              [gdbsrv_cv_have_personality=true],
+              [gdbsrv_cv_have_personality=false],
+              [AC_LINK_IFELSE([PERSONALITY_TEST],
+                              [gdbsrv_cv_have_personality=true],
+                              [gdbsrv_cv_have_personality=false])])
+if $gdbsrv_cv_have_personality
+then
+    AC_DEFINE([HAVE_PERSONALITY], 1,
+              [Define if you support the personality syscall.])
+fi
+
 
 IPA_DEPFILES=""
 extra_libraries=""
Index: gdb/gdbserver/linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.177
diff -u -p -r1.177 linux-low.c
--- gdb/gdbserver/linux-low.c	30 Sep 2011 00:01:59 -0000	1.177
+++ gdb/gdbserver/linux-low.c	5 Oct 2011 17:18:29 -0000
@@ -55,6 +55,13 @@ 
 #define SPUFS_MAGIC 0x23c9b64e
 #endif
 
+#ifdef HAVE_PERSONALITY
+# include <sys/personality.h>
+# if !HAVE_DECL_ADDR_NO_RANDOMIZE
+#  define ADDR_NO_RANDOMIZE 0x0040000
+# endif
+#endif
+
 #ifndef O_LARGEFILE
 #define O_LARGEFILE 0
 #endif
@@ -520,10 +527,30 @@  add_lwp (ptid_t ptid)
 static int
 linux_create_inferior (char *program, char **allargs)
 {
+#ifdef HAVE_PERSONALITY
+  int personality_orig = 0, personality_set = 0;
+#endif
   struct lwp_info *new_lwp;
   int pid;
   ptid_t ptid;
 
+#ifdef HAVE_PERSONALITY
+  if (disable_randomization)
+    {
+      errno = 0;
+      personality_orig = personality (0xffffffff);
+      if (errno == 0 && !(personality_orig & ADDR_NO_RANDOMIZE))
+	{
+	  personality_set = 1;
+	  personality (personality_orig | ADDR_NO_RANDOMIZE);
+	}
+      if (errno != 0 || (personality_set
+			 && !(personality (0xffffffff) & ADDR_NO_RANDOMIZE)))
+	warning ("Error disabling address space randomization: %s",
+		 strerror (errno));
+    }
+#endif
+
 #if defined(__UCLIBC__) && defined(HAS_NOMMU)
   pid = vfork ();
 #else
@@ -552,6 +579,17 @@  linux_create_inferior (char *program, ch
       _exit (0177);
     }
 
+#ifdef HAVE_PERSONALITY
+  if (personality_set)
+    {
+      errno = 0;
+      personality (personality_orig);
+      if (errno != 0)
+	warning ("Error restoring address space randomization: %s",
+		 strerror (errno));
+    }
+#endif
+
   linux_add_process (pid, 0);
 
   ptid = ptid_build (pid, pid, 0);
@@ -4633,6 +4671,15 @@  linux_supports_multi_process (void)
   return 1;
 }
 
+static int
+linux_supports_disable_randomization (void)
+{
+#ifdef HAVE_PERSONALITY
+  return 1;
+#else
+  return 0;
+#endif
+}
 
 /* Enumerate spufs IDs for process PID.  */
 static int
@@ -4965,7 +5012,8 @@  static struct target_ops linux_target_op
   linux_cancel_breakpoints,
   linux_stabilize_threads,
   linux_install_fast_tracepoint_jump_pad,
-  linux_emit_ops
+  linux_emit_ops,
+  linux_supports_disable_randomization,
 };
 
 static void
Index: gdb/gdbserver/server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.148
diff -u -p -r1.148 server.c
--- gdb/gdbserver/server.c	1 Sep 2011 03:14:10 -0000	1.148
+++ gdb/gdbserver/server.c	5 Oct 2011 17:18:29 -0000
@@ -45,6 +45,10 @@  int run_once;
 int multi_process;
 int non_stop;
 
+/* Whether we should attempt to disable the operating system's address
+   space randomization feature before starting an inferior.  */
+int disable_randomization = 1;
+
 static char **program_argv, **wrapper_argv;
 
 /* Enable miscellaneous debugging output.  The name is historical - it
@@ -497,6 +501,27 @@  handle_general_set (char *own_buf)
       return;
     }
 
+  if (strncmp ("QDisableRandomization:", own_buf,
+	       strlen ("QDisableRandomization:")) == 0)
+    {
+      char *packet = own_buf + strlen ("QDisableRandomization:");
+      ULONGEST setting;
+
+      unpack_varlen_hex (packet, &setting);
+      disable_randomization = setting;
+
+      if (remote_debug)
+	{
+	  if (disable_randomization)
+	    fprintf (stderr, "[address space randomization disabled]\n");
+	  else
+	    fprintf (stderr, "[address space randomization enabled]\n");
+	}
+
+      write_ok (own_buf);
+      return;
+    }
+
   if (target_supports_tracepoints ()
       && handle_tracepoint_general_set (own_buf))
     return;
@@ -1545,6 +1570,9 @@  handle_query (char *own_buf, int packet_
       if (target_supports_non_stop ())
 	strcat (own_buf, ";QNonStop+");
 
+      if (target_supports_disable_randomization ())
+	strcat (own_buf, ";QDisableRandomization+");
+
       strcat (own_buf, ";qXfer:threads:read+");
 
       if (target_supports_tracepoints ())
@@ -2549,6 +2577,10 @@  main (int argc, char *argv[])
 		}
 	    }
 	}
+      else if (strcmp (*next_arg, "--disable-randomization") == 0)
+	disable_randomization = 1;
+      else if (strcmp (*next_arg, "--no-disable-randomization") == 0)
+	disable_randomization = 0;
       else if (strcmp (*next_arg, "--once") == 0)
 	run_once = 1;
       else
Index: gdb/gdbserver/server.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.h,v
retrieving revision 1.86
diff -u -p -r1.86 server.h
--- gdb/gdbserver/server.h	15 Sep 2011 22:54:12 -0000	1.86
+++ gdb/gdbserver/server.h	5 Oct 2011 17:18:29 -0000
@@ -299,6 +299,8 @@  extern int run_once;
 extern int multi_process;
 extern int non_stop;
 
+extern int disable_randomization;
+
 #if USE_WIN32API
 #include <winsock2.h>
 typedef SOCKET gdb_fildes_t;
Index: gdb/gdbserver/target.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.h,v
retrieving revision 1.56
diff -u -p -r1.56 target.h
--- gdb/gdbserver/target.h	14 Aug 2011 16:06:59 -0000	1.56
+++ gdb/gdbserver/target.h	5 Oct 2011 17:18:30 -0000
@@ -377,6 +377,9 @@  struct target_ops
   /* Return the bytecode operations vector for the current inferior.
      Returns NULL if bytecode compilation is not supported.  */
   struct emit_ops *(*emit_ops) (void);
+
+  /* Returns true if the target supports disabling randomization.  */
+  int (*supports_disable_randomization) (void);
 };
 
 extern struct target_ops *the_target;
@@ -483,6 +486,10 @@  void set_target_ops (struct target_ops *
 #define target_emit_ops() \
   (the_target->emit_ops ? (*the_target->emit_ops) () : NULL)
 
+#define target_supports_disable_randomization() \
+  (the_target->supports_disable_randomization ? \
+   (*the_target->supports_disable_randomization) () : 0)
+
 /* Start non-stop mode, returns 0 on success, -1 on failure.   */
 
 int start_non_stop (int nonstop);