From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id AIa0Aeyu0WZ9+BkAWB0awg (envelope-from ) for ; Fri, 30 Aug 2024 07:37:16 -0400 Authentication-Results: simark.ca; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=bUPnwPrT; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 000B51E0D0; Fri, 30 Aug 2024 07:37:15 -0400 (EDT) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id DE5831E08C for ; Fri, 30 Aug 2024 07:37:13 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 96BFC385842A for ; Fri, 30 Aug 2024 11:37:13 +0000 (GMT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 8F1F63861825 for ; Fri, 30 Aug 2024 11:34:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8F1F63861825 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8F1F63861825 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725017664; cv=none; b=k4bFAwHa7qSzgXl65agy0A8zWXl6OXSY0jTLykVpwBiEbOx2wGzoCaSIfhc2MIF8IZiXnw609b3bP/vVfY8WGksea7cUKx5WsQ6P7LyhdMxS6X4MxO2y8c6bZ2cNAYF2RwBLC5iNAcBJ/O0r6eIOrNQCqrYpJjtEsbVRXBgFSTI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725017664; c=relaxed/simple; bh=vy4DlsJknzLQMVFR0d0q4a8xJYdY37NYUkDrsq2qzi0=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=lFXVXulad0uGtcWnFc10ynfQdSW359W2DiK2GUmlzLYgx8a+HeBY6ENyYQZLO+NP3G64ZzyLdoSw8Ue4j4WyYiqSu2X+EnirACYy7kDJ53+Ej2cl0z370JoTg3dyvFtRdXdV1zPOwzRQn1LvCP7E5R//PN7VJVIZebQ+OzPh1wY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1725017660; 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=aprrt7HAFUQuLwEI1kgX5tAEnvUFr43UGOCdUQwBTB0=; b=bUPnwPrT9U6hJ1UjvbqtI+loW5l4RVc1DfRpDYFqozYfk8xHfO0ikgbY+XGeyxs3Ssomm9 leCPK43UbEQdGAdy9AftkQ7NiheZp5pRAh9bCampl3o+vgW15p6XidxJ3Nmx0k0rAa4V1o yV4sWSyDgLBYcN0faOarNoQCd+cJVUY= Received: from mail-ej1-f72.google.com (mail-ej1-f72.google.com [209.85.218.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-641-tWp5vv2iPd2GS-VUHrYXbw-1; Fri, 30 Aug 2024 07:34:19 -0400 X-MC-Unique: tWp5vv2iPd2GS-VUHrYXbw-1 Received: by mail-ej1-f72.google.com with SMTP id a640c23a62f3a-a868b6d6882so236031666b.1 for ; Fri, 30 Aug 2024 04:34:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725017657; x=1725622457; 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=hBOccLCiS6MWn7FkTkgBMCZ37AV+ErudbFcV12PDnWA=; b=d3FaMOT9KK5SZlRpiHIOATjGHAF68BNtQQhSZB1GwT+MeTy1chfOuQgcChwqANy9SH I5d0oupkBv5GAAKI8yJoLoRoAV0MRrQGPONLM0le9CkmLyHzyazYkLoQ+bC8XCNmcY4U izWjc2eFgGBpV3QpYOZvd8xQh7SJHQuUcfpcFVQwgl2zA2Aunl6AE+z480iZKJ1BF4D2 eK6tK/9Ikz0Fgy/LpEe+IXEGySCAg7bnykIvl4Lu75OFw3HyN6FOE6WVn3t+W+df76i0 rBBL7CeHUPvA0mc8lchfj14CmfOh6eltDx8g1N2TOw+rs7lc5XjRrxoqgkuYBiFFVsN5 FJWA== X-Gm-Message-State: AOJu0YyX/Ee6MzTnPg4xvNmUbsc6k7tUaHp18aU4FBfSuMwsX+S7v12q 8k7i8a/SSCMe3/MO5oQpDa5BSfoA5QyjvdgGXdKkT4roqVvZVZ2OvhuKykco2dxK9gfQe+PI9ju 4YQhJt2w6vwzcyO4kYtSDrZ1JfXjFHyLjykVXQjKu1cbk0SkldXJBsxXgxhwYupni8SzzDIpOKP bAwMQPNzATP296CYtrStMnlzXBrIZEjIzI6my6YnpgkWQ= X-Received: by 2002:a17:907:7248:b0:a77:ca3b:996c with SMTP id a640c23a62f3a-a89a267a567mr238991766b.16.1725017656900; Fri, 30 Aug 2024 04:34:16 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEdotjpnQXBw13tyJDvkmLkLj86wAnVkl+/xAEBBFzknTPws8RJoxgeJrWLqFa3umFTGyw2fA== X-Received: by 2002:a17:907:7248:b0:a77:ca3b:996c with SMTP id a640c23a62f3a-a89a267a567mr238985166b.16.1725017655693; Fri, 30 Aug 2024 04:34:15 -0700 (PDT) Received: from localhost (178.126.90.146.dyn.plus.net. [146.90.126.178]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a8989215cb5sm204474866b.191.2024.08.30.04.34.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Aug 2024 04:34:14 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess , Eli Zaretskii Subject: [PATCHv6 12/14] gdb: add remove-symbol-file command completion Date: Fri, 30 Aug 2024 12:33:52 +0100 Message-Id: <8fd409d238c3b223c6aef56f36d513c85908d781.1725017349.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 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-9.1 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org The 'remove-symbol-file' command doesn't currently offer command completion. This commit addresses this. The 'remove-symbol-file' uses gdb_argv to split its command arguments, this means that the filename the command expects can be quoted. However, the 'remove-symbol-file' command is a little weird in that it also has a '-a' option, if this option is passed then the command expects not a filename, but an address. Currently the remove_symbol_file_command function splits the command args using gdb_argv, checks for a '-a' flag by looking at the first argument value, and then expects the filename or address to occupy a single entry in the gdb_argv array. The first thing I do is handle the '-a' flag using GDB's option system. I model this option as a flag_option_def (a boolean option). I've dropped the use of gdb_argv and instead use the new(ish) function extract_single_filename_arg, which was added a couple of commits back, to parse the filename argument (when '-a' is not given). If '-a' is given the the remove-symbol-file command expects an address rather than a filename. As we previously split the arguments using gdb_argv this meant the address needed to appear as a single argument. So a user could write: (gdb) remove-symbol-file 0x1234 Or they could write: (gdb) remove-symbol-file some_function Both of these would work fine. But a user could not write: (gdb) remove-symbol-file some_function + 0x1000 As only the 'some_function' part would be processed. Now the user could do this: (gdb) remove-symbol-file "some_function + 0x1000" By enclosing the address expression in quotes this would be handled as a single argument. However, this is a little weird, that's not how commands like 'print' or 'x' work. Also this functionality was neither documented, or tested. And so, in this commit, by removing the use of gdb_argv I bring the 'remove-symbol-file' command inline with GDB's other commands that take an expression, the quotes are no longer needed. Usually in a completer we call 'complete_options', but don't actually capture the option values. But for remove-symbol-file I do. This allows me to spot when the '-a' option has been given, I can then complete the rest of the command line as either a filename or an expression. Reviewed-By: Eli Zaretskii --- gdb/NEWS | 10 + gdb/doc/gdb.texinfo | 1 + gdb/symfile.c | 114 ++++++-- .../gdb.base/filename-completion.exp | 3 +- gdb/testsuite/gdb.base/sym-file.exp | 258 ++++++++++-------- 5 files changed, 238 insertions(+), 148 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 2f5d5ebbcef..8b3b4f13762 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -53,6 +53,16 @@ maintenance info blocks [ADDRESS] are listed starting at the inner global block out to the most inner block. +* Changed commands + +remove-symbol-file + This command now supports file-name completion. + +remove-symbol-file -a ADDRESS + The ADDRESS expression can now be a full expression consisting of + multiple terms, e.g. 'function + 0x1000' (without quotes), + previously only a single term could be given. + * New remote packets vFile:stat diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 8cde2f22637..67e36fbc442 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -21893,6 +21893,7 @@ (@value{GDBP}) @end smallexample +The @var{address} can be any expression which evaluates to an address. @code{remove-symbol-file} does not repeat if you press @key{RET} after using it. diff --git a/gdb/symfile.c b/gdb/symfile.c index 5054d101cd5..2292ecaf344 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -2330,39 +2330,90 @@ add_symbol_file_command (const char *args, int from_tty) } +/* Option support for 'remove-symbol-file' command. */ + +struct remove_symbol_file_options +{ + /* True when the '-a' flag was passed. */ + bool address_flag = false; +}; + +using remove_symbol_file_options_opt_def + = gdb::option::flag_option_def; + +static const gdb::option::option_def remove_symbol_file_opt_defs[] = { + remove_symbol_file_options_opt_def { + "a", + [] (remove_symbol_file_options *opt) { return &opt->address_flag; }, + N_("Select a symbol file containing ADDRESS.") + }, +}; + +static inline gdb::option::option_def_group +make_remove_symbol_file_def_group (remove_symbol_file_options *opts) +{ + return {{remove_symbol_file_opt_defs}, opts}; +} + +/* Completion function for 'remove-symbol-file' command. */ + +static void +remove_symbol_file_command_completer (struct cmd_list_element *ignore, + completion_tracker &tracker, + const char *text, const char * /* word */) +{ + /* Unlike many command completion functions we do gather the option + values here. How we complete the rest of the command depends on + whether the '-a' flag has been given or not. */ + remove_symbol_file_options opts; + auto grp = make_remove_symbol_file_def_group (&opts); + if (gdb::option::complete_options + (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp)) + return; + + /* Complete the rest of the command line as either a filename or an + expression (which will evaluate to an address) if the '-a' flag was + given. */ + if (!opts.address_flag) + { + const char *word + = advance_to_filename_maybe_quoted_complete_word_point (tracker, text); + filename_maybe_quoted_completer (ignore, tracker, text, word); + } + else + { + const char *word + = advance_to_expression_complete_word_point (tracker, text); + symbol_completer (ignore, tracker, text, word); + } +} + /* This function removes a symbol file that was added via add-symbol-file. */ static void remove_symbol_file_command (const char *args, int from_tty) { - struct objfile *objf = NULL; - struct program_space *pspace = current_program_space; - dont_repeat (); - if (args == NULL) - error (_("remove-symbol-file: no symbol file provided")); + remove_symbol_file_options opts; + auto grp = make_remove_symbol_file_def_group (&opts); + gdb::option::process_options + (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp); - gdb_argv argv (args); + struct objfile *objf = nullptr; - if (strcmp (argv[0], "-a") == 0) + if (opts.address_flag) { - /* Interpret the next argument as an address. */ - CORE_ADDR addr; + if (args == nullptr || *args == '\0') + error (_("remove-symbol-file: no address provided")); - if (argv[1] == NULL) - error (_("Missing address argument")); - - if (argv[2] != NULL) - error (_("Junk after %s"), argv[1]); - - addr = parse_and_eval_address (argv[1]); + CORE_ADDR addr = parse_and_eval_address (args); for (objfile *objfile : current_program_space->objfiles ()) { if ((objfile->flags & OBJF_USERLOADED) != 0 && (objfile->flags & OBJF_SHARED) != 0 - && objfile->pspace () == pspace + && objfile->pspace () == current_program_space && is_addr_in_objfile (addr, objfile)) { objf = objfile; @@ -2370,21 +2421,18 @@ remove_symbol_file_command (const char *args, int from_tty) } } } - else if (argv[0] != NULL) + else { - /* Interpret the current argument as a file name. */ - - if (argv[1] != NULL) - error (_("Junk after %s"), argv[0]); - - gdb::unique_xmalloc_ptr filename (tilde_expand (argv[0])); + std::string filename = extract_single_filename_arg (args); + if (filename.empty ()) + error (_("remove-symbol-file: no symbol file provided")); for (objfile *objfile : current_program_space->objfiles ()) { if ((objfile->flags & OBJF_USERLOADED) != 0 && (objfile->flags & OBJF_SHARED) != 0 - && objfile->pspace () == pspace - && filename_cmp (filename.get (), objfile_name (objfile)) == 0) + && objfile->pspace () == current_program_space + && filename_cmp (filename.c_str (), objfile_name (objfile)) == 0) { objf = objfile; break; @@ -3830,14 +3878,22 @@ READNOW_READNEVER_HELP), &cmdlist); set_cmd_completer (c, filename_maybe_quoted_completer); - c = add_cmd ("remove-symbol-file", class_files, - remove_symbol_file_command, _("\ + const auto remove_symbol_file_opts + = make_remove_symbol_file_def_group (nullptr); + static std::string remove_symbol_file_cmd_help + = gdb::option::build_help (_("\ Remove a symbol file added via the add-symbol-file command.\n\ Usage: remove-symbol-file FILENAME\n\ remove-symbol-file -a ADDRESS\n\ The file to remove can be identified by its filename or by an address\n\ -that lies within the boundaries of this symbol file in memory."), +that lies within the boundaries of this symbol file in memory.\n\ +Options:\n\ +%OPTIONS%"), remove_symbol_file_opts); + c = add_cmd ("remove-symbol-file", class_files, + remove_symbol_file_command, + remove_symbol_file_cmd_help.c_str (), &cmdlist); + set_cmd_completer_handle_brkchars (c, remove_symbol_file_command_completer); c = add_cmd ("load", class_files, load_command, _("\ Dynamically load FILE into the running program.\n\ diff --git a/gdb/testsuite/gdb.base/filename-completion.exp b/gdb/testsuite/gdb.base/filename-completion.exp index cf00d007ca7..62fb49570a6 100644 --- a/gdb/testsuite/gdb.base/filename-completion.exp +++ b/gdb/testsuite/gdb.base/filename-completion.exp @@ -122,7 +122,8 @@ proc test_gdb_complete_filename_multiple { proc run_quoting_and_escaping_tests { root } { # Test all the commands which allow quoting of filenames, and # which require whitespace to be escaped in unquoted filenames. - foreach_with_prefix cmd { file exec-file symbol-file add-symbol-file } { + foreach_with_prefix cmd { file exec-file symbol-file add-symbol-file \ + remove-symbol-file } { gdb_start # Completing 'thread apply all ...' commands uses a custom word diff --git a/gdb/testsuite/gdb.base/sym-file.exp b/gdb/testsuite/gdb.base/sym-file.exp index 3e36e65d1c5..17650cbce3a 100644 --- a/gdb/testsuite/gdb.base/sym-file.exp +++ b/gdb/testsuite/gdb.base/sym-file.exp @@ -67,134 +67,156 @@ if {[prepare_for_testing "failed to prepare" $binfile "$srcfile $srcfile2" $exe gdb_load_shlib ${lib_so} -if {![runto_main]} { - return -} - -# 1) Run to gdb_add_symbol_file in $srcfile for adding the library's -# symbols. -gdb_breakpoint gdb_add_symbol_file -gdb_continue_to_breakpoint gdb_add_symbol_file - -# 2) Set a pending breakpoint at bar in $srcfile3. -set result [gdb_breakpoint bar allow-pending] -if {!$result} { - return -} - -# 3) Add the library's symbols using 'add-symbol-file'. -set result [gdb_test "add-symbol-file ${lib_syms} addr" \ - "Reading symbols from .*${lib_syms}\\.\\.\\." \ - "add-symbol-file ${lib_basename}.so addr" \ - "add symbol table from file \".*${lib_basename}\\.so\"\ - at.*\\(y or n\\) " \ - "y"] -if {$result != 0} { - return -} - -# 4) 'info files' must display $srcfile3. -gdb_test "info files" \ - "^(?=(.*${lib_basename})).*" \ - "info files must display ${lib_basename}" - -# 5) Continue to bar in $srcfile3 to ensure that the breakpoint -# was bound correctly after adding $shilb_name. -set lnum_bar [gdb_get_line_number "break at bar" $srcfile3] -gdb_continue_to_breakpoint bar ".*${lib_basename}\\.c:$lnum_bar.*" - -# 6) Set a breakpoint at foo in $srcfile3. -set result [gdb_breakpoint foo] -if {!$result} { - return -} - -# 7) Continue to foo in $srcfile3 to ensure that the breakpoint -# was bound correctly. -set lnum_foo [gdb_get_line_number "break at foo" $srcfile3] -gdb_continue_to_breakpoint foo ".*${lib_basename}\\.c:$lnum_foo.*" - -# 8) Set a breakpoint at gdb_remove_symbol_file in $srcfile for -# removing the library's symbols. -set result [gdb_breakpoint gdb_remove_symbol_file] -if {!$result} { - return -} +proc do_test { remove_expr } { + global lib_basename lib_syms srcfile srcfile3 -# 9) Continue to gdb_remove_symbol_file in $srcfile. -gdb_continue_to_breakpoint gdb_remove_symbol_file - -# 10) Remove the library's symbols using 'remove-symbol-file'. -set result [gdb_test "remove-symbol-file -a addr" \ - ""\ - "remove-symbol-file -a addr" \ - "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\ -.*\\(y or n\\) " \ - "y"] -if {$result != 0} { - return -} + clean_restart $::binfile -# 11) 'info files' must not display ${lib_basename}, anymore. -gdb_test "info files" \ - "^(?!(.*${lib_basename})).*" \ - "info files must not display ${lib_basename}" + if {![runto_main]} { + return + } -# 12) Check that the breakpoints at foo and bar are pending after -# removing the library's symbols. -gdb_test "info breakpoints 3" \ - ".*PENDING.*" \ - "breakpoint at foo is pending" - -gdb_test "info breakpoints 4" \ - ".*PENDING.*" \ - "breakpoint at bar is pending" - -# 13) Check that the execution can continue without error. -set lnum_reload [gdb_get_line_number "reload lib here"] -gdb_breakpoint $lnum_reload -gdb_continue_to_breakpoint reload ".*${srcfile}:$lnum_reload.*" - -# 14) Regression test for a stale breakpoints bug. Check whether -# unloading symbols manually without the program actually unloading -# the library, when breakpoints are inserted doesn't leave stale -# breakpoints behind. -with_test_prefix "stale bkpts" { - # Force breakpoints always inserted. - gdb_test_no_output "set breakpoint always-inserted on" - - # Get past the library reload. + # 1) Run to gdb_add_symbol_file in $srcfile for adding the library's + # symbols. + gdb_breakpoint gdb_add_symbol_file gdb_continue_to_breakpoint gdb_add_symbol_file - # Load the library's symbols. - gdb_test "add-symbol-file ${lib_syms} addr" \ - "Reading symbols from .*${lib_syms}\\.\\.\\." \ - "add-symbol-file ${lib_basename}.so addr" \ - "add symbol table from file \".*${lib_syms}\"\ + # 2) Set a pending breakpoint at bar in $srcfile3. + set result [gdb_breakpoint bar allow-pending] + if {!$result} { + return + } + + # 3) Add the library's symbols using 'add-symbol-file'. + set result [gdb_test "add-symbol-file ${lib_syms} addr" \ + "Reading symbols from .*${lib_syms}\\.\\.\\." \ + "add-symbol-file ${lib_basename}.so addr" \ + "add symbol table from file \".*${lib_basename}\\.so\"\ + at.*\\(y or n\\) " \ + "y"] + if {$result != 0} { + return + } + + # 4) 'info files' must display $srcfile3. + gdb_test "info files" \ + "^(?=(.*${lib_basename})).*" \ + "info files must display ${lib_basename}" + + # 5) Continue to bar in $srcfile3 to ensure that the breakpoint + # was bound correctly after adding $shilb_name. + set lnum_bar [gdb_get_line_number "break at bar" $srcfile3] + gdb_continue_to_breakpoint bar ".*${lib_basename}\\.c:$lnum_bar.*" + + # 6) Set a breakpoint at foo in $srcfile3. + set result [gdb_breakpoint foo] + if {!$result} { + return + } + + # 7) Continue to foo in $srcfile3 to ensure that the breakpoint + # was bound correctly. + set lnum_foo [gdb_get_line_number "break at foo" $srcfile3] + gdb_continue_to_breakpoint foo ".*${lib_basename}\\.c:$lnum_foo.*" + + # 8) Set a breakpoint at gdb_remove_symbol_file in $srcfile for + # removing the library's symbols. + set result [gdb_breakpoint gdb_remove_symbol_file] + if {!$result} { + return + } + + # 9) Continue to gdb_remove_symbol_file in $srcfile. + gdb_continue_to_breakpoint gdb_remove_symbol_file + + # 10) Remove the library's symbols using 'remove-symbol-file'. + set result [gdb_test "remove-symbol-file ${remove_expr}" \ + ""\ + "remove-symbol-file" \ + "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\ +.*\\(y or n\\) " \ + "y"] + if {$result != 0} { + return + } + + # 11) 'info files' must not display ${lib_basename}, anymore. + gdb_test "info files" \ + "^(?!(.*${lib_basename})).*" \ + "info files must not display ${lib_basename}" + + # 12) Check that the breakpoints at foo and bar are pending after + # removing the library's symbols. + gdb_test "info breakpoints 3" \ + ".*PENDING.*" \ + "breakpoint at foo is pending" + + gdb_test "info breakpoints 4" \ + ".*PENDING.*" \ + "breakpoint at bar is pending" + + # 13) Check that the execution can continue without error. + set lnum_reload [gdb_get_line_number "reload lib here"] + gdb_breakpoint $lnum_reload + gdb_continue_to_breakpoint reload ".*${srcfile}:$lnum_reload.*" + + # 14) Regression test for a stale breakpoints bug. Check whether + # unloading symbols manually without the program actually unloading + # the library, when breakpoints are inserted doesn't leave stale + # breakpoints behind. + with_test_prefix "stale bkpts" { + # Force breakpoints always inserted. + gdb_test_no_output "set breakpoint always-inserted on" + + # Get past the library reload. + gdb_continue_to_breakpoint gdb_add_symbol_file + + # Load the library's symbols. + gdb_test "add-symbol-file ${lib_syms} addr" \ + "Reading symbols from .*${lib_syms}\\.\\.\\." \ + "add-symbol-file ${lib_basename}.so addr" \ + "add symbol table from file \".*${lib_syms}\"\ at.*\\(y or n\\) " \ - "y" + "y" - # Set a breakpoint at baz, in the library. - gdb_breakpoint baz + # Set a breakpoint at baz, in the library. + gdb_breakpoint baz - gdb_test "info breakpoints 7" ".*y.*0x.*in baz.*" \ - "breakpoint at baz is resolved" + gdb_test "info breakpoints 7" ".*y.*0x.*in baz.*" \ + "breakpoint at baz is resolved" - # Unload symbols manually without the program actually unloading - # the library. - gdb_test "remove-symbol-file -a addr" \ - "" \ - "remove-symbol-file -a addr" \ - "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\ + # Unload symbols manually without the program actually unloading + # the library. + gdb_test "remove-symbol-file ${remove_expr}" \ + "" \ + "remove-symbol-file" \ + "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\ .*\\(y or n\\) " \ - "y" + "y" + + gdb_test "info breakpoints 7" ".*PENDING.*" \ + "breakpoint at baz is pending" - gdb_test "info breakpoints 7" ".*PENDING.*" \ - "breakpoint at baz is pending" + # Check that execution can continue without error. If GDB leaves + # breakpoints behind, we'll get back a spurious SIGTRAP. + set lnum_end [gdb_get_line_number "end here"] + gdb_breakpoint $lnum_end + gdb_continue_to_breakpoint "end here" ".*end here.*" + } +} - # Check that execution can continue without error. If GDB leaves - # breakpoints behind, we'll get back a spurious SIGTRAP. - set lnum_end [gdb_get_line_number "end here"] - gdb_breakpoint $lnum_end - gdb_continue_to_breakpoint "end here" ".*end here.*" +foreach remove_expr [list addr bar "bar + 0x10" "${lib_syms}" ] { + # Don't use full filenames in the test prefix. Also, add '-a' to + # all the REMOVE_EXPR values which are addresses rather than + # filenames. + set prefix $remove_expr + if { $prefix == $lib_syms } { + set prefix [file tail $prefix] + } else { + set remove_expr "-a $remove_expr" + } + + with_test_prefix "remove_expr=$prefix" { + do_test $remove_expr + } } -- 2.25.4