]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
binutils/
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index 4db0a10f4dfd670f3353845eae1937d221568176..29e1c8bc5b84c50049c463a85de8f51609fde5ed 100644 (file)
@@ -140,6 +140,7 @@ int do_dynamic;
 int do_syms;
 int do_reloc;
 int do_sections;
+int do_section_groups;
 int do_segments;
 int do_unwind;
 int do_using_dynamic;
@@ -2393,6 +2394,7 @@ struct option options[] =
   {"segments",        no_argument, 0, 'l'},
   {"sections",        no_argument, 0, 'S'},
   {"section-headers",  no_argument, 0, 'S'},
+  {"section-groups",   no_argument, 0, 'g'},
   {"symbols",         no_argument, 0, 's'},
   {"syms",            no_argument, 0, 's'},
   {"relocs",          no_argument, 0, 'r'},
@@ -2426,6 +2428,7 @@ usage (void)
      --segments          An alias for --program-headers\n\
   -S --section-headers   Display the sections' header\n\
      --sections          An alias for --section-headers\n\
+  -g --section-groups    Display the section groups\n\
   -e --headers           Equivalent to: -h -l -S\n\
   -s --syms              Display the symbol table\n\
       --symbols          An alias for --syms\n\
@@ -2493,7 +2496,7 @@ parse_args (int argc, char **argv)
     usage ();
 
   while ((c = getopt_long
-         (argc, argv, "ersuahnldSDAIw::x:i:vVWH", options, NULL)) != EOF)
+         (argc, argv, "ersuahnldSDAIgw::x:i:vVWH", options, NULL)) != EOF)
     {
       char *cp;
       int section;
@@ -2514,12 +2517,16 @@ parse_args (int argc, char **argv)
          do_dynamic++;
          do_header++;
          do_sections++;
+         do_section_groups++;
          do_segments++;
          do_version++;
          do_histogram++;
          do_arch++;
          do_notes++;
          break;
+       case 'g':
+         do_section_groups++;
+         break;
        case 'e':
          do_header++;
          do_sections++;
@@ -2746,7 +2753,8 @@ parse_args (int argc, char **argv)
 
   if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
       && !do_segments && !do_header && !do_dump && !do_version
-      && !do_histogram && !do_debugging && !do_arch && !do_notes)
+      && !do_histogram && !do_debugging && !do_arch && !do_notes
+      && !do_section_groups)
     usage ();
   else if (argc < 3)
     {
@@ -3703,6 +3711,124 @@ process_section_headers (FILE *file)
   return 1;
 }
 
+static const char *
+get_group_flags (unsigned int flags)
+{
+  static char buff[32];
+  switch (flags)
+    {
+    case GRP_COMDAT:
+      return "COMDAT";
+
+   default:
+      sprintf (buff, _("[<unknown>: 0x%x]"), flags);
+      break;
+    }
+  return buff;
+}
+
+static int
+process_section_groups (FILE *file)
+{
+  Elf_Internal_Shdr *section;
+  unsigned int i;
+
+  if (!do_section_groups)
+    return 1;
+
+  if (elf_header.e_shnum == 0)
+    {
+      if (do_section_groups)
+       printf (_("\nThere are no section groups in this file.\n"));
+
+      return 1;
+    }
+
+  if (section_headers == NULL)
+    {
+      error (_("Section headers are not available!\n"));
+      abort ();
+    }
+
+  /* Scan the sections for the group section.  */
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum;
+       i++, section++)
+    {
+      if (section->sh_type == SHT_GROUP)
+       {
+         char *name = SECTION_NAME (section);
+         char *group_name, *strtab, *start, *indices;
+         unsigned int entry, j, size;
+         Elf_Internal_Sym *sym;
+         Elf_Internal_Shdr *symtab_sec, *strtab_sec, *sec;
+         Elf_Internal_Sym *symtab;
+
+         /* Get the symbol table.  */
+         symtab_sec = SECTION_HEADER (section->sh_link);
+         if (symtab_sec->sh_type != SHT_SYMTAB)
+           {
+             error (_("Bad sh_link in group section `%s'\n"), name);
+             continue;
+           }
+         symtab = GET_ELF_SYMBOLS (file, symtab_sec);
+
+         sym = symtab + section->sh_info;
+
+         if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+           {
+             bfd_vma sec_index = SECTION_HEADER_INDEX (sym->st_shndx);
+             if (sec_index == 0)
+               {
+                 error (_("Bad sh_info in group section `%s'\n"), name);
+                 continue;
+               }
+             
+             group_name = SECTION_NAME (section_headers + sec_index);
+             strtab = NULL;
+           }
+         else
+           {
+             /* Get the string table.  */
+             strtab_sec = SECTION_HEADER (symtab_sec->sh_link);
+             strtab = get_data (NULL, file, strtab_sec->sh_offset,
+                                strtab_sec->sh_size,
+                                _("string table"));
+
+             group_name = strtab + sym->st_name;
+           }
+
+         start = get_data (NULL, file, section->sh_offset,
+                           section->sh_size, _("section data"));
+
+         indices = start;
+         size = (section->sh_size / section->sh_entsize) - 1;
+         entry = byte_get (indices, 4);
+         indices += 4;
+         printf ("\n%s group section `%s' [%s] contains %u sections:\n",
+                 get_group_flags (entry), name, group_name, size);
+         
+         printf (_("   [Index]    Name\n"));
+         for (j = 0; j < size; j++)
+           {
+             entry = byte_get (indices, 4);
+             indices += 4;
+
+             sec = SECTION_HEADER (entry);
+             printf ("   [%5u]   %s\n",
+                     entry, SECTION_NAME (sec));
+           }
+
+         if (strtab)
+           free (strtab);
+         if (start)
+           free (start);
+       }
+    }
+
+  return 1;
+}
+
 struct
 {
   const char *name;
@@ -10331,6 +10457,8 @@ process_object (char *file_name, FILE *file)
 
   process_section_contents (file);
 
+  process_section_groups (file);
+
   process_corefile_contents (file);
 
   process_gnu_liblist (file);