public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: Re: [PATCH v2] [gdb/testsuite] Handle ptrace operation not permitted in can_spawn_for_attach
Date: Wed, 1 May 2024 11:08:45 +0200	[thread overview]
Message-ID: <356a1259-c1dd-42fc-abbc-7418ce3f009a@suse.de> (raw)
In-Reply-To: <20240501083433.19966-1-tdevries@suse.de>

On 5/1/24 10:34, Tom de Vries wrote:

Um, I forgot that I already send a v2, so this is v2-v2.

Thanks,
- Tom

> When running the testsuite on a system with kernel.yama.ptrace_scope set to 1,
> we run into attach failures.
> 
> Fix this by recognizing "ptrace: Operation not permitted" in
> can_spawn_for_attach.
> 
> Tested on aarch64-linux and x86_64-linux.
> ---
>   gdb/testsuite/gdb.base/break-interp.exp       |   4 +
>   gdb/testsuite/gdb.base/dprintf-detach.exp     |   2 +-
>   .../run-control-while-bg-execution.exp        |   3 +
>   .../gdb.multi/attach-while-running.exp        |   2 +-
>   .../gdb.threads/attach-into-signal.exp        |   3 +-
>   .../gdb.threads/attach-slow-waitpid.exp       |   3 +-
>   gdb/testsuite/gdb.threads/attach-stopped.exp  |   3 +-
>   .../gdb.threads/check-libthread-db.exp        |  42 +++----
>   gdb/testsuite/lib/gdb.exp                     | 112 +++++++++++++++---
>   9 files changed, 135 insertions(+), 39 deletions(-)
> 
> diff --git a/gdb/testsuite/gdb.base/break-interp.exp b/gdb/testsuite/gdb.base/break-interp.exp
> index addacde552d..d7f84db4770 100644
> --- a/gdb/testsuite/gdb.base/break-interp.exp
> +++ b/gdb/testsuite/gdb.base/break-interp.exp
> @@ -318,6 +318,10 @@ proc test_attach_gdb {file pid displacement prefix} {
>   }
>   
>   proc test_attach {file displacement {relink_args ""}} {
> +    if { ![can_spawn_for_attach] } {
> +	return
> +    }
> +
>       global board_info
>       global exec
>   
> diff --git a/gdb/testsuite/gdb.base/dprintf-detach.exp b/gdb/testsuite/gdb.base/dprintf-detach.exp
> index 550d319a895..b4184d698df 100644
> --- a/gdb/testsuite/gdb.base/dprintf-detach.exp
> +++ b/gdb/testsuite/gdb.base/dprintf-detach.exp
> @@ -21,7 +21,7 @@
>   load_lib gdbserver-support.exp
>   
>   # The test relies on "detach/attach".
> -require !use_gdb_stub
> +require can_spawn_for_attach
>   
>   standard_testfile
>   set escapedbinfile [string_to_regexp ${binfile}]
> diff --git a/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp b/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp
> index f1cbd9351d3..380047ae854 100644
> --- a/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp
> +++ b/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp
> @@ -110,6 +110,9 @@ proc do_test { action1 action2 } {
>   
>   foreach_with_prefix action1 { kill detach add none } {
>       foreach_with_prefix action2 { start run attach } {
> +	if { $action2 == "attach" && ![can_spawn_for_attach] } {
> +	   continue
> +	}
>   	do_test $action1 $action2
>       }
>   }
> diff --git a/gdb/testsuite/gdb.multi/attach-while-running.exp b/gdb/testsuite/gdb.multi/attach-while-running.exp
> index eade8b42a18..ca4fa635467 100644
> --- a/gdb/testsuite/gdb.multi/attach-while-running.exp
> +++ b/gdb/testsuite/gdb.multi/attach-while-running.exp
> @@ -36,7 +36,7 @@
>   
>   standard_testfile
>   
> -require !use_gdb_stub
> +require can_spawn_for_attach
>   
>   if { [build_executable "failed to prepare" ${testfile} ${srcfile}] } {
>       return
> diff --git a/gdb/testsuite/gdb.threads/attach-into-signal.exp b/gdb/testsuite/gdb.threads/attach-into-signal.exp
> index 87e34070548..91da960e09a 100644
> --- a/gdb/testsuite/gdb.threads/attach-into-signal.exp
> +++ b/gdb/testsuite/gdb.threads/attach-into-signal.exp
> @@ -17,7 +17,8 @@
>   # This file was created by Jan Kratochvil <jan.kratochvil@redhat.com>.
>   
>   # This test only works on Linux
> -require !use_gdb_stub isnative
> +require can_spawn_for_attach
> +require isnative
>   require {!is_remote host}
>   require {istarget *-linux*}
>   
> diff --git a/gdb/testsuite/gdb.threads/attach-slow-waitpid.exp b/gdb/testsuite/gdb.threads/attach-slow-waitpid.exp
> index dc3e62a7b7e..28d70daad8c 100644
> --- a/gdb/testsuite/gdb.threads/attach-slow-waitpid.exp
> +++ b/gdb/testsuite/gdb.threads/attach-slow-waitpid.exp
> @@ -37,7 +37,8 @@
>   # during the attach phase.
>   
>   # This test only works on Linux
> -require !use_gdb_stub isnative
> +require can_spawn_for_attach
> +require isnative
>   require {!is_remote host}
>   require {istarget *-linux*}
>   
> diff --git a/gdb/testsuite/gdb.threads/attach-stopped.exp b/gdb/testsuite/gdb.threads/attach-stopped.exp
> index 78e194c992f..0421ffc3794 100644
> --- a/gdb/testsuite/gdb.threads/attach-stopped.exp
> +++ b/gdb/testsuite/gdb.threads/attach-stopped.exp
> @@ -18,7 +18,8 @@
>   # This file was updated by Jan Kratochvil <jan.kratochvil@redhat.com>.
>   
>   # This test only works on Linux
> -require !use_gdb_stub isnative
> +require can_spawn_for_attach
> +require isnative
>   require {!is_remote host}
>   require {istarget *-linux*}
>   
> diff --git a/gdb/testsuite/gdb.threads/check-libthread-db.exp b/gdb/testsuite/gdb.threads/check-libthread-db.exp
> index 5662eeda077..6976fe6f83b 100644
> --- a/gdb/testsuite/gdb.threads/check-libthread-db.exp
> +++ b/gdb/testsuite/gdb.threads/check-libthread-db.exp
> @@ -102,25 +102,27 @@ with_test_prefix "automated load-time check" {
>       }
>   
>       # Automated load-time check with NPTL fully operational.
> -    with_test_prefix "libpthread.so fully initialized" {
> -	clean_restart ${binfile}
> -
> -	gdb_test_no_output "maint set check-libthread-db 1"
> -	gdb_test_no_output "set debug libthread-db 1"
> -
> -	set test_spawn_id [spawn_wait_for_attach $binfile]
> -	set testpid [spawn_id_get_pid $test_spawn_id]
> -
> -	gdb_test_sequence "attach $testpid" \
> -	    "check debug libthread-db output" {
> -		"\[\r\n\]+Running libthread_db integrity checks:"
> -		"\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+ ... OK"
> -		"\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+ ... OK"
> -		"\[\r\n\]+libthread_db integrity checks passed."
> -		"\[\r\n\]+[Thread debugging using libthread_db enabled]"
> -	    }
> -
> -	gdb_exit
> -	kill_wait_spawned_process $test_spawn_id
> +    if { [can_spawn_for_attach] } {
> +	with_test_prefix "libpthread.so fully initialized" {
> +	    clean_restart ${binfile}
> +
> +	    gdb_test_no_output "maint set check-libthread-db 1"
> +	    gdb_test_no_output "set debug libthread-db 1"
> +
> +	    set test_spawn_id [spawn_wait_for_attach $binfile]
> +	    set testpid [spawn_id_get_pid $test_spawn_id]
> +
> +	    gdb_test_sequence "attach $testpid" \
> +		"check debug libthread-db output" {
> +		    "\[\r\n\]+Running libthread_db integrity checks:"
> +		    "\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+ ... OK"
> +		    "\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+ ... OK"
> +		    "\[\r\n\]+libthread_db integrity checks passed."
> +		    "\[\r\n\]+[Thread debugging using libthread_db enabled]"
> +		}
> +
> +	    gdb_exit
> +	    kill_wait_spawned_process $test_spawn_id
> +	}
>       }
>   }
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index d092258a9e5..7019f38eb15 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -6155,8 +6155,54 @@ proc gdb_exit { } {
>       catch default_gdb_exit
>   }
>   
> +# Helper function for can_spawn_for_attach.  Try to spawn and attach, and
> +# return 0 only if we cannot attach because it's unsupported.
> +
> +gdb_caching_proc can_spawn_for_attach_1 {} {
> +    # Assume yes.
> +    set res 1
> +
> +    set me "can_spawn_for_attach"
> +    set src {
> +	#include <unistd.h>
> +
> +	int
> +	main (void)
> +	{
> +	    sleep (600);
> +	    return 0;
> +	}
> +    }
> +    if {![gdb_simple_compile $me $src executable]} {
> +	return $res
> +    }
> +
> +    set test_spawn_id [spawn_wait_for_attach_1 $obj]
> +    remote_file build delete $obj
> +
> +    gdb_start
> +
> +    set test_pid [spawn_id_get_pid $test_spawn_id]
> +    set attaching_re "Attaching to process $test_pid"
> +    gdb_test_multiple "attach $test_pid" "can spawn for attach" {
> +	-re -wrap "$attaching_re\r\n.*ptrace: Operation not permitted\\." {
> +	    # Not permitted.
> +	    set res 0
> +	}
> +	-re -wrap "" {
> +	    # Don't know, keep assuming yes.
> +	}
> +    }
> +
> +    gdb_exit
> +
> +    kill_wait_spawned_process $test_spawn_id
> +
> +    return $res
> +}
> +
>   # Return true if we can spawn a program on the target and attach to
> -# it.
> +# it.  Calls gdb_exit for the first call in a test-case.
>   
>   proc can_spawn_for_attach { } {
>       # We use exp_pid to get the inferior's pid, assuming that gives
> @@ -6175,8 +6221,39 @@ proc can_spawn_for_attach { } {
>   	return 0
>       }
>   
> -    # Assume yes.
> -    return 1
> +    # The normal sequence to use for a runtime test like
> +    # can_spawn_for_attach_1 is:
> +    # - gdb_exit (don't use a running gdb, we don't know what state it is in),
> +    # - gdb_start (start a new gdb), and
> +    # - gdb_exit (cleanup).
> +    #
> +    # By making can_spawn_for_attach_1 a gdb_caching_proc, we make it
> +    # unpredictable which test-case will call it first, and consequently a
> +    # test-case may pass in say a full test run, but fail when run
> +    # individually, due to a can_spawn_for_attach call in location where a
> +    # gdb_exit (as can_spawn_for_attach_1 does) breaks things.
> +    # To avoid this, we move the initial gdb_exit out of
> +    # can_spawn_for_attach_1, guaranteeing that we end up in the same state
> +    # regardless of whether can_spawn_for_attach_1 is called.  However, that
> +    # is only necessary for the first call in a test-case, so cache the result
> +    # in a global (which should be reset after each test-case) to keep track
> +    # of that.
> +    #
> +    # In summary, we distinguish between three cases:
> +    # - first call in first test-case.  Executes can_spawn_for_attach_1.
> +    #   Calls gdb_exit, gdb_start, gdb_exit.
> +    # - first call in following test-cases.  Uses cached result of
> +    #   can_spawn_for_attach_1.  Calls gdb_exit.
> +    # - rest.  Use cached result in cache_can_spawn_for_attach_1. Calls no
> +    #   gdb_start or gdb_exit.
> +    global cache_can_spawn_for_attach_1
> +    if { [info exists cache_can_spawn_for_attach_1] } {
> +	return $cache_can_spawn_for_attach_1
> +    }
> +    gdb_exit
> +
> +    set cache_can_spawn_for_attach_1 [can_spawn_for_attach_1]
> +    return $cache_can_spawn_for_attach_1
>   }
>   
>   # Centralize the failure checking of "attach" command.
> @@ -6289,20 +6366,12 @@ proc spawn_id_get_pid { spawn_id } {
>       return $testpid
>   }
>   
> -# Start a set of programs running and then wait for a bit, to be sure
> -# that they can be attached to.  Return a list of processes spawn IDs,
> -# one element for each process spawned.  It's a test error to call
> -# this when [can_spawn_for_attach] is false.
> +# Helper function for spawn_wait_for_attach and can_spawn_for_attach_1.  As
> +# spawn_wait_for_attach, but doesn't check for can_spawn_for_attach.
>   
> -proc spawn_wait_for_attach { executable_list } {
> +proc spawn_wait_for_attach_1 { executable_list } {
>       set spawn_id_list {}
>   
> -    if ![can_spawn_for_attach] {
> -	# The caller should have checked can_spawn_for_attach itself
> -	# before getting here.
> -	error "can't spawn for attach with this target/board"
> -    }
> -
>       foreach {executable} $executable_list {
>   	# Note we use Expect's spawn, not Tcl's exec, because with
>   	# spawn we control when to wait for/reap the process.  That
> @@ -6316,6 +6385,21 @@ proc spawn_wait_for_attach { executable_list } {
>       return $spawn_id_list
>   }
>   
> +# Start a set of programs running and then wait for a bit, to be sure
> +# that they can be attached to.  Return a list of processes spawn IDs,
> +# one element for each process spawned.  It's a test error to call
> +# this when [can_spawn_for_attach] is false.
> +
> +proc spawn_wait_for_attach { executable_list } {
> +    if ![can_spawn_for_attach] {
> +	# The caller should have checked can_spawn_for_attach itself
> +	# before getting here.
> +	error "can't spawn for attach with this target/board"
> +    }
> +
> +    return [spawn_wait_for_attach_1 $executable_list]
> +}
> +
>   #
>   # gdb_load_cmd -- load a file into the debugger.
>   #		  ARGS - additional args to load command.
> 
> base-commit: 7320840f1998547b4428c58d1b39ca41febad83a


  reply	other threads:[~2024-05-01  9:08 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-01  8:34 Tom de Vries
2024-05-01  9:08 ` Tom de Vries [this message]
2024-05-06 11:33 ` Pedro Alves
2024-05-17  3:42 ` Simon Marchi
2024-05-17  9:54   ` Tom de Vries
  -- strict thread matches above, loose matches on Subject: below --
2024-04-18  6:32 Tom de Vries
2024-04-24 19:40 ` Pedro Alves
2024-04-24 21:35   ` Tom de Vries
2024-04-26 18:50     ` Pedro Alves
2024-05-01  8:42       ` Tom de Vries

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=356a1259-c1dd-42fc-abbc-7418ce3f009a@suse.de \
    --to=tdevries@suse.de \
    --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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).