gdb: Have 'maint info sections' print all sections again
[deliverable/binutils-gdb.git] / gdb / maint.c
index 837ed23cfb6b9217aacab4103b687eb7ba51ec15..286ec31013571b661f166a4666c9bfee30318dad 100644 (file)
@@ -23,6 +23,7 @@
 #include "defs.h"
 #include "arch-utils.h"
 #include <ctype.h>
+#include <cmath>
 #include <signal.h>
 #include "command.h"
 #include "gdbcmd.h"
@@ -276,14 +277,68 @@ maint_print_section_info (const char *name, flagword flags,
   printf_filtered ("\n");
 }
 
+/* Information passed between the "maintenance info sections" command, and
+   the worker function that prints each section.  */
+struct maint_print_section_data
+{
+  /* The GDB objfile we're printing this section for.  */
+  struct objfile *objfile;
+
+  /* The argument string passed by the user to the top level maintenance
+     info sections command.  Used for filtering which sections are
+     printed.  */
+  const char *arg;
+
+  /* The number of digits in the highest section index for all sections
+     from the bfd object associated with OBJFILE.  Used when pretty
+     printing the index number to ensure all of the indexes line up.  */
+  int index_digits;
+
+  /* Constructor.  */
+  maint_print_section_data (struct objfile *objfile, const char *arg,
+                           bfd *abfd)
+    : objfile (objfile),
+      arg(arg)
+  {
+    int section_count = gdb_bfd_count_sections (abfd);
+    index_digits = ((int) log10 (section_count)) + 1;
+  }
+
+private:
+  maint_print_section_data () = delete;
+  maint_print_section_data (const maint_print_section_data &) = delete;
+};
+
+/* Helper function to pretty-print the section index of ASECT from ABFD.
+   The INDEX_DIGITS is the number of digits in the largest index that will
+   be printed, and is used to pretty-print the resulting string.  */
+
+static void
+print_section_index (bfd *abfd,
+                    asection *asect,
+                    int index_digits)
+{
+  std::string result
+    = string_printf (" [%d] ", gdb_bfd_section_index (abfd, asect));
+  /* The '+ 4' for the leading and trailing characters.  */
+  printf_filtered ("%-*s", (index_digits + 4), result.c_str ());
+}
+
+/* Print information about ASECT from ABFD.  DATUM holds a pointer to a
+   maint_print_section_data object.  The section will be printed using the
+   VMA's from the bfd, which will not be the relocated addresses for bfds
+   that should be relocated.  The information must be printed with the
+   same layout as PRINT_OBJFILE_SECTION_INFO below.  */
+
 static void
