From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 2KJKA7m4HWD2LAAAWB0awg (envelope-from ) for ; Fri, 05 Feb 2021 16:29:29 -0500 Received: by simark.ca (Postfix, from userid 112) id 035061EFCB; Fri, 5 Feb 2021 16:29:28 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED, MAILING_LIST_MULTI,T_DKIM_INVALID,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from 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 RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id B446A1EF7A for ; Fri, 5 Feb 2021 16:29:24 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 714653861878; Fri, 5 Feb 2021 21:29:24 +0000 (GMT) Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by sourceware.org (Postfix) with ESMTPS id 141A03857815 for ; Fri, 5 Feb 2021 21:29:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 141A03857815 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=andrew.burgess@embecosm.com Received: by mail-wr1-x434.google.com with SMTP id c4so9213662wru.9 for ; Fri, 05 Feb 2021 13:29:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xLUHP3YQtLNyQjunmCONe5ufd5aA+PE0zbkGgypiy7s=; b=P2klX+fiuQqJ6GHecgxegCYrAJWzXudJnxcVTgtnM3q3E6DsdoYLo+An/MV0JAmJyO AkKOsqQOjrQtZQvmS3DtdOS5H86XVvai2xXV9eGlkV7t/x3IDksWp0anmawYYWRNPNqH u3AcfyEfP/CTBuv8vTGe8+TTFgkk3GDY8Xce9kHh25vTVDq7YymuybKI9+yUFd/7ebzI Q8lRo3TkwQtIvDeskf/kQssiSVrd/Kbx47jZXwjvNxWRpz9kJc5UdX0YZPWbZqRkz0sD pzUgA7k0uCoFrhVu/b4my0ca7Cvy8goMm7jn1lFCqfEkfqZG/d79zDfBRSQwZIQ+tnbV rKxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xLUHP3YQtLNyQjunmCONe5ufd5aA+PE0zbkGgypiy7s=; b=VNBvPT7UEQbPtDrV+ObRllnU+jXh64cNSf7l7mRue3YZqH6Jzph4oKM/ngyy44XMfv RZ4FlVQOermw+iQXgT/ReMWG7cG270oIRWURcHAR9/4CRiQ9BevSku8fslIXaOhaE9c/ Xa34xC3q3dOtfDgzOc+X/gu8Jgw0oqmyqcgjVS0rnBIG6mtQ3GyAOfsDALQ0dpboow7A eP4wgqe0uMT81aVH7+eVBek1sLMjRzys62FfinZ9CXnut70Vhxko0xC+TjdJGkqprmIK B+pFHDI+5avhXVXXtTUQmip8MDWGB+4oPkZxRA2eqSw6Q55uvBSqSEj48l5jEhYMDyRC wgAg== X-Gm-Message-State: AOAM5320X/3oMz5yRqvaRX3qAQpb1pScYtAcX64gzgy9+o6sXx6QqxHI Fy3Qrrl8HLxLtW+9Aa3cVDo87Jig3MEP/g== X-Google-Smtp-Source: ABdhPJxedx1ZAEirD8OjA79ntcB6rVqDseXIAUTLvYdv4Te5UohSO7lK30TUJTMf/dJ9Ut58yifjcg== X-Received: by 2002:adf:f6c4:: with SMTP id y4mr6907956wrp.127.1612560559744; Fri, 05 Feb 2021 13:29:19 -0800 (PST) Received: from localhost (host109-151-46-64.range109-151.btcentralplus.com. [109.151.46.64]) by smtp.gmail.com with ESMTPSA id l10sm13710300wro.4.2021.02.05.13.29.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Feb 2021 13:29:19 -0800 (PST) From: Andrew Burgess To: gdb-patches@sourceware.org Subject: [PATCH 3/3] gdb: change 'maint info section' to use command options Date: Fri, 5 Feb 2021 21:29:11 +0000 Message-Id: <46a0be74dee73dda27d6c9e20c149fa4bc6a89f9.1612560410.git.andrew.burgess@embecosm.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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: , Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" The 'maintenance info sections' command currently takes a list of filters on the command line. It can also accept the magic string 'ALLOBJ' which acts more like a command line flag, telling the command to print information about all objfiles. The manual has this to say about the options and filters: ... In addition, 'maint info sections' provides the following command options (which may be arbitrarily combined): ... Implying (to me at least) that I can do this: (gdb) maint info sections ALLOBJ READONLY to list all the read-only sections from all currently loaded object files. Unfortunately, this doesn't work. The READONLY filter will work, but ALLOBJ will not be detected correctly. It would be fairly simple to fix the ALLOBJ detection. However, I dislike this mixing of command options (ALLOBJ) with command data (the filters, e.g. READONLY, etc). As this is a maintenance command, so not really intended for end users, I think we can be a little more aggressive in "fixing" the option parsing. So that's what I do in this commit. The ALLOBJ mechanism is replaced with a real command option (-all-objects). The rest of the command operates just as before. The example above would now become: (gdb) maint info sections -all-objects READONLY The manual has been updated, and I added a NEWS entry to document the change. gdb/ChangeLog: * NEWS: Mention changes to 'maint info sections'. * maint.c (match_substring): Return a bool, fix whitespace issue. (struct single_bfd_flag_info): New struct. (bfd_flag_info): New static global. (match_bfd_flags): Return a bool, use bfd_flag_info. (print_bfd_flags): Use bfd_flag_info. (maint_print_section_info): Delete trailing whitespace. (struct maint_info_sections_opts): New struct. (maint_info_sections_option_defs): New static global. (maint_info_sections_completer): New function. (maintenance_info_sections): Use option parsing mechanism. (_initialize_maint_cmds): Register command completer. gdb/doc/ChangeLog: * gdb.texinfo (Files): Update documentation for 'maint info sections'. gdb/testsuite/ChangeLog: * gdb.base/maint-info-sections.exp: Update expected output, and add additional tests. Again. --- gdb/ChangeLog | 16 ++ gdb/NEWS | 5 + gdb/doc/ChangeLog | 5 + gdb/doc/gdb.texinfo | 29 ++- gdb/maint.c | 228 +++++++++++------- gdb/testsuite/ChangeLog | 5 + .../gdb.base/maint-info-sections.exp | 32 ++- 7 files changed, 213 insertions(+), 107 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index d4c76570331..632aa99d2a6 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -86,6 +86,11 @@ inferior [ID] behavior of the command is unchanged and have the inferior ID become the current inferior. +maintenance info sections + The ALLOBJ keyword has been replaced with an -all-objects command + line flag. It is now possible to filter which sections are printed + even when -all-objects is passed. + *** Changes in GDB 10 * There are new feature names for ARC targets: "org.gnu.gdb.arc.core" diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 174fd6d0ffc..e8ddbffa186 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20619,22 +20619,25 @@ current ones. @kindex maint info sections -@item maint info sections +@item maint info sections @r{[}-all-objects@r{]} @r{[}@var{filter-list}@r{]} Another command that can give you extra information about program sections is @code{maint info sections}. In addition to the section information displayed by @code{info files}, this command displays the flags and file -offset of each section in the executable and core dump files. In addition, -@code{maint info sections} provides the following command options (which -may be arbitrarily combined): - -@table @code -@item ALLOBJ -Display sections for all loaded object files, including shared libraries. -@item @var{sections} -Display info only for named @var{sections}. -@item @var{section-flags} -Display info only for sections for which @var{section-flags} are true. -The section flags that @value{GDBN} currently knows about are: +offset of each section in the executable and core dump files. + +When @samp{-all-objects} is passed then sections from all loaded object +files, including shared libraries, are printed. + +The optional @var{filter-list} is a space separated list of filter +keywords. Sections that match any one of the filter criteria will be +printed. There are two types of filter: + +@table @code +@item @var{section-name} +Display information about any section named @var{section-name}. +@item @var{section-flag} +Display information for any section with @var{section-flag}. The +section flags that @value{GDBN} currently knows about are: @table @code @item ALLOC Section will have space allocated in the process when loaded. diff --git a/gdb/maint.c b/gdb/maint.c index c6fc83ccfb7..ec60870f07f 100644 --- a/gdb/maint.c +++ b/gdb/maint.c @@ -131,10 +131,10 @@ maintenance_space_display (const char *args, int from_tty) /* Mini tokenizing lexer for 'maint info sections' command. */ -static int +static bool match_substring (const char *string, const char *substr) { - int substr_len = strlen(substr); + int substr_len = strlen (substr); const char *tok; while ((tok = strstr (string, substr)) != NULL) @@ -150,90 +150,82 @@ match_substring (const char *string, const char *substr) || tok[substr_len] == '\0') { /* Token is delimited at the rear. Got a whole-word match. */ - return 1; + return true; } } /* Token didn't match as a whole word. Advance and try again. */ string = tok + 1; } - return 0; + return false; } -static int +/* Structure holding information about a single bfd section flag. This is + used by the "maintenance info sections" command to print the sections, + and for filtering which sections are printed. */ + +struct single_bfd_flag_info +{ + /* The name of the section. This is what is printed for the flag, and + what the user enter in order to filter by flag. */ + const char *name; + + /* The bfd defined SEC_* flagword value for this flag. */ + flagword value; +}; + +/* Vector of all the known bfd flags. */ + +static std::vector bfd_flag_info = + { + { "ALLOC", SEC_ALLOC }, + { "LOAD", SEC_LOAD }, + { "RELOC", SEC_RELOC }, + { "READONLY", SEC_READONLY }, + { "CODE", SEC_CODE }, + { "DATA", SEC_DATA }, + { "ROM", SEC_ROM }, + { "CONSTRUCTOR", SEC_CONSTRUCTOR }, + { "HAS_CONTENTS", SEC_HAS_CONTENTS }, + { "NEVER_LOAD", SEC_NEVER_LOAD }, + { "COFF_SHARED_LIBRARY", SEC_COFF_SHARED_LIBRARY }, + { "IS_COMMON", SEC_IS_COMMON } + }; + +/* For each flag in the global BFD_FLAG_INFO list, if FLAGS has a flag's + flagword value set, and STRING contains the flag's name then return + true, otherwise return false. STRING is never nullptr. */ + +static bool match_bfd_flags (const char *string, flagword flags) { - if (flags & SEC_ALLOC) - if (match_substring (string, "ALLOC")) - return 1; - if (flags & SEC_LOAD) - if (match_substring (string, "LOAD")) - return 1; - if (flags & SEC_RELOC) - if (match_substring (string, "RELOC")) - return 1; - if (flags & SEC_READONLY) - if (match_substring (string, "READONLY")) - return 1; - if (flags & SEC_CODE) - if (match_substring (string, "CODE")) - return 1; - if (flags & SEC_DATA) - if (match_substring (string, "DATA")) - return 1; - if (flags & SEC_ROM) - if (match_substring (string, "ROM")) - return 1; - if (flags & SEC_CONSTRUCTOR) - if (match_substring (string, "CONSTRUCTOR")) - return 1; - if (flags & SEC_HAS_CONTENTS) - if (match_substring (string, "HAS_CONTENTS")) - return 1; - if (flags & SEC_NEVER_LOAD) - if (match_substring (string, "NEVER_LOAD")) - return 1; - if (flags & SEC_COFF_SHARED_LIBRARY) - if (match_substring (string, "COFF_SHARED_LIBRARY")) - return 1; - if (flags & SEC_IS_COMMON) - if (match_substring (string, "IS_COMMON")) - return 1; - - return 0; + gdb_assert (string != nullptr); + + for (const auto &f : bfd_flag_info) + { + if (flags & f.value + && match_substring (string, f.name)) + return true; + } + + return false; } +/* Print the names of all flags set in FLAGS. The names are taken from the + BFD_FLAG_INFO global. */ + static void print_bfd_flags (flagword flags) { - if (flags & SEC_ALLOC) - printf_filtered (" ALLOC"); - if (flags & SEC_LOAD) - printf_filtered (" LOAD"); - if (flags & SEC_RELOC) - printf_filtered (" RELOC"); - if (flags & SEC_READONLY) - printf_filtered (" READONLY"); - if (flags & SEC_CODE) - printf_filtered (" CODE"); - if (flags & SEC_DATA) - printf_filtered (" DATA"); - if (flags & SEC_ROM) - printf_filtered (" ROM"); - if (flags & SEC_CONSTRUCTOR) - printf_filtered (" CONSTRUCTOR"); - if (flags & SEC_HAS_CONTENTS) - printf_filtered (" HAS_CONTENTS"); - if (flags & SEC_NEVER_LOAD) - printf_filtered (" NEVER_LOAD"); - if (flags & SEC_COFF_SHARED_LIBRARY) - printf_filtered (" COFF_SHARED_LIBRARY"); - if (flags & SEC_IS_COMMON) - printf_filtered (" IS_COMMON"); + for (const auto &f : bfd_flag_info) + { + if (flags & f.value) + printf_filtered (" %s", f.name); + } } static void -maint_print_section_info (const char *name, flagword flags, - CORE_ADDR addr, CORE_ADDR endaddr, +maint_print_section_info (const char *name, flagword flags, + CORE_ADDR addr, CORE_ADDR endaddr, unsigned long filepos, int addr_size) { printf_filtered (" %s", hex_string_custom (addr, addr_size)); @@ -400,27 +392,71 @@ maint_print_all_sections (const char *header, bfd *abfd, objfile *objfile, } } +/* The options for the "maintenance info sections" command. */ + +struct maint_info_sections_opts +{ + /* For "-all-objects". */ + bool all_objects = false; +}; + +static const gdb::option::option_def maint_info_sections_option_defs[] = { + + gdb::option::flag_option_def { + "all-objects", + [] (maint_info_sections_opts *opts) { return &opts->all_objects; }, + N_("Display information from all loaded object files."), + }, +}; + +/* Create an option_def_group for the "maintenance info sections" options, + with CC_OPTS as context. */ + +static inline gdb::option::option_def_group +make_maint_info_sections_options_def_group (maint_info_sections_opts *cc_opts) +{ + return {{maint_info_sections_option_defs}, cc_opts}; +} + +/* Completion for the "maintenance info sections" command. */ + +static void +maint_info_sections_completer (struct cmd_list_element *cmd, + completion_tracker &tracker, + const char *text, const char * /* word */) +{ + /* Complete command options. */ + const auto group = make_maint_info_sections_options_def_group (nullptr); + if (gdb::option::complete_options + (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group)) + return; + const char *word = advance_to_expression_complete_word_point (tracker, text); + + /* Offer completion for section flags, but not section names. This is + only a maintenance command after all, no point going over the top. */ + std::vector flags; + for (const auto &f : bfd_flag_info) + flags.push_back (f.name); + flags.push_back (nullptr); + complete_on_enum (tracker, flags.data (), text, word); +} + /* Implement the "maintenance info sections" command. */ static void maintenance_info_sections (const char *arg, int from_tty) { - bool allobj = false; - - /* Only this function cares about the 'ALLOBJ' argument; if 'ALLOBJ' is - the only argument, discard it rather than passing it down to - print_objfile_section_info (which wouldn't know how to handle it). */ - if (arg != nullptr && strcmp (arg, "ALLOBJ") == 0) - { - arg = nullptr; - allobj = true; - } + /* Check if the "-all-objects" flag was passed. */ + maint_info_sections_opts opts; + const auto group = make_maint_info_sections_options_def_group (&opts); + gdb::option::process_options + (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group); for (objfile *ofile : current_program_space->objfiles ()) { if (ofile->obfd == current_program_space->exec_bfd ()) maint_print_all_sections (_("Exec file: "), ofile->obfd, ofile, arg); - else if (allobj) + else if (opts.all_objects) maint_print_all_sections (_("Object file: "), ofile->obfd, ofile, arg); } @@ -1062,17 +1098,29 @@ Commands for showing internal info about the program being debugged."), &maintenancelist); add_alias_cmd ("i", "info", class_maintenance, 1, &maintenancelist); - add_cmd ("sections", class_maintenance, maintenance_info_sections, _("\ + const auto opts = make_maint_info_sections_options_def_group (nullptr); + static std::string maint_info_sections_command_help + = gdb::option::build_help (_("\ List the BFD sections of the exec and core files.\n\ -Arguments may be any combination of:\n\ - [one or more section names]\n\ - ALLOC LOAD RELOC READONLY CODE DATA ROM CONSTRUCTOR\n\ - HAS_CONTENTS NEVER_LOAD COFF_SHARED_LIBRARY IS_COMMON\n\ -Sections matching any argument will be listed (no argument\n\ -implies all sections). In addition, the special argument\n\ - ALLOBJ\n\ -lists all sections from all object files, including shared libraries."), - &maintenanceinfolist); +\n\ +Usage: maintenance info sections [-all-objects] [FILTERS]\n\ +\n\ +FILTERS is a list of words, each word is either:\n\ + + A section name - any section with this name will be printed, or\n\ + + A section flag - any section with this flag will be printed. The\n\ + known flags are:\n\ + ALLOC LOAD RELOC READONLY CODE DATA ROM CONSTRUCTOR\n\ + HAS_CONTENTS NEVER_LOAD COFF_SHARED_LIBRARY IS_COMMON\n\ +\n\ +Sections matching any of the FILTERS will be listed (no FILTERS implies\n\ +all sections should be printed).\n\ +\n\ +Options:\n\ +%OPTIONS%"), opts); + cmd = add_cmd ("sections", class_maintenance, maintenance_info_sections, + maint_info_sections_command_help.c_str (), + &maintenanceinfolist); + set_cmd_completer_handle_brkchars (cmd, maint_info_sections_completer); add_basic_prefix_cmd ("print", class_maintenance, _("Maintenance command for printing GDB internal state."), diff --git a/gdb/testsuite/gdb.base/maint-info-sections.exp b/gdb/testsuite/gdb.base/maint-info-sections.exp index 19e5c122226..07c53b16177 100644 --- a/gdb/testsuite/gdb.base/maint-info-sections.exp +++ b/gdb/testsuite/gdb.base/maint-info-sections.exp @@ -15,6 +15,8 @@ # Test just for the 'maintenance info sections' command. +load_lib completion-support.exp + standard_testfile break.c break1.c if {[prepare_for_testing "failed to prepare" $testfile \ @@ -139,11 +141,11 @@ gdb_test "add-symbol-file ${binfile}" ".*" \ gdb_test_no_output "maint info sections" \ "no output when no executable is set" -# Check that the executable shows up as an object file when ALLOBJ is -# used. +# Check that the executable shows up as an object file when +# -all-objects is used. set seen_header false set seen_a_section false -gdb_test_multiple "maint info sections ALLOBJ" "" { +gdb_test_multiple "maint info sections -all-objects" "" { -re "Object file: `${binfile}', file type \[^.\]+\.\r\n" { set seen_header true exp_continue @@ -154,7 +156,29 @@ gdb_test_multiple "maint info sections ALLOBJ" "" { } -re "^$gdb_prompt $" { gdb_assert { $seen_header && $seen_a_section } \ - "ensure header and section seen in ALLOBJ case" + "ensure header and section seen in -all-objects case" pass $gdb_test_name } } + +# Test the command line completion on 'maint info sections'. First +# the command line flag. +test_gdb_complete_unique \ + "maintenance info sections -" \ + "maintenance info sections -all-objects" + +# Now check the section flags complete. +test_gdb_complete_multiple "maintenance info sections " "" "" { + "ALLOC" + "CODE" + "COFF_SHARED_LIBRARY" + "CONSTRUCTOR" + "DATA" + "HAS_CONTENTS" + "IS_COMMON" + "LOAD" + "NEVER_LOAD" + "READONLY" + "RELOC" + "ROM" +} -- 2.25.4