* [PATCH 1/3] gdb/testsuite: split 'maint info sections' tests to a new file
2021-02-05 21:29 [PATCH 0/3] Changes to 'maint info sections' Andrew Burgess
@ 2021-02-05 21:29 ` Andrew Burgess
2021-02-08 19:28 ` Tom Tromey
2021-02-05 21:29 ` [PATCH 2/3] gdb: 'maint info sections' - handle the no executable case Andrew Burgess
2021-02-05 21:29 ` [PATCH 3/3] gdb: change 'maint info section' to use command options Andrew Burgess
2 siblings, 1 reply; 8+ messages in thread
From: Andrew Burgess @ 2021-02-05 21:29 UTC (permalink / raw)
To: gdb-patches
The next couple of patches are going to add more tests for the 'maint
info sections' command. Rather than try to jam these tests into the
already quite long gdb.base/maint.c, this commit moves all of the
tests for 'maint info sections' into a new file.
I've updated the tests to make use of some newer testsuite constructs,
like -wrap and $gdb_test_name for gdb_test_multiple, but otherwise the
tests should not have changed with this commit.
gdb/testsuite/ChangeLog:
* gdb.base/maint-info-sections.exp: New file, content is moved
from gdb.base/maint.exp and cleaned up to use latest testsuite
techniques.
* gdb.base/maint.exp: Tests moved out to
gdb.base/maint-info-sections.exp.
---
gdb/testsuite/ChangeLog | 8 ++
.../gdb.base/maint-info-sections.exp | 127 ++++++++++++++++++
gdb/testsuite/gdb.base/maint.exp | 87 ------------
3 files changed, 135 insertions(+), 87 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/maint-info-sections.exp
diff --git a/gdb/testsuite/gdb.base/maint-info-sections.exp b/gdb/testsuite/gdb.base/maint-info-sections.exp
new file mode 100644
index 00000000000..6c41ff2bd90
--- /dev/null
+++ b/gdb/testsuite/gdb.base/maint-info-sections.exp
@@ -0,0 +1,127 @@
+# Copyright 1998-2021 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 <http://www.gnu.org/licenses/>.
+
+# Test just for the 'maintenance info sections' command.
+
+standard_testfile break.c break1.c
+
+if {[prepare_for_testing "failed to prepare" $testfile \
+ [list $srcfile $srcfile2] {debug nowarnings}]} {
+ return -1
+}
+
+if ![runto_main] then {
+ untested "maint info sections"
+ return -1
+}
+
+# Check that 'maint info sections' output looks correct. When
+# checking the lines for each section we reject section names starting
+# with a '*' character, the internal *COM*, *UND*, *ABS*, and *IND*
+# sections should not be displayed in this output.
+set seen_header false
+set seen_a_section false
+gdb_test_multiple "maint info sections" "general output check" {
+ -re "Exec file:\r\n\[\t ]+`\[^'\]+', file type \[^.\]+\.\r\n" {
+ set seen_header true
+ exp_continue
+ }
+ -re "^ \\\[\[0-9\]+\\\]\[\t \]+$hex->$hex at $hex: \[^*\r\]+\r\n" {
+ set seen_a_section true
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ gdb_assert { $seen_header && $seen_a_section }
+ pass $gdb_test_name
+ }
+}
+
+# It'd be nice to check for every possible section. However, that's
+# problematic, since the relative ordering wanders from release to
+# release of the compilers. Instead, we'll just check for two
+# sections which appear to always come out in the same relative
+# order. (If that changes, then we should just check for one
+# section.)
+#
+# And by the way: This testpoint will break for PA64, where a.out's
+# are ELF files.
+
+# Standard GNU names.
+set text_section ".text"
+set data_section ".data"
+
+gdb_test_multiple "maint info sections" "" {
+ -re -wrap "Exec file:\r\n.*${binfile}., file type.*ER_RO.*" {
+ # Looks like RealView which uses different section names.
+ set text_section ER_RO
+ set data_section ER_RW
+ pass "maint info sections"
+ }
+ -re -wrap "Exec file:\r\n.*${binfile}., file type.*neardata.*" {
+ # c6x doesn't have .data section. It has .neardata and .fardata section.
+ set data_section ".neardata"
+ pass "maint info sections"
+ }
+ -re -wrap "Exec file:\r\n.*${binfile}., file type.*" {
+ pass "maint info sections"
+ }
+}
+
+# Test for new option: maint info sections <section name>
+# If you don't have a .text section, this will require tweaking.
+
+gdb_test_multiple "maint info sections $text_section" "" {
+ -re -wrap " \\.bss .*" {
+ fail $gdb_test_name
+ }
+ -re -wrap " $data_section .*" {
+ fail $gdb_test_name
+ }
+ -re -wrap " $text_section .*" {
+ pass $gdb_test_name
+ }
+}
+
+# Test for new option: CODE section flag
+# If your data section is tagged CODE, xfail this test.
+
+gdb_test_multiple "maint info sections CODE" "" {
+ -re -wrap " $data_section .*" {
+ fail $gdb_test_name
+ }
+ -re -wrap " $text_section .*" {
+ pass $gdb_test_name
+ }
+}
+
+# Test for new option: DATA section flag
+# If your text section is tagged DATA, xfail this test.
+#
+# The "maint info sections DATA" test is marked for XFAIL on Windows,
+# because Windows has text sections marked DATA.
+setup_xfail "*-*-*cygwin*"
+setup_xfail "*-*-*mingw*"
+
+gdb_test_multiple "maint info sections DATA" "" {
+ -re -wrap " $text_section .*" {
+ fail $gdb_test_name
+ }
+ -re -wrap " $data_section .*" {
+ pass $gdb_test_name
+ }
+ -re -wrap " .rodata .*" {
+ pass $gdb_test_name
+ }
+}
diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp
index 4b5b0391971..b418c023d73 100644
--- a/gdb/testsuite/gdb.base/maint.exp
+++ b/gdb/testsuite/gdb.base/maint.exp
@@ -40,7 +40,6 @@
#maintenance print unwind -- Print unwind table entry at given address
#
#
-#maintenance info sections -- List the BFD sections of the exec and core files
#maintenance info breakpoints -- Status of all breakpoints
#
@@ -118,23 +117,6 @@ if ![runto_main] then {
perror "tests suppressed"
}
-# Check that 'maint info sections' output looks correct. When
-# checking the lines for each section we reject section names starting
-# with a '*' character, the internal *COM*, *UND*, *ABS*, and *IND*
-# sections should not be displayed in this output.
-set test "check maint info sections output"
-gdb_test_multiple "maint info sections" $test {
- -re "Exec file:\r\n\[\t ]+`\[^'\]+', file type \[^.\]+\.\r\n" {
- exp_continue
- }
- -re "^ \\\[\[0-9\]+\\\]\[\t \]+$hex->$hex at $hex: \[^*\r\]+\r\n" {
- exp_continue
- }
- -re "^$gdb_prompt $" {
- pass $test
- }
-}
-
# If we're using .gdb_index or .debug_names there will be no psymtabs.
set have_gdb_index [ exec_has_index_section ${binfile} ]
@@ -417,75 +399,6 @@ if [istarget "hppa*-*-11*"] {
set oldtimeout $timeout
set timeout [expr $timeout + 300]
-# It'd be nice to check for every possible section. However, that's
-# problematic, since the relative ordering wanders from release to
-# release of the compilers. Instead, we'll just check for two
-# sections which appear to always come out in the same relative
-# order. (If that changes, then we should just check for one
-# section.)
-#
-# And by the way: This testpoint will break for PA64, where a.out's
-# are ELF files.
-
-# Standard GNU names.
-set text_section ".text"
-set data_section ".data"
-
-gdb_test_multiple "maint info sections" "maint info sections" {
- -re "Exec file:\r\n.*maint($EXEEXT)?., file type.*ER_RO.*$gdb_prompt $" {
- # Looks like RealView which uses different section names.
- set text_section ER_RO
- set data_section ER_RW
- pass "maint info sections"
- }
- -re "Exec file:\r\n.*maint($EXEEXT)?., file type.*neardata.*$gdb_prompt $" {
- # c6x doesn't have .data section. It has .neardata and .fardata section.
- set data_section ".neardata"
- pass "maint info sections"
- }
- -re "Exec file:\r\n.*maint($EXEEXT)?., file type.*$gdb_prompt $" {
- pass "maint info sections"
- }
-}
-
-# Test for new option: maint info sections <section name>
-# If you don't have a .text section, this will require tweaking.
-
-gdb_test_multiple "maint info sections $text_section" \
- "maint info sections .text" {
- -re ".* \\.bss .*$gdb_prompt $" {
- fail "maint info sections .text"
- }
- -re ".* $data_section .*$gdb_prompt $" {
- fail "maint info sections .text"
- }
- -re ".* $text_section .*$gdb_prompt $" {
- pass "maint info sections .text"
- }
- }
-
-# Test for new option: CODE section flag
-# If your data section is tagged CODE, xfail this test.
-
-gdb_test_multiple "maint info sections CODE" "maint info sections CODE" {
- -re ".* $data_section .*$gdb_prompt $" { fail "maint info sections CODE" }
- -re ".* $text_section .*$gdb_prompt $" { pass "maint info sections CODE" }
-}
-
-# Test for new option: DATA section flag
-# If your text section is tagged DATA, xfail this test.
-#
-# The "maint info sections DATA" test is marked for XFAIL on Windows,
-# because Windows has text sections marked DATA.
-setup_xfail "*-*-*cygwin*"
-setup_xfail "*-*-*mingw*"
-
-gdb_test_multiple "maint info sections DATA" "maint info sections DATA" {
- -re ".* $text_section .*$gdb_prompt $" { fail "maint info sections DATA" }
- -re ".* $data_section .*$gdb_prompt $" { pass "maint info sections DATA" }
- -re ".* .rodata .*$gdb_prompt $" { pass "maint info sections DATA" }
-}
-
set bp_location6 [gdb_get_line_number "set breakpoint 6 here"]
gdb_test_multiple "maint info breakpoints" "maint info breakpoints" {
--
2.25.4
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/3] gdb/testsuite: split 'maint info sections' tests to a new file
2021-02-05 21:29 ` [PATCH 1/3] gdb/testsuite: split 'maint info sections' tests to a new file Andrew Burgess
@ 2021-02-08 19:28 ` Tom Tromey
0 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2021-02-08 19:28 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches
>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:
Andrew> The next couple of patches are going to add more tests for the 'maint
Andrew> info sections' command. Rather than try to jam these tests into the
Andrew> already quite long gdb.base/maint.c, this commit moves all of the
Andrew> tests for 'maint info sections' into a new file.
Andrew> I've updated the tests to make use of some newer testsuite constructs,
Andrew> like -wrap and $gdb_test_name for gdb_test_multiple, but otherwise the
Andrew> tests should not have changed with this commit.
Andrew> gdb/testsuite/ChangeLog:
Andrew> * gdb.base/maint-info-sections.exp: New file, content is moved
Andrew> from gdb.base/maint.exp and cleaned up to use latest testsuite
Andrew> techniques.
Andrew> * gdb.base/maint.exp: Tests moved out to
Andrew> gdb.base/maint-info-sections.exp.
Looks reasonable to me. Thank you.
Tom
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/3] gdb: 'maint info sections' - handle the no executable case
2021-02-05 21:29 [PATCH 0/3] Changes to 'maint info sections' Andrew Burgess
2021-02-05 21:29 ` [PATCH 1/3] gdb/testsuite: split 'maint info sections' tests to a new file Andrew Burgess
@ 2021-02-05 21:29 ` Andrew Burgess
2021-02-08 19:29 ` Tom Tromey
2021-02-05 21:29 ` [PATCH 3/3] gdb: change 'maint info section' to use command options Andrew Burgess
2 siblings, 1 reply; 8+ messages in thread
From: Andrew Burgess @ 2021-02-05 21:29 UTC (permalink / raw)
To: gdb-patches
The 'maint info sections' command is split into two blocks or work,
first if there's an executable then the sections from the executable,
and optionally all other loaded object files are printed. Then all
the sections from any core file are printed.
I ran into a situation where (for various reasons) I wasn't using a
main executable. Instead I connected to a remote target and used
add-symbol-file. This allowed me to debug an image that was already
loaded on the remote system.
Unfortunately, when I tried to use 'maint info sections' I saw
nothing. The reason is that the loop over all object files is hidden
behind a check that we have a main executable.
This commit removes this check and merges together some duplicate
code. I also (I think) made the output of this command cleaner.
Here is the original output of 'maint info sections':
Exec file:
`/tmp/hello.x', file type elf64-x86-64.
[0] 0x004002a8->0x004002c4 at 0x000002a8: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x004002c4->0x004002e8 at 0x000002c4: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS
...
And my modified output:
Exec file: `/home/andrew/tmp/hello.x', file type elf64-x86-64.
[0] 0x004002a8->0x004002c4 at 0x000002a8: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x004002c4->0x004002e8 at 0x000002c4: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS
...
The forced newline after 'Exec file: ' has been removed. This is now
a wrap point (in case the filename is very long).
Here is the original output of 'maint info sections ALLOBJ':
Exec file:
`/tmp/hello.x', file type elf64-x86-64.
Object file: /tmp/hello.x
[0] 0x004002a8->0x004002c4 at 0x000002a8: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x004002c4->0x004002e8 at 0x000002c4: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS
...
Object file: /lib64/ld-linux-x86-64.so.2
[0] 0x7ffff7fd12a8->0x7ffff7fd12c8 at 0x000002a8: .note.gnu.property ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x7ffff7fd12c8->0x7ffff7fd12ec at 0x000002c8: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS
...
And my modified output:
Exec file: `/tmp/hello.x', file type elf64-x86-64.
[0] 0x004002a8->0x004002c4 at 0x000002a8: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x004002c4->0x004002e8 at 0x000002c4: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS
...
Object file: `/lib64/ld-linux-x86-64.so.2', file type elf64-x86-64.
[0] 0x7ffff7fd12a8->0x7ffff7fd12c8 at 0x000002a8: .note.gnu.property ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x7ffff7fd12c8->0x7ffff7fd12ec at 0x000002c8: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS
...
The executable now only gets a single header line. The header line
for the additional object files is no longer indented as it was
before, and the line is laid out in a similar style to the main
executable line (with quotes and file type information).
And of course, the biggest change. If GDB is started with no
executable, but then the user does 'add-symbol-file ....' followed by
'maint info sections ALLOBJ', previously they got nothing, now they
get:
Object file: `/tmp/hello.x', file type elf64-x86-64.
[0] 0x004002a8->0x004002c4 at 0x000002a8: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x004002c4->0x004002e8 at 0x000002c4: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS
...
gdb/ChangeLog:
* maint.c (print_bfd_section_info_maybe_relocated): Delete,
functionality merged into...
(maint_print_all_sections): ...this new function.
(maintenance_info_sections): Make use of maint_print_all_sections,
allow all objects to be printed even where there's no executable.
gdb/testsuite/ChangeLog:
* gdb.base/maint-info-sections.exp: Update expected output, and
add additional tests.
---
gdb/ChangeLog | 8 ++
gdb/maint.c | 114 +++++++++---------
gdb/testsuite/ChangeLog | 5 +
.../gdb.base/maint-info-sections.exp | 41 ++++++-
4 files changed, 105 insertions(+), 63 deletions(-)
diff --git a/gdb/maint.c b/gdb/maint.c
index d718d707134..c6fc83ccfb7 100644
--- a/gdb/maint.c
+++ b/gdb/maint.c
@@ -354,25 +354,50 @@ maint_obj_section_from_bfd_section (bfd *abfd,
return osect;
}
-/* Print information about ASECT from ABFD. Where possible the information for
- ASECT will print the relocated addresses of the section.
+/* Print information about all sections from ABFD, which is the bfd
+ corresponding to OBJFILE. It is fine for OBJFILE to be nullptr, but
+ ABFD must never be nullptr. If OBJFILE is provided then the sections of
+ ABFD will (potentially) be displayed relocated (i.e. the object file was
+ loaded with add-symbol-file and custom offsets were provided).
- ARG is the argument string passed by the user to the top level maintenance
- info sections command. Used for filtering which sections are printed. */
+ HEADER is a string that describes this file, e.g. 'Exec file: ', or
+ 'Core file: '.
+
+ ARG is a string used for filtering which sections are printed, this can
+ be nullptr for no filtering. See the top level 'maint info sections'
+ for a fuller description of the possible filtering strings. */
static void
-print_bfd_section_info_maybe_relocated (bfd *abfd, asection *asect,
- objfile *objfile, const char *arg,
- int index_digits)
+maint_print_all_sections (const char *header, bfd *abfd, objfile *objfile,
+ const char *arg)
{
- gdb_assert (objfile->sections != NULL);
- obj_section *osect
- = maint_obj_section_from_bfd_section (abfd, asect, objfile);
+ puts_filtered (header);
+ wrap_here (" ");
+ printf_filtered ("`%s', ", bfd_get_filename (abfd));
+ wrap_here (" ");
+ printf_filtered (_("file type %s.\n"), bfd_get_target (abfd));
- if (osect->the_bfd_section == NULL)
- print_bfd_section_info (abfd, asect, arg, index_digits);
- else
- print_objfile_section_info (abfd, osect, arg, index_digits);
+ int section_count = gdb_bfd_count_sections (abfd);
+ int digits = index_digits (section_count);
+
+ for (asection *sect : gdb_bfd_sections (abfd))
+ {
+ obj_section *osect = nullptr;
+
+ if (objfile != nullptr)
+ {
+ gdb_assert (objfile->sections != nullptr);
+ osect
+ = maint_obj_section_from_bfd_section (abfd, sect, objfile);
+ if (osect->the_bfd_section == nullptr)
+ osect = nullptr;
+ }
+
+ if (osect == nullptr)
+ print_bfd_section_info (abfd, sect, arg, digits);
+ else
+ print_objfile_section_info (abfd, osect, arg, digits);
+ }
}
/* Implement the "maintenance info sections" command. */
@@ -380,56 +405,27 @@ print_bfd_section_info_maybe_relocated (bfd *abfd, asection *asect,
static void
maintenance_info_sections (const char *arg, int from_tty)
{
- if (current_program_space->exec_bfd ())
- {
- bool allobj = false;
-
- printf_filtered (_("Exec file:\n"));
- printf_filtered (" `%s', ",
- bfd_get_filename (current_program_space->exec_bfd ()));
- wrap_here (" ");
- printf_filtered (_("file type %s.\n"),
- bfd_get_target (current_program_space->exec_bfd ()));
-
- /* 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 && strcmp (arg, "ALLOBJ") == 0)
- {
- arg = NULL;
- allobj = true;
- }
+ bool allobj = false;
- for (objfile *ofile : current_program_space->objfiles ())
- {
- if (allobj)
- printf_filtered (_(" Object file: %s\n"),
- bfd_get_filename (ofile->obfd));
- else if (ofile->obfd != current_program_space->exec_bfd ())
- continue;
-
- int section_count = gdb_bfd_count_sections (ofile->obfd);
-
- for (asection *sect : gdb_bfd_sections (ofile->obfd))
- print_bfd_section_info_maybe_relocated
- (ofile->obfd, sect, ofile, arg, index_digits (section_count));
- }
+ /* 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;
}
- if (core_bfd)
+ for (objfile *ofile : current_program_space->objfiles ())
{
- printf_filtered (_("Core file:\n"));
- printf_filtered (" `%s', ", bfd_get_filename (core_bfd));
- wrap_here (" ");
- printf_filtered (_("file type %s.\n"), bfd_get_target (core_bfd));
-
- int section_count = gdb_bfd_count_sections (core_bfd);
-
- for (asection *sect : gdb_bfd_sections (core_bfd))
- print_bfd_section_info (core_bfd, sect, arg,
- index_digits (section_count));
+ if (ofile->obfd == current_program_space->exec_bfd ())
+ maint_print_all_sections (_("Exec file: "), ofile->obfd, ofile, arg);
+ else if (allobj)
+ maint_print_all_sections (_("Object file: "), ofile->obfd, ofile, arg);
}
+
+ if (core_bfd)
+ maint_print_all_sections (_("Core file: "), core_bfd, nullptr, arg);
}
static void
diff --git a/gdb/testsuite/gdb.base/maint-info-sections.exp b/gdb/testsuite/gdb.base/maint-info-sections.exp
index 6c41ff2bd90..19e5c122226 100644
--- a/gdb/testsuite/gdb.base/maint-info-sections.exp
+++ b/gdb/testsuite/gdb.base/maint-info-sections.exp
@@ -34,7 +34,7 @@ if ![runto_main] then {
set seen_header false
set seen_a_section false
gdb_test_multiple "maint info sections" "general output check" {
- -re "Exec file:\r\n\[\t ]+`\[^'\]+', file type \[^.\]+\.\r\n" {
+ -re "Exec file: `\[^'\]+', file type \[^.\]+\.\r\n" {
set seen_header true
exp_continue
}
@@ -63,18 +63,18 @@ set text_section ".text"
set data_section ".data"
gdb_test_multiple "maint info sections" "" {
- -re -wrap "Exec file:\r\n.*${binfile}., file type.*ER_RO.*" {
+ -re -wrap "Exec file: .*${binfile}., file type.*ER_RO.*" {
# Looks like RealView which uses different section names.
set text_section ER_RO
set data_section ER_RW
pass "maint info sections"
}
- -re -wrap "Exec file:\r\n.*${binfile}., file type.*neardata.*" {
+ -re -wrap "Exec file: .*${binfile}., file type.*neardata.*" {
# c6x doesn't have .data section. It has .neardata and .fardata section.
set data_section ".neardata"
pass "maint info sections"
}
- -re -wrap "Exec file:\r\n.*${binfile}., file type.*" {
+ -re -wrap "Exec file: .*${binfile}., file type.*" {
pass "maint info sections"
}
}
@@ -125,3 +125,36 @@ gdb_test_multiple "maint info sections DATA" "" {
pass $gdb_test_name
}
}
+
+# Restart GDB, but don't load the executable.
+clean_restart
+
+# Now load the executable in as a symbol file.
+gdb_test "add-symbol-file ${binfile}" ".*" \
+ "load the executable as a symbol file" \
+ "add symbol table from file \"${binfile}\"\r\n\\(y or n\\) " \
+ "y"
+
+# As we have no object file 'maint info sections' will print nothing.
+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.
+set seen_header false
+set seen_a_section false
+gdb_test_multiple "maint info sections ALLOBJ" "" {
+ -re "Object file: `${binfile}', file type \[^.\]+\.\r\n" {
+ set seen_header true
+ exp_continue
+ }
+ -re "^ \\\[\[0-9\]+\\\]\[\t \]+$hex->$hex at $hex: \[^*\r\]+\r\n" {
+ set seen_a_section true
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ gdb_assert { $seen_header && $seen_a_section } \
+ "ensure header and section seen in ALLOBJ case"
+ pass $gdb_test_name
+ }
+}
--
2.25.4
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 2/3] gdb: 'maint info sections' - handle the no executable case
2021-02-05 21:29 ` [PATCH 2/3] gdb: 'maint info sections' - handle the no executable case Andrew Burgess
@ 2021-02-08 19:29 ` Tom Tromey
0 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2021-02-08 19:29 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches
>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:
Andrew> Unfortunately, when I tried to use 'maint info sections' I saw
Andrew> nothing. The reason is that the loop over all object files is hidden
Andrew> behind a check that we have a main executable.
Andrew> This commit removes this check and merges together some duplicate
Andrew> code. I also (I think) made the output of this command cleaner.
Yeah, I agree.
Andrew> gdb/ChangeLog:
Andrew> * maint.c (print_bfd_section_info_maybe_relocated): Delete,
Andrew> functionality merged into...
Andrew> (maint_print_all_sections): ...this new function.
Andrew> (maintenance_info_sections): Make use of maint_print_all_sections,
Andrew> allow all objects to be printed even where there's no executable.
Andrew> gdb/testsuite/ChangeLog:
Andrew> * gdb.base/maint-info-sections.exp: Update expected output, and
Andrew> add additional tests.
Looks good.
Tom
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/3] gdb: change 'maint info section' to use command options
2021-02-05 21:29 [PATCH 0/3] Changes to 'maint info sections' Andrew Burgess
2021-02-05 21:29 ` [PATCH 1/3] gdb/testsuite: split 'maint info sections' tests to a new file Andrew Burgess
2021-02-05 21:29 ` [PATCH 2/3] gdb: 'maint info sections' - handle the no executable case Andrew Burgess
@ 2021-02-05 21:29 ` Andrew Burgess
2021-02-06 7:16 ` Eli Zaretskii via Gdb-patches
2021-02-08 19:32 ` Tom Tromey
2 siblings, 2 replies; 8+ messages in thread
From: Andrew Burgess @ 2021-02-05 21:29 UTC (permalink / raw)
To: 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<single_bfd_flag_info> 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<maint_info_sections_opts> {
+ "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<const char *> 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
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 3/3] gdb: change 'maint info section' to use command options
2021-02-05 21:29 ` [PATCH 3/3] gdb: change 'maint info section' to use command options Andrew Burgess
@ 2021-02-06 7:16 ` Eli Zaretskii via Gdb-patches
2021-02-08 19:32 ` Tom Tromey
1 sibling, 0 replies; 8+ messages in thread
From: Eli Zaretskii via Gdb-patches @ 2021-02-06 7:16 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches
> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Fri, 5 Feb 2021 21:29:11 +0000
>
> 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.
Thanks, the documentation parts are approved.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 3/3] gdb: change 'maint info section' to use command options
2021-02-05 21:29 ` [PATCH 3/3] gdb: change 'maint info section' to use command options Andrew Burgess
2021-02-06 7:16 ` Eli Zaretskii via Gdb-patches
@ 2021-02-08 19:32 ` Tom Tromey
1 sibling, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2021-02-08 19:32 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches
>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:
Andrew> The ALLOBJ mechanism is replaced with a real command
Andrew> option (-all-objects). The rest of the command operates just as
Andrew> before. The example above would now become:
Andrew> (gdb) maint info sections -all-objects READONLY
Nice.
Andrew> gdb/ChangeLog:
Andrew> * NEWS: Mention changes to 'maint info sections'.
Andrew> * maint.c (match_substring): Return a bool, fix whitespace issue.
Andrew> (struct single_bfd_flag_info): New struct.
Andrew> (bfd_flag_info): New static global.
Andrew> (match_bfd_flags): Return a bool, use bfd_flag_info.
Andrew> (print_bfd_flags): Use bfd_flag_info.
Andrew> (maint_print_section_info): Delete trailing whitespace.
Andrew> (struct maint_info_sections_opts): New struct.
Andrew> (maint_info_sections_option_defs): New static global.
Andrew> (maint_info_sections_completer): New function.
Andrew> (maintenance_info_sections): Use option parsing mechanism.
Andrew> (_initialize_maint_cmds): Register command completer.
I had one nit here.
Andrew> +/* Vector of all the known bfd flags. */
Andrew> +
Andrew> +static std::vector<single_bfd_flag_info> bfd_flag_info =
Andrew> + {
I don't think you need a vector (and thus a static constructor) here.
Instead you can just use a "static const" array. The for-each
statements will still work fine in this case.
Somewhere I have a patch to remove some uses of ARRAY_SIZE in favor of
this approach...
thanks,
Tom
^ permalink raw reply [flat|nested] 8+ messages in thread