From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 51563 invoked by alias); 1 Sep 2016 14:48:42 -0000 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 Received: (qmail 50514 invoked by uid 89); 1 Sep 2016 14:48:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 spammy=snyder, Snyder, angle, interrupted X-HELO: mail-pa0-f65.google.com Received: from mail-pa0-f65.google.com (HELO mail-pa0-f65.google.com) (209.85.220.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 01 Sep 2016 14:48:31 +0000 Received: by mail-pa0-f65.google.com with SMTP id cf3so4302051pad.2 for ; Thu, 01 Sep 2016 07:48:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version:content-transfer-encoding; bh=rqfZGGnIGYysYn5VqJ7EXRkD8nZZsqQnhJc0RhnRu7w=; b=CBrdrR8R0dFil/IwWBlNmRO/1fJQcjOE3fmn7wCanQDkDSUZ2rKjzhKFwcQKej/Ymo c83xdnmJDI6sYVpMjS92hXwhPNlcDXWahZ1AGcAkhsTmWJHuYlwCnwAs/ytLxgdjfncX ul0RKMtvQ2RoTo/ePK5pe5g20NmUNrj3s4QucM6clmglFsM5XEnn5aqggtv5MedzYThG 7kp/PQoTkBFp2ndkLksVdR0qqHPNxitcQxL07hJwm4kVgIThHiGh/CwFl680uz2FL2Cn +h8IB64r9qDb5JAaHvr4A0NHe4AQeWwjqZvlJnP3ko4c1KXiPjWsd+tdr+ozi4SE+ou5 aCNw== X-Gm-Message-State: AE9vXwNlItPgCB3rDz38vMgSVUn1GhigaijUfAxm/lPErzroN4S2ambGPttlojRNs0PbDQ== X-Received: by 10.66.123.105 with SMTP id lz9mr27741498pab.56.1472741309358; Thu, 01 Sep 2016 07:48:29 -0700 (PDT) Received: from E107787-LIN (gcc115.osuosl.org. [140.211.9.73]) by smtp.gmail.com with ESMTPSA id s12sm8301722pfj.73.2016.09.01.07.48.23 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Thu, 01 Sep 2016 07:48:27 -0700 (PDT) From: Yao Qi To: Pedro Alves Cc: Yao Qi , "gdb-patches\@sourceware.org" Subject: Re: [RFC] Set process affinity in test to work around ARM ptrace bug References: <1467295036-2816-1-git-send-email-yao.qi@linaro.org> <86a8hxzni8.fsf@gmail.com> Date: Thu, 01 Sep 2016 14:48:00 -0000 In-Reply-To: (Pedro Alves's message of "Mon, 25 Jul 2016 15:28:17 +0100") Message-ID: <86vayfbrrf.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2016-09/txt/msg00017.txt.bz2 Pedro Alves writes: This work is interrupted by 7.12 release. Now, I can visit this problem again. > But since this is only for when running the testsuite alone, I could argu= e that > this masks the problem and thus makes it look like gdb works better on an > affected system than it really does. I think if I were working on gdb/gd= bserver > on arm, I'd much prefer if gdb told me my system had a broken ptrace, so I > could act on it, rather than masking it off and pretend all is well. > How about we make gdb / gdbserver detect bad kernel version, and output a > warning to the effect? We already have precedent in > nat/linux-ptrace.c. Do you mean linux_ptrace_test_ret_to_nx_instr? > I think we should probably do that regardless of any testsuite workaround. > Yes, I agree. I'll write a test in nat/linux-ptrace.c too. > How bad would it be to push for people to update their kernels? > I am pushing people to update kernels. I've updated the kernels on some boards I am using, but there are many boxes which is difficult to update kernel. > > From a testsuite workaround angle, instead of sprinkling=20 > set_process_affinity calls around, what if we we added a new proc > that would be called at the top of the .exp files: > > gdb_caching_proc skip_arm_vfp_tests {} { > > if arm && linux && broken linux versions { > return 1 > } >=20=20=20 > return 0 > } > > This would skip tests instead of making them pass, but how bad would > that be? I assume that people doing gdb development/testing on arm will > be able to update their kernels, and will very much want to do that. I happen to see there is a proc gdb_skip_float_test, so I write a patch to detect broken kernel ptrace in it, and use gdb_skip_float_test all over the test cases. How about the patch below? --=20 Yao (=E9=BD=90=E5=B0=A7) From: Yao Qi Date: Thu, 1 Sep 2016 14:39:47 +0100 Subject: [PATCH] Detect broken ptrace in gdb_skip_float_test We recently found a ARM kernel ptrace bug http://lists.infradead.org/pipermail/linux-arm-kernel/2016-May/431962.html Details can be found in the comment in gdb_skip_float_test. We can skip floating point tests if the kernel bug is detected. This patch adds more code in gdb_skip_float_test to detect the broken ptrace on arm-linux. Such detection should be done at the beginning of the test, because it starts a fresh GDB, so change the test cases to invoke gdb_skip_float_test at the beginning of test, and use its return value afterwards. Since gdb_skip_float_test becomes a gdb_caching_proc, so it can't have an argument, this patch also removes argument "msg", which isn't useful. gdb/testsuite: 2016-09-01 Yao Qi * gdb.arch/arm-neon.exp: Skip it if gdb_skip_float_test returns true. * gdb.base/call-ar-st.exp: Invoke gdb_skip_float_test. * gdb.base/call-rt-st.exp: Likewise. * gdb.base/call-sc.exp: Invoke gdb_skip_float_test and use its return value instead of gdb,skip_float_test. * gdb.base/callfuncs.exp: Invoke gdb_skip_float_test. (do_function_calls): Use its return value instead of gdb,skip_float_test. * gdb.base/finish.exp: Likewise. * gdb.base/funcargs.exp: Likewise. * gdb.base/return.exp: Likewise. * gdb.base/return2.exp: Likewise. * gdb.base/varargs.exp: Likewise. * lib/gdb.exp (gdb_skip_float_test): Change it to gdb_caching_proc. Detect the broken ptrace on arm-linux. diff --git a/gdb/testsuite/gdb.arch/arm-neon.exp b/gdb/testsuite/gdb.arch/a= rm-neon.exp index 053170f..e4612f9 100644 --- a/gdb/testsuite/gdb.arch/arm-neon.exp +++ b/gdb/testsuite/gdb.arch/arm-neon.exp @@ -20,6 +20,11 @@ if {![istarget "aarch64*-*-*"] && ![istarget "arm*-*-*"]= } { return } =20 +if { [gdb_skip_float_test] } { + verbose "Skipping ${gdb_test_file_name}." + return +} + standard_testfile if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug qu= iet}] } { unsupported "ARM NEON is not supported" diff --git a/gdb/testsuite/gdb.base/call-ar-st.exp b/gdb/testsuite/gdb.base= /call-ar-st.exp index 28436d5..c63935a 100644 --- a/gdb/testsuite/gdb.base/call-ar-st.exp +++ b/gdb/testsuite/gdb.base/call-ar-st.exp @@ -33,6 +33,8 @@ if [get_compiler_info] { return -1 } =20 +set skip_float_test [gdb_skip_float_test] + if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} { untested $testfile.exp return -1 @@ -65,7 +67,7 @@ gdb_test continue \ =20 =20 #call print_double_array(double_array) -if {![gdb_skip_float_test "print print_double_array(double_array)"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "print print_double_array(double_array)"] } { =20 gdb_test_stdio "print print_double_array(double_array)" \ @@ -126,7 +128,7 @@ gdb_test "tbreak $stop_line" \ "Temporary breakpoint.* file .*$srcfile, line $stop_line.*" \ "tbreakpoint at tbreak3" =20 -if {![gdb_skip_float_test "continuing to tbreak3"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "continuing to tbreak3"] } { =20 gdb_test_stdio "continue" \ @@ -168,7 +170,7 @@ if ![gdb_skip_stdio_test "next over print_int_array in = print_all_arrays"] { } =20 #call print_double_array(array_d) -if {![gdb_skip_float_test "print print_double_array(array_d)"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "print print_double_array(array_d)"] } { =20 gdb_test_stdio "print print_double_array(array_d)" \ @@ -186,7 +188,7 @@ gdb_test "tbreak $stop_line" \ "Temporary breakpoint.* file .*$srcfile, line $stop_line.*" \ "tbreakpoint at tbreak4" =20 -if {![gdb_skip_float_test "continuing to tbreak4"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "continuing to tbreak4"] } { =20 gdb_test_stdio "continue" \ @@ -305,7 +307,7 @@ if ![gdb_skip_stdio_test "continuing to tbreak6"] { # *flags, *flags_combo, *three_char, *five_char,=20 # *int_char_combo, *d1, *d2, *d3, *f1, *f2, *f3) =20 -if {![gdb_skip_float_test "print print_small_structs(...)"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "print print_small_structs(...)"] } { gdb_test_stdio "print print_small_structs(*struct1, *struct2, *struct3= , *struct4, *flags, *flags_combo, *three_char, *five_char, *int_char_combo,= *d1, *d2, *d3, *f1, *f2, *f3)" \ [multi_line \ @@ -369,7 +371,7 @@ gdb_test "print compute_with_small_structs(20)" \ #call print_ten_doubles(123.456, 123.456, -0.12, -1.23, 343434.8, 89.098,= =20 # 3.14, -5678.12345, -0.11111111, 216.97065) =20 -if {![gdb_skip_float_test "print print_ten_doubles(...)"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "print print_ten_doubles(...)"]} { gdb_test_stdio "print print_ten_doubles(123.456, 123.456, -0.12, -1.23= , 343434.8, 89.098, 3.14, -5678.12345, -0.11111111, 216.97065)" \ [multi_line \ @@ -397,7 +399,7 @@ gdb_test "tbreak print_long_arg_list" \ # The short match case below handles cases where a buffer # overflows or something, and expect can't deal with the full # line. Perhaps a more elegant solution exists... -sts 1999-08-17 -if {![gdb_skip_float_test "step into print_long_arg_list"]} { +if {!$skip_float_test} { gdb_test_multiple "continue" "step into print_long_arg_list" { -re ".*print_long_arg_list \\(a=3D22.25, b=3D33.375, c=3D0, d=3D-25, e=3D= 100, f=3D2345, struct1=3D\{value =3D 6, head =3D 0\}, struct2=3D\{value =3D= 10, head =3D 0\}, struct3=3D\{value =3D 12, head =3D 0\}, struct4=3D\{valu= e =3D 14, head =3D 0\}, flags=3D\{alpha =3D 1, beta =3D 0, gamma =3D 1, del= ta =3D 0, epsilon =3D 1, omega =3D 0\}, flags_combo=3D\{alpha =3D 1, beta = =3D 0, ch1 =3D 121 \'y\', gamma =3D 1, delta =3D 0, ch2 =3D 110 \'n\', epsi= lon =3D 1, omega =3D 0\}, three_char=3D\{ch1 =3D 97 \'a\', ch2 =3D 98 \'b\'= , ch3 =3D 99 \'c\'\}, five_char=3D\{ch1 =3D 108 \'l\', ch2 =3D 109 \'m\', c= h3 =3D 110 \'n\', ch4 =3D 111 \'o\', ch5 =3D 112 \'p\'\}, int_char_combo=3D= \{int1 =3D 123, ch1 =3D 122 \'z\'\}, d1=3D\{double1 =3D 10.5\}, d2=3D\{doub= le1 =3D -3.375\}, d3=3D\{double1 =3D 675.09375\}, f1=3D\{float1 =3D 45.2340= 012, float2 =3D 43.5999985\}, f2=3D\{float1 =3D 78.0100021, float2 =3D 122.= 099998\}, f3=3D\{float1 =3D -1232.34497, float2 =3D -199.210007\}\\) at .*$= {srcfile}:$stop_line\[\r\n\]+$stop_line\[ \t\]+printf\\(\"double :.*\", a\\= );.*$gdb_prompt $" { pass "step into print_long_arg_list" @@ -419,7 +421,7 @@ set ws "\[\n\r\t \]+" # flags_combo, three_char, five_char, int_char_com= bo,=20 # d1, d2, d3, f1, f2, f3) =20 -if {![gdb_skip_float_test "print_small_structs from print_long_arg_list"] = && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "print_small_structs from print_long_arg_list"] = } { =20 # On 32-bit SPARC, some of the args are passed by ref, others by @@ -520,7 +522,7 @@ gdb_test continue "Continuing\\..*main \\(\\) at .*$src= file:$stop_line\[\r\n\t \ =20 #call print_long_arg_list(a, b, c, d, e, f, *struct1, *struct2, *struct3, = *struct4, *flags, *flags_combo, *three_char, *five_char, *int_char_combo, *= d1, *d2, *d3, *f1, *f2, *f3) =20 -if {![gdb_skip_float_test "print print_long_arg_list"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "print print_long_arg_list"] } { =20 gdb_test_stdio "print print_long_arg_list(a, b, c, d, e, f, *struct1, = *struct2, *struct3, *struct4, *flags, *flags_combo, *three_char, *five_char= , *int_char_combo, *d1, *d2, *d3, *f1, *f2, *f3)" \ diff --git a/gdb/testsuite/gdb.base/call-rt-st.exp b/gdb/testsuite/gdb.base= /call-rt-st.exp index 0f9c5e8..a92ba9e 100644 --- a/gdb/testsuite/gdb.base/call-rt-st.exp +++ b/gdb/testsuite/gdb.base/call-rt-st.exp @@ -44,6 +44,8 @@ if [target_info exists gdb,cannot_call_functions] { continue } =20 +set skip_float_test [gdb_skip_float_test] + # Start with a fresh gdb. =20 clean_restart ${binfile} @@ -128,14 +130,14 @@ if ![gdb_skip_stdio_test "print print_one_large_struc= t(...)"] { ".\[0-9\]+ =3D \\{next_index =3D \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10\\}, val= ues =3D \\{4, 6, 8, 10, 12, 14, 16, 18, 20, 22\\}, head =3D 0\\}" } =20 -if {![gdb_skip_float_test "print print_one_double(*d1)"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "print print_one_double(*d1)"] } { print_struct_call "print_one_double(*d1)" \ ".*Contents of one_double_t:\[ \r\n\]+1\\.111110\[ \r\n\]+" \ ".\[0-9\]+ =3D \\{double1 =3D 1\\.111\[0-9\]*\\}" } =20 -if {![gdb_skip_float_test "print print_two_floats(*f3)"] && \ +if {!$skip_float_test && \ ![gdb_skip_stdio_test "print print_two_floats(*f3)"] } { print_struct_call "print_two_floats(*f3)" \ ".*Contents of two_floats_t:\[ \r\n\]+-2\\.345000\[ \t]+1\\.000000\[ \r\n= \]+" \ diff --git a/gdb/testsuite/gdb.base/call-sc.exp b/gdb/testsuite/gdb.base/ca= ll-sc.exp index 7592d65..89065e1 100644 --- a/gdb/testsuite/gdb.base/call-sc.exp +++ b/gdb/testsuite/gdb.base/call-sc.exp @@ -35,6 +35,7 @@ standard_testfile .c if [get_compiler_info] { return -1 } +set skip_float_test [gdb_skip_float_test] =20 # Compile a variant of scalars.c using TYPE to specify the type of the # parameter and return-type. Run the compiled program up to "main". @@ -427,7 +428,7 @@ start_scalars_test tll test_scalar_calls test_scalar_returns =20 -if ![target_info exists gdb,skip_float_tests] { +if {!$skip_float_test} { # Approx size: 4, 8, ... start_scalars_test tf test_scalar_calls diff --git a/gdb/testsuite/gdb.base/callfuncs.exp b/gdb/testsuite/gdb.base/= callfuncs.exp index 1ec33d8..b108952 100644 --- a/gdb/testsuite/gdb.base/callfuncs.exp +++ b/gdb/testsuite/gdb.base/callfuncs.exp @@ -30,6 +30,8 @@ if [target_info exists gdb,cannot_call_functions] { continue } =20 +set skip_float_test [gdb_skip_float_test] + # FIXME: Before calling this proc, we should probably verify that # we can call inferior functions and get a valid integral value # returned. @@ -38,7 +40,7 @@ if [target_info exists gdb,cannot_call_functions] { # (computed in the inferior) is 1 for true and 0 for false. =20 proc do_function_calls {} { - global gdb_prompt + global gdb_prompt skip_float_test =20 # We need to up this because this can be really slow on some boards. set timeout 60 @@ -71,7 +73,7 @@ proc do_function_calls {} { gdb_test "p t_long_values(789,long_val2)" " =3D 1" gdb_test "p t_long_values(long_val1,-321)" " =3D 1" =20 - if ![target_info exists gdb,skip_float_tests] { + if {!$skip_float_test} { gdb_test "p t_float_values(0.0,0.0)" " =3D 0" =20 # These next four tests fail on the mn10300. @@ -199,7 +201,7 @@ proc do_function_calls {} { gdb_test "p t_structs_l(struct_val1)" "=3D 51" \ "call inferior func with struct - returns long" =20 - if ![target_info exists gdb,skip_float_tests] { + if {!$skip_float_test} { gdb_test "p t_structs_f(struct_val1)" "=3D 2.12.*" \ "call inferior func with struct - returns float" gdb_test "p t_structs_d(struct_val1)" "=3D 9.87.*" \ diff --git a/gdb/testsuite/gdb.base/finish.exp b/gdb/testsuite/gdb.base/fin= ish.exp index 47bf6f8..c5387bb 100644 --- a/gdb/testsuite/gdb.base/finish.exp +++ b/gdb/testsuite/gdb.base/finish.exp @@ -15,6 +15,7 @@ =20 # This file was written by Michael Snyder (msnyder@redhat.com) =20 +set skip_float_test [gdb_skip_float_test] =20 # re-use the program from the "return2" test. if { [prepare_for_testing finish.exp finish return2.c] } { @@ -86,7 +87,7 @@ proc finish_abbreviation { abbrev } { } =20 proc finish_tests { } { - global gdb_prompt + global gdb_prompt skip_float_test =20 if { ! [ runto_main ] } then { untested finish.exp @@ -99,7 +100,7 @@ proc finish_tests { } { finish_1 "int" finish_1 "long" finish_1 "long_long" - if ![target_info exists gdb,skip_float_tests] { + if {!$skip_float_test} { finish_1 "float" finish_1 "double" } diff --git a/gdb/testsuite/gdb.base/funcargs.exp b/gdb/testsuite/gdb.base/f= uncargs.exp index 792ca9e..fe04b2f 100644 --- a/gdb/testsuite/gdb.base/funcargs.exp +++ b/gdb/testsuite/gdb.base/funcargs.exp @@ -29,6 +29,8 @@ if [get_compiler_info] { return -1 } =20 +set skip_float_test [gdb_skip_float_test] + if {[prepare_for_testing $testfile.exp $testfile $srcfile $compile_flags]}= { untested $testfile.exp return -1 @@ -1155,7 +1157,7 @@ gdb_test_no_output "set print frame-arguments all" =20 integral_args unsigned_integral_args -if {![target_info exists gdb,skip_float_tests]} { +if {!$skip_float_test} { float_and_integral_args } =20 @@ -1165,7 +1167,7 @@ if [support_complex_tests] { =20 complex_integral_args =20 - if {![target_info exists gdb,skip_float_tests]} { + if {!$skip_float_test} { complex_float_integral_args } } diff --git a/gdb/testsuite/gdb.base/return.exp b/gdb/testsuite/gdb.base/ret= urn.exp index 95748eb..63cccf2 100644 --- a/gdb/testsuite/gdb.base/return.exp +++ b/gdb/testsuite/gdb.base/return.exp @@ -19,8 +19,10 @@ if { [prepare_for_testing return.exp "return"] } { return -1 } =20 +set skip_float_test [gdb_skip_float_test] + proc return_tests { } { - global gdb_prompt + global gdb_prompt skip_float_test =20 =20 if { ! [ runto func1 ] } then { return 0 } @@ -88,7 +90,7 @@ proc return_tests { } { # is not xfailed. =20 setup_xfail "sparc-*-solaris2.3*" "sparc-*-solaris2.4*" "m6811-*-*" - if ![target_info exists gdb,skip_float_tests] { + if {!$skip_float_test} { gdb_test "p tmp3" ".* =3D 5.*" \ "correct value returned double test (known problem with sparc solaris= )" } diff --git a/gdb/testsuite/gdb.base/return2.exp b/gdb/testsuite/gdb.base/re= turn2.exp index d6ff283..77be75e 100644 --- a/gdb/testsuite/gdb.base/return2.exp +++ b/gdb/testsuite/gdb.base/return2.exp @@ -23,6 +23,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${bi= nfile}" executable {deb return -1 } =20 +set skip_float_test [gdb_skip_float_test] + proc return_1 { type } { global gdb_prompt =20 @@ -77,7 +79,7 @@ proc return_void { } { } =20 proc return2_tests { } { - global gdb_prompt + global gdb_prompt skip_float_test =20 if { ! [ runto_main ] } then { untested return2.exp @@ -92,7 +94,7 @@ proc return2_tests { } { if { ! [istarget "m6811-*-*"] && ![istarget "h8300*-*"] } then { return_1 "long_long" } - if ![target_info exists gdb,skip_float_tests] { + if {!$skip_float_test} { return_1 "float" if { ! [istarget "m6811-*-*"] } then { return_1 "double" diff --git a/gdb/testsuite/gdb.base/varargs.exp b/gdb/testsuite/gdb.base/va= rargs.exp index f400541..36b0107 100644 --- a/gdb/testsuite/gdb.base/varargs.exp +++ b/gdb/testsuite/gdb.base/varargs.exp @@ -37,6 +37,8 @@ if [get_compiler_info] { return -1 } =20 +set skip_float_test [gdb_skip_float_test] + set additional_flags {debug} if [support_complex_tests] { lappend additional_flags "additional_flags=3D-DTEST_COMPLEX" @@ -87,7 +89,7 @@ gdb_test_stdio "print find_max2(3,1,2,3)" \ ".\[0-9\]+ =3D 3" \ "print find_max2(3,1,2,3)" =20 -if {![target_info exists gdb,skip_float_tests]} { +if {!$skip_float_test} { gdb_test_stdio "print find_max_double(5,1.0,17.0,2.0,3.0,4.0)" \ "find_max\\(.*\\) returns 17\\.000000\[ \r\n\]+" \ ".\[0-9\]+ =3D 17" \ diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index b7b8fad..5cab774 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -4882,14 +4882,102 @@ proc rerun_to_main {} { } } =20 -# Print a message and return true if a test should be skipped -# due to lack of floating point suport. +# Return true if a test should be skipped due to lack of floating +# point support or GDB can't fetch the contents from floating point +# registers. =20 -proc gdb_skip_float_test { msg } { +gdb_caching_proc gdb_skip_float_test { if [target_info exists gdb,skip_float_tests] { - verbose "Skipping test '$msg': no float tests." return 1 } + + # There is an ARM kernel ptrace bug that hardware VFP registers + # are not updated after GDB ptrace set VFP registers. The bug + # was introduced by kernel commit 8130b9d7b9d858aa04ce67805e8951e3cb6e= 9b2f + # in 2012 and is fixed in e2dfb4b880146bfd4b6aa8e138c0205407cebbaf + # in May 2016. In other words, kernels older than 4.6.3, 4.4.14, + # 4.1.27, 3.18.36, and 3.14.73 have this bug. + # This kernel bug is detected by check how does GDB change the + # program result by changing one VFP register. + if { [istarget "arm*-*-linux*"] } { + + set compile_flags {debug nowarnings } + + # Set up, compile, and execute a test program having VFP + # operations. + set src [standard_temp_file arm_vfp[pid].c] + set exe [standard_temp_file arm_vfp[pid].x] + + gdb_produce_source $src { + int main() { + double d =3D 4.0; + int ret; + + asm ("vldr d0, [%0]" : : "r" (&d)); + asm ("vldr d1, [%0]" : : "r" (&d)); + asm (".global break_here\n" + "break_here:"); + asm ("vcmp.f64 d0, d1\n" + "vmrs APSR_nzcv, fpscr\n" + "bne L_value_different\n" + "movs %0, #0\n" + "b L_end\n" + "L_value_different:\n" + "movs %0, #1\n" + "L_end:\n" : "=3Dr" (ret) :); + + /* Return $d0 !=3D $d1. */ + return ret; + } + } + + verbose "compiling testfile $src" 2 + set lines [gdb_compile $src $exe executable $compile_flags] + file delete $src + + if ![string match "" $lines] then { + verbose "testfile compilation failed, returning 1" 2 + return 0 + } + + # No error message, compilation succeeded so now run it via gdb. + # Run the test up to 5 times to detect whether ptrace can + # correctly update VFP registers or not. + set skip_vfp_test 0 + for {set i 0} {$i < 5} {incr i} { + global gdb_prompt srcdir subdir + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load "$exe" + + runto_main + gdb_test "break *break_here" + gdb_continue_to_breakpoint "break_here" + + # Modify $d0 to a different value, so the exit code should + # be 1. + gdb_test "set \$d0 =3D 5.0" + + set test "continue to exit" + gdb_test_multiple "continue" "$test" { + -re "exited with code 01.*$gdb_prompt $" { + } + -re "exited normally.*$gdb_prompt $" { + # However, the exit code is 0. That means something + # wrong in setting VFP registers. + set skip_vfp_test 1 + break + } + } + } + + gdb_exit + remote_file build delete $exe + + return $skip_vfp_test + } return 0 } =20