-print_bfd_section_info (bfd *abfd, 
-                       asection *asect, 
+print_bfd_section_info (bfd *abfd,
+                       asection *asect,
                        void *datum)
 {
   flagword flags = bfd_get_section_flags (abfd, asect);
   const char *name = bfd_section_name (abfd, asect);
-  const char *arg = (const char *) datum;
+  maint_print_section_data *print_data = (maint_print_section_data *) datum;
+  const char *arg = print_data->arg;
 
   if (arg == NULL || *arg == '\0'
       || match_substring (arg, name)
@@ -295,19 +350,25 @@ print_bfd_section_info (bfd *abfd,
 
       addr = bfd_section_vma (abfd, asect);
       endaddr = addr + bfd_section_size (abfd, asect);
-      printf_filtered (" [%d] ", gdb_bfd_section_index (abfd, asect));
+      print_section_index (abfd, asect, print_data->index_digits);
       maint_print_section_info (name, flags, addr, endaddr,
                                asect->filepos, addr_size);
     }
 }
 
+/* Print information about ASECT which is GDB's wrapper around a section
+   from ABFD.  The information must be printed with the same layout as
+   PRINT_BFD_SECTION_INFO above.  PRINT_DATA holds information used to
+   filter which sections are printed, and for formatting the output.  */
+
 static void
-print_objfile_section_info (bfd *abfd, 
-                           struct obj_section *asect, 
-                           const char *string)
+print_objfile_section_info (bfd *abfd,
+                           struct obj_section *asect,
+                           maint_print_section_data *print_data)
 {
   flagword flags = bfd_get_section_flags (abfd, asect->the_bfd_section);
   const char *name = bfd_section_name (abfd, asect->the_bfd_section);
+  const char *string = print_data->arg;
 
   if (string == NULL || *string == '\0'
       || match_substring (string, name)
@@ -316,6 +377,8 @@ print_objfile_section_info (bfd *abfd,
       struct gdbarch *gdbarch = gdbarch_from_bfd (abfd);
       int addr_size = gdbarch_addr_bit (gdbarch) / 8;
 
+      print_section_index (abfd, asect->the_bfd_section,
+                          print_data->index_digits);
       maint_print_section_info (name, flags,
                                obj_section_addr (asect),
                                obj_section_endaddr (asect),
@@ -324,12 +387,56 @@ print_objfile_section_info (bfd *abfd,
     }
 }
 
+/* Find an obj_section, GDB's wrapper around a bfd section for ASECTION
+   from ABFD.  It might be that no such wrapper exists (for example debug
+   sections don't have such wrappers) in which case nullptr is returned.  */
+
+static obj_section *
+maint_obj_section_from_bfd_section (bfd *abfd,
+                                   asection *asection,
+                                   objfile *ofile)
+{
+  if (ofile->sections == nullptr)
+    return nullptr;
+
+  obj_section *osect
+    = &ofile->sections[gdb_bfd_section_index (abfd, asection)];
+
+  if (osect >= ofile->sections_end)
+    return nullptr;
+
+  return osect;
+}
+
+/* Print information about ASECT from ABFD.  DATUM holds a pointer to a
+   maint_print_section_data object.  Where possible the information for
+   ASECT will print the relocated addresses of the section.  */
+
+static void
+print_bfd_section_info_maybe_relocated (bfd *abfd,
+                                       asection *asect,
+                                       void *datum)
+{
+  maint_print_section_data *print_data = (maint_print_section_data *) datum;
+  objfile *objfile = print_data->objfile;
+
+  gdb_assert (objfile->sections != NULL);
+  obj_section *osect
+    = maint_obj_section_from_bfd_section (abfd, asect, objfile);
+
+  if (osect->the_bfd_section == NULL)
+    print_bfd_section_info (abfd, asect, datum);
+  else
+    print_objfile_section_info (abfd, osect, print_data);
+}
+
+/* Implement the "maintenance info sections" command.  */
+
 static void
 maintenance_info_sections (const char *arg, int from_tty)
 {
   if (exec_bfd)
     {
-      struct obj_section *osect;
       bool allobj = false;
 
       printf_filtered (_("Exec file:\n"));
@@ -352,22 +459,27 @@ maintenance_info_sections (const char *arg, int from_tty)
          if (allobj)
            printf_filtered (_("  Object file: %s\n"),
                             bfd_get_filename (ofile->obfd));
-         ALL_OBJFILE_OSECTIONS (ofile, osect)
-           {
-             if (!allobj && ofile->obfd != exec_bfd)
-               continue;
-             print_objfile_section_info (ofile->obfd, osect, arg);
-           }
+         else if (ofile->obfd != exec_bfd)
+           continue;
+
+         maint_print_section_data print_data (ofile, arg, ofile->obfd);
+
+         bfd_map_over_sections (ofile->obfd,
+                                print_bfd_section_info_maybe_relocated,
+                                (void *) &print_data);
        }
     }
 
   if (core_bfd)
     {
+      maint_print_section_data print_data (nullptr, arg, core_bfd);
+
       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));
-      bfd_map_over_sections (core_bfd, print_bfd_section_info, (void *) arg);
+      bfd_map_over_sections (core_bfd, print_bfd_section_info,
+                            (void *) &print_data);
     }
 }
 
This page took 0.043043 seconds and 4 git commands to generate.