From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 8063B3854540 for ; Mon, 21 Nov 2022 11:56:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8063B3854540 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669031761; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ll+cT+Poss9KY8tjDWXehdLx1s0eTcs1Svy5JR1u9N0=; b=KFF4gpb3v9LZwvU7ozxOkMP7+k2A4FF7rfMr1LkL4I1ZqGZ8wsCEWJ6zURuls24KFVMxrC GYs6+3cjW8n64npVWv7zIV6hQONcNgTFAeRL7slzQS1/8ADY1qGEl+QM1ydZrdBwzuDVJr v4P70MX5uSWaZ4RQD7xDIdoFXswo7ls= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-113-5lJfGvh6MTKppv3wFaKZxQ-1; Mon, 21 Nov 2022 06:55:59 -0500 X-MC-Unique: 5lJfGvh6MTKppv3wFaKZxQ-1 Received: by mail-wm1-f69.google.com with SMTP id m17-20020a05600c3b1100b003cf9cc47da5so6380104wms.9 for ; Mon, 21 Nov 2022 03:55:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:references :in-reply-to:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=XmiLGATWfK+1Dy5KQGPk73fQQLhTpOhiRIHe1OOr8Z0=; b=k3I23kk0jz48YJZZUWJIqF4OsVgZA+Z44+dH5n0ng63Bxzx9ySxSaJYwMN8Skzh5h2 QZwAt+JAtch/P2MvGB8NKy7y9jQ7poFmBiPGyxYI4qpsxaVGh7VS4f9pTRggxtnnhNEL 8yUdpY7HZFk5cIH1UVPU98ZxvDM7rvympeNDsx+r4uEr+zpEgURa0f1/J+l3BasYHcSB iqhcVOXQnxDN4cQ7A5jDDJgMn7n53J59085ScMDep6Xz+MSqk0KOUE2rUIJEYSl+/Rws DWt0hahuOsaHtG/+QidRFEWFI295Ubu5UkkZm+NfK5wRgYhugBg2sMT+WMLZHl4ioAsd PDQg== X-Gm-Message-State: ANoB5pl+GjZWbHSrZ5V95VAnq9c2aZpjk0t3Vgc79VIDIGCpHPW1eHof PHL17BoswpXY5H+Sfm7JtSMdP1B78GFyfyogkZdDtTsuBAlhmdV5eQVANbPbXE1QgQOgz21kti6 HayZ/NToE2vMl2NM0PEJO5g== X-Received: by 2002:a5d:6706:0:b0:241:cf90:ab1e with SMTP id o6-20020a5d6706000000b00241cf90ab1emr1120622wru.685.1669031758265; Mon, 21 Nov 2022 03:55:58 -0800 (PST) X-Google-Smtp-Source: AA0mqf7JvdopcJmz0YYt34j1k8nCeS4ARoLYKq78YTNjvB5NeiyPp2TAdq8CMYDrlOSoI81khGWoqA== X-Received: by 2002:a5d:6706:0:b0:241:cf90:ab1e with SMTP id o6-20020a5d6706000000b00241cf90ab1emr1120609wru.685.1669031757780; Mon, 21 Nov 2022 03:55:57 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id n128-20020a1ca486000000b003c70191f267sm18051569wme.39.2022.11.21.03.55.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Nov 2022 03:55:57 -0800 (PST) From: Andrew Burgess To: Dr Lancelot SIX , Asaf Fisher via Gdb-patches Cc: Asaf Fisher Subject: Re: [PATCH v3 2/2] Make GDB resolve dlopen of memory mapped shared libraries In-Reply-To: References: <20221021174205.5389-1-asaffisher.dev@gmail.com> <20221021174205.5389-2-asaffisher.dev@gmail.com> <87sfiqa9ec.fsf@redhat.com> Date: Mon, 21 Nov 2022 11:55:56 +0000 Message-ID: <87zgck7c8j.fsf@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP,WEIRD_PORT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Dr Lancelot SIX writes: > Hi Asaf and Andrew, > > Thanks for working on this! I have included comments below in the patch. > > On 10/11/2022 19:37, Andrew Burgess via Gdb-patches wrote: >> Asaf Fisher via Gdb-patches writes: >> >>> Introduced `check_proc_self_file` that checks if a path used by >>> inferior in dlopen is in the form of `/proc/self/...` and if so resolve= s >>> it to `/proc/[pid]/...` >>> >>> Bug:https://sourceware.org/bugzilla/show_bug.cgi?id=3D29586 >> Hi Asaf, >> >> Thanks for providing a fix for this, and thanks for submitting the >> copyright assignment paperwork. >> >> I took a look through your patch and ended up tweaking it a little. >> I've attached a revised version below, which I'd love to hear your >> feedback on. >> >> When making changes my goal was to extend your fix to work with >> gdbserver just like it works with native targets. You can test >> different gdbserver setups like this: >> >> make check-gdb TESTS=3D"gdb.base/solib-proc-self.exp" \ >> RUNTESTFLAGS=3D"--target_board=3Dnative-extended-gdbse= rver" >> >> This will setup gdbserver and connect GDB to it with 'target >> extended-remote', you can also test using the 'native-gdbserver' board, >> which will connect to gdbserver as just 'target remote'. >> >> Ideally any new test will pass in all three configurations (the default >> plus the two listed above), and initially, your change only fixed the >> native target case. By moving the fix elsewhere in the shared library >> loading process I think I new have all three cases working. >> >> I also extended the test to test using a 'target:' sysroot. By default >> when testing with the two gdbserver boards above, we set the sysroot to >> "" (the empty string), this tells GDB that remote files can be found on >> the local machine, and avoids all files accesses having to go over the >> remote protocol. However, given the nature of this change, I figured it >> was worth testing with the 'target:' sysroot too, this means we re-run >> the tests bu sending all file accesses over the remote protocol. That >> case is also fixed with the patch below. >> >> Where I'd most appreciate your feedback is for the algorithm by which >> the /proc/self path is spotted and converted to /proc/PID. I've cut the >> code back a bit from what you had originally, mostly because I couldn't >> find a way to test that the extra complexity was required. If you have >> any additional test cases that could show that the slimmed down code is >> not good enough, then that would be great. >> >> Thanks, >> Andrew >> >> --- >> >> commit 0bf4c98bc225c89a0a1ddcea727eca178ad69710 >> Author: Asaf Fisher >> Date: Fri Oct 21 17:42:05 2022 +0000 >> >> gdb: handle loading shared libraries from /proc/self/fd/ >> =20 >> Bug PR gdb/29586 describes a situations where a shared library is >> created in memory, then written to a memory mapped file. The memor= y >> mapped file will show up as a file descriptor within /proc/self/fd/= , >> and this path is then used with dlopen in order to call functions >> within the in-memory shared library. >> =20 >> When attempting to debug this GDB hangs. The problem is that, GDB >> stops at the shared-library event, reads the shared library path fr= om >> the inferior, which is "/proc/self/fd/", and then GDB attempts= to >> open this file. >> =20 >> Unfortunately, this means GDB tries to open a file within GDB's >> /proc/self/fd/ directory, not within the inferior's directory. In = the >> case of our hang it turns out that the file descriptor that is open= ed >> is a pipe, and GDB hangs trying to read from the pipe. >> =20 >> However, the behaviour is really just undefined, depending on which >> file descriptor the inferior tries to open, GDB will open, or fail = to >> open, random files within its /proc/self/fd directory. >> =20 >> The solution proposed in this commit is to hook into solib_find_1, = and >> spot when GDB is looking for any file in /proc/self/, if this is th= e >> case, then the filename is rewritten as /proc/, where is >> the process-id of the current inferior. >> =20 >> The test passes for the unix, native-gdbserver, and >> native-extended-gdbserver targets. When testing with either of the >> gdbserver targets, the test is run using the default empty sysroot, >> and also using the 'target:' sysroot. >> =20 >> Bug:https://sourceware.org/bugzilla/show_bug.cgi?id=3D29586 >> gdb.base/solib-proc-self.exp >> Co-authored-by: Andrew Burgess >> >> diff --git a/gdb/solib.c b/gdb/solib.c >> index 7cfdd81114c..cf2d0d3bc3a 100644 >> --- a/gdb/solib.c >> +++ b/gdb/solib.c >> @@ -83,6 +83,35 @@ show_solib_search_path (struct ui_file *file, int fro= m_tty, >> # define DOS_BASED_FILE_SYSTEM 0 >> #endif >> =20 >> +/* Fix references to files in /proc/self/fd/ when opening a shared libr= ary. >> + >> + SO_NAME is the name of the shared library being loaded. This functi= on >> + returns a possibly modified name which should be used as the path to= the >> + shared library. >> + >> + If SO_NAME starts with /proc/self, then the returned name will be >> + modified to start with /proc/PID where 'PID' is the pid of the curre= nt >> + inferior. */ >> + >> +static gdb::unique_xmalloc_ptr >> +filter_proc_self_filenames (gdb::unique_xmalloc_ptr so_name) >> +{ >> + static const char *proc_self_prefix =3D "/proc/self"; >> + >> + /* Is the path really a /proc/self? */ >> + if (!startswith (so_name.get (), proc_self_prefix)) >> + return so_name; >> + >> + /* Get the part of the path after /proc/self. For example given >> + '/proc/self/fd' we find the '/fd' part. */ >> + gdb_assert (strlen (so_name.get ()) >=3D strlen (proc_self_prefix)); > > I am not sure how this assert can ever fail as the test just before=20 > checked that so_name starts with proc_self_prefix.=C2=A0 How can it have = a=20 > smaller length? > Removed. >> + const char *tail =3D so_name.get () + strlen (proc_self_prefix); >> + >> + /* Build a replacement path. */ >> + int inferior_pid =3D inferior_ptid.pid (); >> + return xstrprintf ("/proc/%d%s", inferior_pid, tail); >> +} >> + >> /* Return the full pathname of a binary file (the main executable or a >> shared library file), or NULL if not found. If FD is non-NULL, *FD >> is set to either -1 or an open file handle for the binary file. >> @@ -172,6 +201,12 @@ solib_find_1 (const char *in_pathname, int *fd, boo= l is_solib) >> =09} >> } >> =20 >> + /* If the path starts /proc/self then rewrite this as /proc/PID using= the >> + current inferior's pid. Failing to do this will cause GDB to try = and >> + open files within its proc directory, rather than the inferiors. = */ >> + temp_pathname.reset (xstrdup (in_pathname)); >> + temp_pathname =3D filter_proc_self_filenames (std::move (temp_pathnam= e)); >> + >> /* Note, we're interested in IS_TARGET_ABSOLUTE_PATH, not >> IS_ABSOLUTE_PATH. The latter is for host paths only, while >> IN_PATHNAME is a target path. For example, if we're supposed to >> @@ -184,9 +219,7 @@ solib_find_1 (const char *in_pathname, int *fd, bool= is_solib) >> 3rd attempt, c:/foo/bar.dll =3D=3D> /sysroot/foo/bar.dll >> */ >> =20 >> - if (!IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname) || sysroot =3D=3D = NULL) >> - temp_pathname.reset (xstrdup (in_pathname)); >> - else >> + if (IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname) && sysroot !=3D NUL= L) > > Just a nit, but you could s/NULL/nullptr while at updating this line > Fixed. >> { >> bool need_dir_separator; >> =20 >> @@ -213,7 +246,7 @@ solib_find_1 (const char *in_pathname, int *fd, bool= is_solib) >> /* Cat the prefixed pathname together. */ >> temp_pathname.reset (concat (sysroot, >> =09=09=09=09 need_dir_separator ? SLASH_STRING : "", >> -=09=09=09=09 in_pathname, (char *) NULL)); >> +=09=09=09=09 temp_pathname.get (), (char *) NULL)); > Same here. Also, could nullptr make it so the "(char *)" cast becomes=20 > useless? Fixed. >> } >> =20 >> /* Handle files to be accessed via the target. */ >> diff --git a/gdb/testsuite/gdb.base/solib-proc-self.cc b/gdb/testsuite/g= db.base/solib-proc-self.cc >> new file mode 100644 >> index 00000000000..f2439d738a3 >> --- /dev/null >> +++ b/gdb/testsuite/gdb.base/solib-proc-self.cc >> @@ -0,0 +1,73 @@ >> +/* This testcase is part of GDB, the GNU debugger. >> + >> + Copyright 2022 Free Software Foundation, Inc. >> + >> + This program is free software; you can redistribute it and/or modify >> + it under the terms of the GNU General Public License as published by >> + the Free Software Foundation; either version 3 of the License, or >> + (at your option) any later version. >> + >> + This program is distributed in the hope that it will be useful, >> + but WITHOUT ANY WARRANTY; without even the implied warranty of >> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + GNU General Public License for more details. >> + >> + You should have received a copy of the GNU General Public License >> + along with this program. If not, see.= */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#ifdef __WIN32__ >> +#include >> +#define dlopen(name, mode) LoadLibrary (name) >> +#define dlclose(handle) FreeLibrary (handle) >> +#define dlerror() "an error occurred" >> +#else >> +#include >> +#endif >> + >> +int >> +main () >> +{ >> + /* Read the shared libraries contents into a buffer. */ >> + std::ifstream read_so_file =3D std::ifstream (SHLIB_NAME); >> + read_so_file.seekg (0, std::ios::end); >> + std::streamsize size =3D read_so_file.tellg (); >> + read_so_file.seekg (0, std::ios::beg); >> + std::vector buffer (size); >> + if (!read_so_file.read (buffer.data (), size)) >> + { >> + fprintf (stderr, "Failed to load solib\n"); >> + exit (1); >> + } >> + >> + /* Create a memory mapped file, then write the shared library to that >> + new memory mapped file. */ >> + int mem_fd =3D memfd_create ("test", 0); >> + write (mem_fd, buffer.data (), buffer.size ()); >> + >> + /* Generate the /proc/self/fd/[num] path for the memory mapped file. = */ >> + std::string proc_self_fd_path;=09=09/* break-here */ >> + std::stringstream proc_self_fd_path_stream >> + =3D std::stringstream (proc_self_fd_path); >> + proc_self_fd_path_stream << "/proc/self/fd/" << mem_fd; >> + >> + /* Call dlopen on it. */ >> + void *handle =3D dlopen (proc_self_fd_path_stream.str ().c_str (), RT= LD_LAZY); >> + if (!handle) >> + { >> + fprintf (stderr, "%s\n", dlerror ()); >> + exit (1); >> + } >> + /* It worked. */ >> + dlclose (handle); >> + >> + return 0; >> +} >> diff --git a/gdb/testsuite/gdb.base/solib-proc-self.exp b/gdb/testsuite/= gdb.base/solib-proc-self.exp >> new file mode 100644 >> index 00000000000..1c845822490 >> --- /dev/null >> +++ b/gdb/testsuite/gdb.base/solib-proc-self.exp >> @@ -0,0 +1,130 @@ >> +# Copyright 2022 Free Software Foundation, Inc. >> + >> +# This program is free software; you can redistribute it and/or modify >> +# it under the terms of the GNU General Public License as published by >> +# the Free Software Foundation; either version 3 of the License, or >> +# (at your option) any later version. >> +# >> +# This program is distributed in the hope that it will be useful, >> +# but WITHOUT ANY WARRANTY; without even the implied warranty of >> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> +# GNU General Public License for more details. >> +# >> +# You should have received a copy of the GNU General Public License >> +# along with this program. If not, see. = */ >> + >> +# Test connecting and disconnecting at shared library events. >> + >> +if {[skip_shlib_tests]} { >> + untested "could not run to main" >> + return 0 >> +} >> + >> +standard_testfile .cc >> + >> +# Reuse an existing library, we don't care about the library contents >> +# for this test. >> +set libfile so-disc-shr >> +set libsrc "${srcdir}/${subdir}/${libfile}.c" >> +set libname "${libfile}.so" >> +set libobj [standard_output_file ${libname}] >> + >> +# Compile the shared library. >> +if { [gdb_compile_shlib $libsrc $libobj {debug}] !=3D ""} { >> + return -1 >> +} >> + >> +# Compile the test executable. >> +if [ build_executable "failed to prepare" $testfile $srcfile \ >> +=09 [list shlib_load debug c++ additional_flags=3D-DSHLIB_NAME=3D"${lib= obj}"]] { >> + return -1 >> +} >> + >> +# Start GDB and run to the point where the test program tries to dlopen= a file >> +# from within /proc/self/fd/. Catch the shared library event and check= that >> +# we actually try to load a file from /proc//fd/. >> +# >> +# If SYSROOT is not the empty string, then this is set as the value of = GDB's >> +# sysroot immediately after starting GDB. The only value that is (curr= ently) >> +# supported, other than the empty string, is 'target:'. >> +proc do_test { {sysroot ""} } { >> + clean_restart $::binfile >> + >> + if {$sysroot !=3D ""} { >> +=09gdb_test_no_output "set sysroot ${sysroot}" >> + } >> + >> + gdb_load_shlib $::libobj >> + >> + if ![runto_main] then { >> +=09return 0 >> + } >> + >> + # Get inferior's PID for later. >> + set inferior_pid [get_inferior_pid] >> + >> + # Turn on the solib-events so we can see that gdb resolves everythi= ng >> + # correctly. >> + gdb_test_no_output "set stop-on-solib-events 1" >> + >> + # Run to the 'break-here' marker. >> + gdb_breakpoint [gdb_get_line_number "break-here"] >> + gdb_continue_to_breakpoint "break-here" ".* break-here .*" >> + >> + set memfd "" >> + gdb_test_multiple "p mem_fd" "Get file descriptor" { >> +=09-re -wrap "\\\$$::decimal =3D (\[^\r\n\]*)" { >> +=09 set memfd $expect_out(1,string) >> +=09 pass $gdb_test_name >> +=09} >> + } >> + >> + gdb_test "continue" "Stopped due to shared library event.*" \ >> +=09"continue to load" > > I've been running this patch (as modified by Andrew) and see a failure=20 > in the tests. > > (gdb) PASS: gdb.base/solib-proc-self.exp: continue to breakpoint: break-h= ere > p mem_fd > $1 =3D 4 > (gdb) PASS: gdb.base/solib-proc-self.exp: Get file descriptor > continue > Continuing. > Stopped due to shared library event: > Inferior loaded /proc/7331/fd/4 > (gdb) PASS: gdb.base/solib-proc-self.exp: continue to load > continue > Continuing. > Stopped due to shared library event (no libraries added or removed) > (gdb) FAIL: gdb.base/solib-proc-self.exp: continue > > I believe this "continue" should be removed.=C2=A0 The test passes cleanl= y=20 > without it. I looked at this failure a little, turns out, for some reason, I'm seeing two solib stop events related to the dlopen call, here's what my gdb.log looks like: ... (gdb) PASS: gdb.base/solib-proc-self.exp: continue to breakpoint: break-h= ere p mem_fd $1 =3D 4 (gdb) PASS: gdb.base/solib-proc-self.exp: Get file descriptor continue Continuing. Stopped due to shared library event (no libraries added or removed) (gdb) PASS: gdb.base/solib-proc-self.exp: continue to load continue Continuing. Stopped due to shared library event: Inferior loaded /proc/2891392/fd/4 (gdb) PASS: gdb.base/solib-proc-self.exp: continue Here's the inferior backtrace at the first (no libraries added or removed) stop: #0 0x00007ffff7fd85da in _dl_map_object_from_fd () from /lib64/ld-linux-= x86-64.so.2 #1 0x00007ffff7fdb366 in _dl_map_object () from /lib64/ld-linux-x86-64.s= o.2 #2 0x00007ffff7fe5d55 in dl_open_worker () from /lib64/ld-linux-x86-64.s= o.2 #3 0x00007ffff7ba24f8 in _dl_catch_exception () from /lib64/libc.so.6 #4 0x00007ffff7fe58fe in _dl_open () from /lib64/ld-linux-x86-64.so.2 #5 0x00007ffff7f8c39c in dlopen_doit () from /lib64/libdl.so.2 #6 0x00007ffff7ba24f8 in _dl_catch_exception () from /lib64/libc.so.6 #7 0x00007ffff7ba25c3 in _dl_catch_error () from /lib64/libc.so.6 #8 0x00007ffff7f8cb09 in _dlerror_run () from /lib64/libdl.so.2 #9 0x00007ffff7f8c42a in dlopen@@GLIBC_2.2.5 () from /lib64/libdl.so.2 #10 0x0000000000402555 in main () at /tmp/build/gdb/testsuite/../../../sr= c/gdb/testsuite/gdb.base/solib-proc-self.cc:63 And the backtrace at the second stop: #0 0x00007ffff7fe60a8 in dl_open_worker () from /lib64/ld-linux-x86-64.s= o.2 #1 0x00007ffff7ba24f8 in _dl_catch_exception () from /lib64/libc.so.6 #2 0x00007ffff7fe58fe in _dl_open () from /lib64/ld-linux-x86-64.so.2 #3 0x00007ffff7f8c39c in dlopen_doit () from /lib64/libdl.so.2 #4 0x00007ffff7ba24f8 in _dl_catch_exception () from /lib64/libc.so.6 #5 0x00007ffff7ba25c3 in _dl_catch_error () from /lib64/libc.so.6 #6 0x00007ffff7f8cb09 in _dlerror_run () from /lib64/libdl.so.2 #7 0x00007ffff7f8c42a in dlopen@@GLIBC_2.2.5 () from /lib64/libdl.so.2 #8 0x0000000000402555 in main () at /tmp/build/gdb/testsuite/../../../sr= c/gdb/testsuite/gdb.base/solib-proc-self.cc:63 I'm going to fold the two continue calls together into a gdb_test_multiple, but I'll also dig into why I see two stop events, maybe there's a GDB issue here. Thanks, Andrew > > Best, > Lancelot. > >> + >> + # Check if inferior resolved the /proc/self/fd/[num] to /proc/[pid]= /fd/[num]. >> + gdb_test "continue" \ >> +=09[multi_line \ >> +=09 "Stopped due to shared library event:" \ >> +=09 " Inferior loaded (?:target:)?/proc/${inferior_pid}/fd/$memfd"= ] >> +} >> + >> +# First run of the test. >> +do_test >> + >> +# Possible second run of the test. If we are using a remote target the= n we >> +# should consider setting the sysroot to 'target:' and re-running the t= est. >> +if {[target_info exists gdb_protocol] >> + && ([target_info gdb_protocol] =3D=3D "remote" >> +=09|| [target_info gdb_protocol] =3D=3D "extended-remote")} { >> + # GDB will already be running after the first call to do_test, so w= e can >> + # take a peek at the current sysroot setting, and decide if we shou= ld >> + # repeat the test with a different setting. >> + >> + set new_sysroot "" >> + gdb_test_multiple "show sysroot" "" { >> +=09-wrap -re "The current system root is \"\"\\." { >> +=09 pass $gdb_test_name >> + >> +=09 # Repeat the test with 'target:' sysroot. >> +=09 set new_sysroot "target:" >> +=09} >> +=09-wrap -re "The current system root is \"target:\"\\." { >> +=09 pass $gdb_test_name >> + >> +=09 # Nothing else to do, we already tested with target: sysroot. >> +=09} >> +=09-re "$gdb_prompt $" { >> +=09 pass $gdb_test_name >> + >> +=09 # If already testing with any other sysroot, we probably should >> +=09 # not try to adjust things, so don't do any further testing. >> +=09} >> + } >> + >> + with_test_prefix "sysroot $new_sysroot" { >> +=09if { $new_sysroot !=3D "" } { >> +=09 do_test $new_sysroot >> +=09} >> + } >> +} >>