From patchwork Fri Nov 18 16:42:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 60840 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EB105384D9BB for ; Fri, 18 Nov 2022 16:43:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EB105384D9BB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668789833; bh=RowFyS30cFNkFkTCrfGg3xwPxZjPBleOywcZowwjeB8=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=wfho7802LPGJjiENgilEJ//FIC9mWnE4e6v1XSBFvT0gmZCnMWlk8c+EF7mOBMGDj nIBKCkc1qFVvTgaMB+H/f/HYhCqRGHreNPUqakStSGon2gZ2c4VY9HaJaKjSd12Vpm pRn8f9GXuU0qt7BSYMYvKF3hPJYgIfJyeGsd8trM= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 66C6D3852C63 for ; Fri, 18 Nov 2022 16:43:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 66C6D3852C63 Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-122-T8c3nib4MJGkggGA43Ynww-1; Fri, 18 Nov 2022 11:43:15 -0500 X-MC-Unique: T8c3nib4MJGkggGA43Ynww-1 Received: by mail-wr1-f69.google.com with SMTP id v14-20020adf8b4e000000b0024174021277so1792299wra.13 for ; Fri, 18 Nov 2022 08:43:14 -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:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RowFyS30cFNkFkTCrfGg3xwPxZjPBleOywcZowwjeB8=; b=ods3H5ZeG6Tkn62aWwwvAo0MgKxtwFMOIC2gkm7QapjVWg+52QicEMS+oixGEbG8tV ww+7Kf6RjXpNBtc4IOf+oidUiQO6SYoalOL/cGRRbPmJ2d/MXBmyNgzuZjgwfjQtsbff 1fjpfUVoqvgPjcXIBUEJuubxTl67jp6n+042bul5EXfLP3qAtryOKtDiwH0AGzbN/oRy D5NT88irOyWJOQIVC6H7rmjxko9UwSTTmS7cyGKeo05YRDkQ6gL2WO0zzSzWH+kfQPkd z849A9nmkwIPJbSpG3BRhxzXBTiD53v3cGo+afy2z0E865R6MByQIBkNUm7dl0zkjeaR oVZg== X-Gm-Message-State: ANoB5plkLxXqltm0W/hDPDZylTQ+vQUynx6QVCjIl3sNc30Tt84KYWnH ZYgqqJ8ne9Q75eKFcO5fvnrlTkHRaeFC49hWPrCLw7wr1DvwAyRLWV8qOL1xyL1uSQ3IBZXTE1k 5Ov62W4yp6a73TjKCyjroBaP7UR3L1iXFAdygBLftup7sdDCdFQ7B1N/G+hN+OHaGUqA+xx5GIw == X-Received: by 2002:a05:600c:292:b0:3cf:8203:1761 with SMTP id 18-20020a05600c029200b003cf82031761mr5704926wmk.64.1668789793222; Fri, 18 Nov 2022 08:43:13 -0800 (PST) X-Google-Smtp-Source: AA0mqf7AlQ4J5h0sQl+MgcE9y5Od8C94TNg2ATbl2DPNKVKbTz5IuEO/oWFPuLrfHaPmQ8pgRMjGug== X-Received: by 2002:a05:600c:292:b0:3cf:8203:1761 with SMTP id 18-20020a05600c029200b003cf82031761mr5704889wmk.64.1668789792552; Fri, 18 Nov 2022 08:43:12 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id l12-20020a05600c2ccc00b003cf54b77bfesm9600219wmc.28.2022.11.18.08.43.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 08:43:12 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 7/7] gdb: some process_stratum_target should not be shared Date: Fri, 18 Nov 2022 16:42:58 +0000 Message-Id: <577f2c47793acb501c2611c0e6c7ea379f774830.1668789658.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com 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 autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" When multi-target support was added to GDB, an assumption was made that all process_stratum_target sub-classes could be shared by multiple inferiors. For things like the Linux and FreeBSD native targets, as well as the remote target, this is absolutely true (or was made true). But some targets were never updated to be shareable, for example, the core_target, which is used when reading core-files, stores some of its state in the program_space, but also, the core-file and the executable being debugged are closely related. As each add-inferior call creates an inferior with a new program_space, and doesn't automatically copy the executable, or the current core-file, I don't think it really makes sense to "share" core_target objects between inferiors. Consider this session: $ gdb -q (gdb) file test1 Reading symbols from test1... (gdb) core-file core.test1.433190 [New LWP 433190] Core was generated by `./test1'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000000000401111 in foo () at test1.c:6 6 return *global_ptr; (gdb) add-inferior [New inferior 2] Added inferior 2 on connection 1 (core) (gdb) info inferiors Num Description Connection Executable * 1 process 433190 1 (core) /tmp/multi-core/test1 2 1 (core) (gdb) info connections Num What Description * 1 core Local core dump file (gdb) inferior 2 [Switching to inferior 2 [] ()] (gdb) file test2 Reading symbols from test2... (gdb) core-file core.test2.433203 [New LWP 433203] Core was generated by `./test2'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000000000401111 in main () at test2.c:6 6 return *global_ptr; (gdb) info inferiors Num Description Connection Executable 1 process 433190 1 (core) /tmp/multi-core/test1 * 2 process 433203 2 (core) /tmp/multi-core/test2 (gdb) info connections Num What Description 1 core Local core dump file * 2 core Local core dump file (gdb) After the 'add-inferior' the core_target connection is shared between the inferiors. However, as soon as the user sets up the core-file and executable in the new inferior a new core connection has been created. I think this behaviour might be confusing, so I'd like to have GDB not initially share the core connection. Instead, when the user tries to add the new inferior a warning is given, and the new inferior is created without a connection, like this: $ gdb -q (gdb) file test1 Reading symbols from test1... (gdb) core-file core.test1.433190 [New LWP 433190] Core was generated by `./test1'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000000000401111 in foo () at test1.c:6 6 return *global_ptr; (gdb) add-inferior [New inferior 2] warning: can't share connection 1 (core) between inferiors Added inferior 2 (gdb) info inferiors Num Description Connection Executable * 1 process 433190 1 (core) /tmp/multi-core/test1 2 (gdb) If the user explicitly asks for the new inferior to be created without a connection, then no warning will be given. At this point the user is free to setup inferior 2 with a different executable and core file (or to do anything they like with the inferior). In an earlier version of this patch I had GDB error instead of giving a warning. However, the error message ended up being something like: can't share connection ..... between inferiors, use -no-connection option to create an inferior without sharing a connection. but it seemed better to just create the inferior. I've updated the docs, and added a NEWS entry for the new warning. In the docs for clone-inferior I've added reference to -no-connection, which was previously missing. --- gdb/NEWS | 7 + gdb/corelow.c | 5 + gdb/doc/gdb.texinfo | 37 +++- gdb/inferior.c | 16 ++ gdb/inferior.h | 6 +- gdb/target.c | 14 ++ gdb/target.h | 8 + gdb/testsuite/gdb.multi/multi-core-files-1.c | 37 ++++ gdb/testsuite/gdb.multi/multi-core-files-2.c | 31 ++++ gdb/testsuite/gdb.multi/multi-core-files.exp | 172 +++++++++++++++++++ 10 files changed, 329 insertions(+), 4 deletions(-) create mode 100644 gdb/testsuite/gdb.multi/multi-core-files-1.c create mode 100644 gdb/testsuite/gdb.multi/multi-core-files-2.c create mode 100644 gdb/testsuite/gdb.multi/multi-core-files.exp diff --git a/gdb/NEWS b/gdb/NEWS index 8176940ae1a..5c8dac12de7 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -81,6 +81,13 @@ * New convenience variable $_inferior_thread_count contains the number of live threads in the current inferior. +* The add-inferior, clone-inferior, and MI -add-inferior commands will + now give a warning, and create the new inferior without a + connection, when the current inferior, at the time the command is + given, is a core-file target. The core-file target could never + really be shared between inferiors, GDB is now more vocal about what + is going on. + * New commands maintenance set ignore-prologue-end-flag on|off diff --git a/gdb/corelow.c b/gdb/corelow.c index 293bc8d4f59..4d8393a3587 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -128,6 +128,11 @@ class core_target final : public process_stratum_target /* See definition. */ void info_proc_mappings (struct gdbarch *gdbarch); + /* The core_target only works for the inferior in which it was initially + opened, and can't be copied to some other inferior's target_stack. */ + bool is_shareable () override + { return false; } + private: /* per-core data */ /* Get rid of the core inferior. */ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 566da9e7d92..bb33e60a22e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -3358,8 +3358,31 @@ remote} command to connect to some other @code{gdbserver} instance, use @code{run} to spawn a local program, etc. +Not all connections can be shared between inferiors. For example, the +@code{target core} target is unique for each inferior. That is, +multiple inferiors can use @code{target core} at the same time, but +each @code{target core} is different. If you try to +@code{add-inferior}, and the current inferior is @code{target core}, +then @value{GDBN} will give a warning and create the new inferior +without a connection, like this: + +@smallexample +(@value{GDBP}) file test1 +Reading symbols from test1... +(@value{GDBP}) target core core.test1.433190 +[New LWP 433190] +Core was generated by `./test1'. +Program terminated with signal SIGSEGV, Segmentation fault. +#0 0x0000000000401111 in foo () at test1.c:6 +6 return *global_ptr; +(@value{GDBP}) add-inferior +[New inferior 2] +warning: can't share connection 1 (core) between inferiors +Added inferior 2 +@end smallexample + @kindex clone-inferior -@item clone-inferior [ -copies @var{n} ] [ @var{infno} ] +@item clone-inferior [ -copies @var{n} ] [ -no-connection ] [ @var{infno} ] Adds @var{n} inferiors ready to execute the same program as inferior @var{infno}; @var{n} defaults to 1, and @var{infno} defaults to the number of the current inferior. This command copies the values of the @@ -3384,6 +3407,13 @@ You can now simply switch focus to inferior 2 and run it. +Like @code{add-inferior}, @code{clone-inferior} shares the connection +with the inferior @var{infno}. If the @var{-no-connection} option is +given, then the new inferior will be created without a connection. If +the connection of inferior @var{infno} can't be shared, then +@value{GDBN} will give a warning, and the new inferior will be created +without a connection. + @kindex remove-inferiors @item remove-inferiors @var{infno}@dots{} Removes the inferior or inferiors @var{infno}@dots{}. It is not @@ -37828,6 +37858,11 @@ @code{gdbserver} instance, use @code{-exec-run} to spawn a local program, etc. +If the connection of the current inferior cannot be shared, e.g.@: the +@code{-target-select core} target cannot be shared between inferiors, +then @value{GDBN} will give a warning and create the new inferior +without a connection. + The command response always has a field, @var{inferior}, whose value is the identifier of the thread group corresponding to the new inferior. diff --git a/gdb/inferior.c b/gdb/inferior.c index f4b9828a425..ec4c348f7e3 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -816,6 +816,22 @@ switch_to_inferior_and_push_target (inferior *new_inf, symbols. */ switch_to_inferior_no_thread (new_inf); + if (!no_connection && proc_target != nullptr + && !proc_target->is_shareable ()) + { + if (proc_target->connection_string () != nullptr) + warning (_("can't share connection %d (%s %s) between inferiors"), + proc_target->connection_number, + proc_target->shortname (), + proc_target->connection_string ()); + else + warning (_("can't share connection %d (%s) between inferiors"), + proc_target->connection_number, + proc_target->shortname ()); + + proc_target = nullptr; + } + /* Reuse the target for new inferior. */ if (!no_connection && proc_target != NULL) { diff --git a/gdb/inferior.h b/gdb/inferior.h index 2917f42e624..a312cd2b9bb 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -759,9 +759,9 @@ extern struct inferior *add_inferior_with_spaces (void); /* Print the current selected inferior. */ extern void print_selected_inferior (struct ui_out *uiout); -/* Switch to inferior NEW_INF, a new inferior, and unless - NO_CONNECTION is true, push the process_stratum_target of ORG_INF - to NEW_INF. */ +/* Switch to inferior NEW_INF, a new inferior, and unless NO_CONNECTION is + true, or the process_stratum_target of ORG_INF is not shareable, push + the process_stratum_target of ORG_INF to NEW_INF. */ extern void switch_to_inferior_and_push_target (inferior *new_inf, bool no_connection, inferior *org_inf); diff --git a/gdb/target.c b/gdb/target.c index b2af51551ba..ac0608645b4 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1187,6 +1187,12 @@ target_stack::push (target_ops *t) if (m_stack[stratum].get () != nullptr) unpush (m_stack[stratum].get ()); + /* If this target can't be shared, then check that the target doesn't + already appear on some other target stack. */ + if (!t->is_shareable ()) + for (inferior *inf : all_inferiors ()) + gdb_assert (!inf->target_is_pushed (t)); + /* Now add the new one. */ m_stack[stratum] = std::move (ref); @@ -3221,6 +3227,14 @@ target_ops::fileio_readlink (struct inferior *inf, const char *filename, /* See target.h. */ +bool +target_ops::is_shareable () +{ + return true; +} + +/* See target.h. */ + int target_fileio_open (struct inferior *inf, const char *filename, int flags, int mode, bool warn_if_slow, fileio_error *target_errno) diff --git a/gdb/target.h b/gdb/target.h index 547ee8a3bbd..30e5085a543 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -1321,6 +1321,14 @@ struct target_ops virtual bool store_memtags (CORE_ADDR address, size_t len, const gdb::byte_vector &tags, int type) TARGET_DEFAULT_NORETURN (tcomplain ()); + + /* Return true if this target can be shared on multiple target_stacks, + or false if this target should only appear on a single target_stack. + When this function returns false multiple separate instances of the + same target_ops sub-class can still appear on different + target_stacks, but the same concrete instance can only appear on a + single target_stack. */ + virtual bool is_shareable (); }; /* Deleter for std::unique_ptr. See comments in diff --git a/gdb/testsuite/gdb.multi/multi-core-files-1.c b/gdb/testsuite/gdb.multi/multi-core-files-1.c new file mode 100644 index 00000000000..f996973023e --- /dev/null +++ b/gdb/testsuite/gdb.multi/multi-core-files-1.c @@ -0,0 +1,37 @@ +/* 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 + +int +bar () +{ + abort (); + return 0; +} + +int +baz () +{ + return bar (); +} + +int +main () +{ + return baz (); +} diff --git a/gdb/testsuite/gdb.multi/multi-core-files-2.c b/gdb/testsuite/gdb.multi/multi-core-files-2.c new file mode 100644 index 00000000000..fb99e137c3f --- /dev/null +++ b/gdb/testsuite/gdb.multi/multi-core-files-2.c @@ -0,0 +1,31 @@ +/* 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 + +int +foo () +{ + abort (); + return 0; +} + +int +main () +{ + return foo (); +} diff --git a/gdb/testsuite/gdb.multi/multi-core-files.exp b/gdb/testsuite/gdb.multi/multi-core-files.exp new file mode 100644 index 00000000000..8c2610000a0 --- /dev/null +++ b/gdb/testsuite/gdb.multi/multi-core-files.exp @@ -0,0 +1,172 @@ +# 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 . + +# This script runs some basic tests that GDB can support multiple +# inferiors each debugging different core files. +# +# We also check the behaviour of GDB if the user attempts to clone or +# duplicate an inferior that is debugging a core file. + +standard_testfile -1.c -2.c + +set binfile1 "${binfile}-1" +set binfile2 "${binfile}-2" + +if {[build_executable "build first executable" $binfile1 $srcfile \ + debug] == -1} { + untested "failed to compile first executable" + return -1 +} + +if {[build_executable "build second executable" $binfile2 $srcfile2 \ + debug] == -1} { + untested "failed to compile second executable" + return -1 +} + +set corefile1 [core_find $binfile1] +set corefile2 [core_find $binfile2] +if { $corefile1 == "" || $corefile2 == "" } { + untested "Can't generate core files" + return +} + +# Start GDB, and load the first executable and corefile into the first +# inferior. +clean_restart ${binfile1} +gdb_test "core-file $corefile1" "Program terminated with .*" \ + "load core file" +gdb_test "bt" "bar \\(\\) at .*" \ + "check backtrace in inferior 1" + +# The native-extended-remote board connects to the remote target as +# soon as GDB is started, this means that connection 1 is to the +# remote target, and the core target we create below will be +# connection 2. +# +# In all other cases, the core target gets to be connection 1. +if { [target_info gdb_protocol] == "extended-remote"} { + set conn_num 2 +} else { + set conn_num 1 +} + +# Try to use add-inferior and clone-inferior to create new +# inferiors. In both cases this will try to share the core_target +# between inferior 1 and the new inferior. As the core_target can't +# be shared we should get a warning, and the inferior should be +# created without a connection. +gdb_test "add-inferior" \ + [multi_line \ + "\\\[New inferior 2\\\]" \ + "warning: can't share connection ${conn_num} \\(core\\) between inferiors" \ + "Added inferior 2"] +gdb_test "clone-inferior" \ + [multi_line \ + "\\\[New inferior 3\\\]" \ + "warning: can't share connection ${conn_num} \\(core\\) between inferiors" \ + "Added inferior 3"] + +# Check the MI -add-inferior command. Do this using interpreter-exec. +# We're not doing a full MI test here, just checking this one command. +gdb_test "interpreter-exec mi \"-add-inferior\"" \ + [multi_line \ + "~\"\\\[New inferior 4\\\]..\"" \ + "&\"warning: can't share connection ${conn_num} \\(core\\) between inferiors..\"" \ + "~\"Added inferior 4..\"" \ + "\\^done,inferior=\"\[^\"\]+\""] + +# Now check that none of the new inferiors have a connection. +gdb_test "info inferiors" \ + [multi_line \ + "\\*\\s+1\\s+\[^\r\n\]+\\s+${conn_num} \\(core\\)\\s+\[^\r\n\]+.*" \ + "\\s+2\\s+\\s+" \ + "\\s+3\\s+\\s+\[^\r\n\]+" \ + "\\s+4\\s+\\s+"] \ + "first info inferiors call" + +# Now use add-inferior and clone-inferior but this time with the +# -no-connection option, this should avoid issuing the warning. We +# also use interpreter-exec to test the MI version of this command. +gdb_test "add-inferior -no-connection" \ + [multi_line \ + "\\\[New inferior 5\\\]" \ + "Added inferior 5"] +gdb_test "clone-inferior -no-connection" \ + [multi_line \ + "\\\[New inferior 6\\\]" \ + "Added inferior 6"] +gdb_test "interpreter-exec mi \"-add-inferior --no-connection\"" \ + "\\\[New inferior 7\\\].*Added inferior 7.*" + +# Now check that none of the new inferiors have a connection. +gdb_test "info inferiors" \ + [multi_line \ + "\\*\\s+1\\s+\[^\r\n\]+\\s+${conn_num} \\(core\\)\\s+\[^\r\n\]+.*" \ + "\\s+2\\s+\\s+" \ + "\\s+3\\s+\\s+\[^\r\n\]+" \ + "\\s+4\\s+\\s+" \ + "\\s+5\\s+\\s+" \ + "\\s+6\\s+\\s+\[^\r\n\]+" \ + "\\s+7\\s+\\s+"] \ + "second info inferiors call" + +# Check after all the new inferiors have been created that we still +# only have a single connection. +gdb_test "info connections" \ + "\\*\\s+${conn_num}\\s+\\s+core\\s+Local core dump file\\s*" + +# Now switch to inferior 2 and load the second executable and core +# file. Check the backtrace for the presence of function 'foo', this +# indicates we are seeing the correct core file. +gdb_test "inferior 2" "Switching to inferior 2 .*" +gdb_test "file $binfile2" \ + "Reading symbols from .*" \ + "Loaded second test binary" +gdb_test "core-file $corefile2" \ + "Program terminated with signal SIGABRT, Aborted.*" \ + "Loaded second core file" +gdb_test "bt" "foo \\(\\) at .*" \ + "check backtrace in inferior 2" + +# Switch to inferior 3, this one was cloned from inferior 1, so is +# already debugging the first binary file. Check its backtrace for +# 'bar', which indicates we are debugging the correct core file. +gdb_test "inferior 3" "Switching to inferior 3 .*" +gdb_test "core-file $corefile1" \ + "Program terminated with signal SIGABRT, Aborted.*" \ + "Loaded first core file into inferior 3" +gdb_test "bt" "bar \\(\\) at .*" \ + "check backtrace in inferior 3" + +# Detach from some of the core files and delete some of the inferiors. +gdb_test "detach" "No core file now\\." \ + "detach from inferior 3 core file" +gdb_test "inferior 2" "Switching to inferior 2 .*" \ + "switch back to inferior 2" +gdb_test_no_output "remove-inferiors 3 4" + +# Now detach in inferior 2, and delete the inferior. +gdb_test "detach" "No core file now\\." \ + "detach from inferior 2 core file" +gdb_test "inferior 1" "Switching to inferior 1 .*" \ + "switch back to inferior 1" +gdb_test_no_output "remove-inferiors 2" + +# Finally, check that inferior 1 backtrace is still working. +gdb_test "bt" "bar \\(\\) at .*" \ + "check backtrace in inferior 1 again" +gdb_test "detach" "No core file now\\." \ + "detach from inferior 1 core file"