PATCH: Fix a section group bug

H. J. Lu hjl@lucon.org
Mon Apr 26 22:21:00 GMT 2004


The current assembler will dump core on

section       .text,"axG",@progbits,.foo_group,comdat


This patch fixes it. I also added the --section-groups/-g option to
readelf.


H.J.
-------------- next part --------------
binutils/

2004-04-26  H.J. Lu  <hongjiu.lu@intel.com>

	* readelf.c (do_section_groups): New.
	(options): Add --section-groups/-g.
	(usage): Mention --section-groups/-g.
	(parse_args): Support --section-groups/-g.
	(get_group_flags): New.
	(process_section_groups): New.
	(process_object): Call process_section_groups.

gas/

2004-04-26  H.J. Lu  <hongjiu.lu@intel.com>

	* config/obj-elf.c (obj_elf_change_section): Check if the old
	group name is NULL before comparison.

gas/testsuite/

2004-04-26  H.J. Lu  <hongjiu.lu@intel.com>

	* gas/elf/elf.exp: Add group0a, group0b and group1 for section
	group.

	* gas/elf/group0.s: New file.
	* gas/elf/group0a.d: Likewise.
	* gas/elf/group0b.d: Likewise.
	* gas/elf/group1.e: Likewise.
	* gas/elf/group1.s: Likewise.

--- binutils/binutils/readelf.c.group	2004-04-01 08:34:45.000000000 -0800
+++ binutils/binutils/readelf.c	2004-04-26 14:55:53.000000000 -0700
@@ -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 *f
 
   process_section_contents (file);
 
+  process_section_groups (file);
+
   process_corefile_contents (file);
 
   process_gnu_liblist (file);
--- binutils/gas/config/obj-elf.c.group	2004-03-18 10:11:27.000000000 -0800
+++ binutils/gas/config/obj-elf.c	2004-04-26 14:41:52.000000000 -0700
@@ -645,7 +645,8 @@ obj_elf_change_section (const char *name
       if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
 	as_warn (_("ignoring changed section entity size for %s"), name);
       if ((attr & SHF_GROUP) != 0
-	  && strcmp (elf_group_name (old_sec), group_name) != 0)
+	  && (elf_group_name (old_sec) == NULL
+	      || strcmp (elf_group_name (old_sec), group_name) != 0))
 	as_warn (_("ignoring new section group for %s"), name);
     }
 
--- binutils/gas/testsuite/gas/elf/elf.exp.group	2003-11-10 11:36:12.000000000 -0800
+++ binutils/gas/testsuite/gas/elf/elf.exp	2004-04-26 14:21:00.000000000 -0700
@@ -48,6 +48,9 @@ if { ([istarget "*-*-elf*"]		
 	set target_machine -m32r
     }
     run_dump_test "ehopt0"
+    run_dump_test "group0a" 
+    run_dump_test "group0b" 
+    run_list_test "group1" "" "" ""
     run_dump_test "section0" 
     run_dump_test "section1" 
     run_list_test "section2" "$target_machine" "-al" ""
--- binutils/gas/testsuite/gas/elf/group0.s.group	2004-04-26 11:03:08.000000000 -0700
+++ binutils/gas/testsuite/gas/elf/group0.s	2004-04-26 10:45:11.000000000 -0700
@@ -0,0 +1,4 @@
+	.section       .foo,"axG",@progbits,.foo_group,comdat
+	.byte	1
+	.section       .bar,"aG",@progbits,.foo_group,comdat
+	.byte	1
--- binutils/gas/testsuite/gas/elf/group0a.d.group	2004-04-26 11:03:05.000000000 -0700
+++ binutils/gas/testsuite/gas/elf/group0a.d	2004-04-26 14:29:47.000000000 -0700
@@ -0,0 +1,9 @@
+#readelf: -SW
+#name: group section
+#source: group0.s
+
+#...
+[ 	]*\[.*\][ 	]+\.foo[ 	]+PROGBITS.*[ 	]+AXG[ 	]+.*
+[ 	]*\[.*\][ 	]+\.bar[ 	]+PROGBITS.*[ 	]+AG[ 	]+.*
+[ 	]*\[.*\][ 	]+\.foo_group[ 	]+GROUP.*
+#pass
--- binutils/gas/testsuite/gas/elf/group0b.d.group	2004-04-26 14:21:14.000000000 -0700
+++ binutils/gas/testsuite/gas/elf/group0b.d	2004-04-26 14:22:30.000000000 -0700
@@ -0,0 +1,10 @@
+#readelf: -g
+#name: group section
+#source: group0.s
+
+#...
+COMDAT group section `.foo_group' \[.foo_group\] contains 2 sections:
+[ 	]+\[Index\][ 	]+Name
+[ 	]+\[.*\][ 	]+.foo
+[ 	]+\[.*\][ 	]+.bar
+#pass
--- binutils/gas/testsuite/gas/elf/group1.e.group	2004-04-26 11:03:19.000000000 -0700
+++ binutils/gas/testsuite/gas/elf/group1.e	2004-04-26 11:02:40.000000000 -0700
@@ -0,0 +1,7 @@
+
+Symbol table '.symtab' contains 4 entries:
+   Num:    Value[ 	]* Size Type    Bind   Vis      Ndx Name
+     0: 0+0     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 0+0     0 SECTION LOCAL  DEFAULT    1 
+     2: 0+0     0 SECTION LOCAL  DEFAULT    2 
+     3: 0+0     0 SECTION LOCAL  DEFAULT    3 
--- binutils/gas/testsuite/gas/elf/group1.s.group	2004-04-26 11:03:11.000000000 -0700
+++ binutils/gas/testsuite/gas/elf/group1.s	2004-04-26 10:45:57.000000000 -0700
@@ -0,0 +1,2 @@
+	.section       .text,"axG",@progbits,.foo_group,comdat
+	.byte	1


More information about the Binutils mailing list