From patchwork Wed Oct 5 18:32:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulrich Weigand X-Patchwork-Id: 4539 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id D63A323DEF for ; Wed, 5 Oct 2011 18:33:03 +0000 (UTC) Received: from mail-gy0-f180.google.com (mail-gy0-f180.google.com [209.85.160.180]) by fiordland.canonical.com (Postfix) with ESMTP id 4E92EA18BFB for ; Wed, 5 Oct 2011 18:33:03 +0000 (UTC) Received: by gyd8 with SMTP id 8so2670118gyd.11 for ; Wed, 05 Oct 2011 11:33:02 -0700 (PDT) Received: by 10.223.94.134 with SMTP id z6mr375297fam.8.1317839581129; Wed, 05 Oct 2011 11:33:01 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.23.170 with SMTP id n10cs101637laf; Wed, 5 Oct 2011 11:33:00 -0700 (PDT) Received: by 10.216.134.169 with SMTP id s41mr6857349wei.68.1317839579611; Wed, 05 Oct 2011 11:32:59 -0700 (PDT) Received: from mtagate3.uk.ibm.com (mtagate3.uk.ibm.com. [194.196.100.163]) by mx.google.com with ESMTPS id a6si1958110wed.80.2011.10.05.11.32.59 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 05 Oct 2011 11:32:59 -0700 (PDT) Received-SPF: pass (google.com: domain of uweigand@de.ibm.com designates 194.196.100.163 as permitted sender) client-ip=194.196.100.163; Authentication-Results: mx.google.com; spf=pass (google.com: domain of uweigand@de.ibm.com designates 194.196.100.163 as permitted sender) smtp.mail=uweigand@de.ibm.com Received: from d06nrmr1307.portsmouth.uk.ibm.com (d06nrmr1307.portsmouth.uk.ibm.com [9.149.38.129]) by mtagate3.uk.ibm.com (8.13.1/8.13.1) with ESMTP id p95IWwqY008044 for ; Wed, 5 Oct 2011 18:32:58 GMT Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by d06nrmr1307.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p95IWwEg2502880 for ; Wed, 5 Oct 2011 19:32:58 +0100 Received: from d06av02.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p95IWwIm029996 for ; Wed, 5 Oct 2011 12:32:58 -0600 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id p95IWuVb029968; Wed, 5 Oct 2011 12:32:56 -0600 Message-Id: <201110051832.p95IWuVb029968@d06av02.portsmouth.uk.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Wed, 05 Oct 2011 20:32:56 +0200 Subject: [rfc v2, rfa-doc] Disable address space randomization with remote targets To: pedro@codesourcery.com (Pedro Alves) Date: Wed, 5 Oct 2011 20:32:56 +0200 (CEST) From: "Ulrich Weigand" Cc: gdb-patches@sourceware.org, jan.kratochvil@redhat.com (Jan Kratochvil), patches@linaro.org In-Reply-To: <201109301715.06928.pedro@codesourcery.com> from "Pedro Alves" at Sep 30, 2011 05:15:06 PM X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 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 . 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. 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 = ¤t_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 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 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 +" +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 +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 +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 ]) +define([PERSONALITY_TEST], [AC_LANG_PROGRAM([#include ], [ +# 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 +# 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 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);