OSDN Git Service

PR 10478:
authornickc <nickc>
Wed, 9 Sep 2009 15:03:51 +0000 (15:03 +0000)
committernickc <nickc>
Wed, 9 Sep 2009 15:03:51 +0000 (15:03 +0000)
        * elf.c (bfd_section_from_shdr): Do not reject sparc binaries with
        section headers containing sh_link values of SHN_BEFORE or
        SHN_AFTER.
        * elfcode.h (elf_object_p): Likewise.

        readelf.c (get_elf_section_flags): Add support for SHF_EXCLUDE and
        SHF_ORDERED.
        (process_section_headers): Warn about out of range sh_link
        values.  When displaying detailed section header information
        annote the SHN_BEFORE and SHN_AFTER values.

bfd/ChangeLog
bfd/elf.c
bfd/elfcode.h
binutils/ChangeLog
binutils/readelf.c

index 39ee6fd..82a663b 100644 (file)
@@ -1,3 +1,11 @@
+2009-09-09  Nick Clifton  <nickc@redhat.com>
+
+       PR 10478:
+       * elf.c (bfd_section_from_shdr): Do not reject sparc binaries with
+       section headers containing sh_link values of SHN_BEFORE or
+       SHN_AFTER.
+       * elfcode.h (elf_object_p): Likewise.
+
 2009-09-09  Tristan Gingold  <gingold@adacore.com>
 
        Handle DYLD_INFO introduced by Darwin10.
@@ -12,7 +20,6 @@
        (bfd_mach_o_load_command_name): AddB FD_MACH_O_LC_DYLD_INFO.
        (bfd_mach_o_print_dyld_info): New function.
 
-
 2009-09-09  M R Swami Reddy <MR.Swami.Reddy@nsc.com>
 
        * elf32-cr16.c (elf32_cr16_relocate_section): Add code to discard the
index 13f6904..ed974c0 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1514,10 +1514,24 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
     case SHT_DYNAMIC:  /* Dynamic linking information.  */
       if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
        return FALSE;
-      if (hdr->sh_link > elf_numsections (abfd)
-         || elf_elfsections (abfd)[hdr->sh_link] == NULL)
+      if (hdr->sh_link > elf_numsections (abfd))
+       {
+         /* PR 10478: Accept sparc binaries with a sh_link
+            field set to SHN_BEFORE or SHN_AFTER.  */
+         switch (bfd_get_arch (abfd))
+           {
+           case bfd_arch_sparc:
+             if (hdr->sh_link == (SHN_LORESERVE & 0xffff) /* SHN_BEFORE */
+                 || hdr->sh_link == ((SHN_LORESERVE + 1) & 0xffff) /* SHN_AFTER */)
+               break;
+             /* Otherwise fall through.  */
+           default:
+             return FALSE;
+           }
+       }
+      else if (elf_elfsections (abfd)[hdr->sh_link] == NULL)
        return FALSE;
-      if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
+      else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
        {
          Elf_Internal_Shdr *dynsymhdr;
 
index 10aa131..889d25a 100644 (file)
@@ -760,7 +760,23 @@ elf_object_p (bfd *abfd)
 
          /* Sanity check sh_link and sh_info.  */
          if (i_shdrp[shindex].sh_link >= num_sec)
-           goto got_wrong_format_error;
+           {
+             /* PR 10478: Accept sparc binaries with a sh_link
+                field set to SHN_BEFORE or SHN_AFTER.  */
+             switch (ebd->elf_machine_code)
+               {
+               case EM_OLD_SPARCV9:
+               case EM_SPARC32PLUS:
+               case EM_SPARCV9:
+               case EM_SPARC:
+                 if (i_shdrp[shindex].sh_link == (SHN_LORESERVE & 0xffff) /* SHN_BEFORE */
+                     || i_shdrp[shindex].sh_link == ((SHN_LORESERVE + 1) & 0xffff) /* SHN_AFTER */)
+                   break;
+                 /* Otherwise fall through.  */
+               default:
+                 goto got_wrong_format_error;
+               }
+           }
 
          if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK)
               || i_shdrp[shindex].sh_type == SHT_RELA
index 1722fe7..022cda5 100644 (file)
@@ -1,3 +1,12 @@
+2009-09-09  Nick Clifton  <nickc@redhat.com>
+
+       PR 10478:
+       readelf.c (get_elf_section_flags): Add support for SHF_EXCLUDE and
+       SHF_ORDERED.
+       (process_section_headers): Warn about out of range sh_link
+       values.  When displaying detailed section header information
+       annote the SHN_BEFORE and SHN_AFTER values.
+
 2009-09-08  Alan Modra  <amodra@bigpond.net.au>
 
        * dwarf.c (byte_get_little_endian): Handle size of 3.
index 590c70d..872ec09 100644 (file)
@@ -3873,26 +3873,29 @@ get_elf_section_flags (bfd_vma sh_flags)
     }
   flags [] =
     {
-       { "WRITE", 5 },
-       { "ALLOC", 5 },
-       { "EXEC", 4 },
-       { "MERGE", 5 },
-       { "STRINGS", 7 },
-       { "INFO LINK", 9 },
-       { "LINK ORDER", 10 },
-       { "OS NONCONF", 10 },
-       { "GROUP", 5 },
-       { "TLS", 3 },
-       /* IA-64 specific.  */
-       { "SHORT", 5 },
-       { "NORECOV", 7 },
-       /* IA-64 OpenVMS specific.  */
-       { "VMS_GLOBAL", 10 },
-       { "VMS_OVERLAID", 12 },
-       { "VMS_SHARED", 10 },
-       { "VMS_VECTOR", 10 },
-       { "VMS_ALLOC_64BIT", 15 },
-       { "VMS_PROTECTED", 13}
+      /*  0 */ { STRING_COMMA_LEN ("WRITE") },
+      /*  1 */ { STRING_COMMA_LEN ("ALLOC") },
+      /*  2 */ { STRING_COMMA_LEN ("EXEC") },
+      /*  3 */ { STRING_COMMA_LEN ("MERGE") },
+      /*  4 */ { STRING_COMMA_LEN ("STRINGS") },
+      /*  5 */ { STRING_COMMA_LEN ("INFO LINK") },
+      /*  6 */ { STRING_COMMA_LEN ("LINK ORDER") },
+      /*  7 */ { STRING_COMMA_LEN ("OS NONCONF") },
+      /*  8 */ { STRING_COMMA_LEN ("GROUP") },
+      /*  9 */ { STRING_COMMA_LEN ("TLS") },
+      /* IA-64 specific.  */
+      /* 10 */ { STRING_COMMA_LEN ("SHORT") },
+      /* 11 */ { STRING_COMMA_LEN ("NORECOV") },
+      /* IA-64 OpenVMS specific.  */
+      /* 12 */ { STRING_COMMA_LEN ("VMS_GLOBAL") },
+      /* 13 */ { STRING_COMMA_LEN ("VMS_OVERLAID") },
+      /* 14 */ { STRING_COMMA_LEN ("VMS_SHARED") },
+      /* 15 */ { STRING_COMMA_LEN ("VMS_VECTOR") },
+      /* 16 */ { STRING_COMMA_LEN ("VMS_ALLOC_64BIT") },
+      /* 17 */ { STRING_COMMA_LEN ("VMS_PROTECTED") },
+      /* SPARC specific.  */
+      /* 18 */ { STRING_COMMA_LEN ("EXCLUDE") },
+      /* 19 */ { STRING_COMMA_LEN ("ORDERED") }
     };
 
   if (do_section_details)
@@ -3926,8 +3929,9 @@ get_elf_section_flags (bfd_vma sh_flags)
 
            default:
              index = -1;
-             if (elf_header.e_machine == EM_IA_64)
+             switch (elf_header.e_machine)
                {
+               case EM_IA_64:
                  if (flag == SHF_IA_64_SHORT)
                    index = 10;
                  else if (flag == SHF_IA_64_NORECOV)
@@ -3945,8 +3949,20 @@ get_elf_section_flags (bfd_vma sh_flags)
                      default:                        break;
                      }
 #endif
+                 break;
+
+               case EM_OLD_SPARCV9:
+               case EM_SPARC32PLUS:
+               case EM_SPARCV9:
+               case EM_SPARC:
+                 if (flag == SHF_EXCLUDE)
+                   index = 18;
+                 else if (flag == SHF_ORDERED)
+                   index = 19;
+                 break;
+               default:
+                 break;
                }
-             break;
            }
 
          if (index != -1)
@@ -4327,6 +4343,8 @@ process_section_headers (FILE * file)
 
       if (is_32bit_elf)
        {
+         const char * link_too_big = NULL;
+
          print_vma (section->sh_addr, LONG_HEX);
 
          printf ( " %6.6lx %6.6lx %2.2lx",
@@ -4339,10 +4357,45 @@ process_section_headers (FILE * file)
          else
            printf (" %3s ", get_elf_section_flags (section->sh_flags));
 
-         printf ("%2u %3u %2lu\n",
-                 section->sh_link,
-                 section->sh_info,
-                 (unsigned long) section->sh_addralign);
+         if (section->sh_link >= elf_header.e_shnum)
+           {
+             link_too_big = "";
+             /* The sh_link value is out of range.  Normally this indicates
+                an error but it can have special values in SPARC binaries.  */
+             switch (elf_header.e_machine)
+               {
+               case EM_OLD_SPARCV9:
+               case EM_SPARC32PLUS:
+               case EM_SPARCV9:
+               case EM_SPARC:
+                 if (section->sh_link == (SHN_BEFORE & 0xffff))
+                   link_too_big = "BEFORE";
+                 else if (section->sh_link == (SHN_AFTER & 0xffff))
+                   link_too_big = "AFTER";
+                 break;
+               default:
+                 break;
+               }
+           }
+
+         if (do_section_details)
+           {
+             if (link_too_big != NULL && * link_too_big)
+               printf ("<%s> ", link_too_big);
+             else
+               printf ("%2u ", section->sh_link);
+             printf ("%3u %2lu\n", section->sh_info,
+                     (unsigned long) section->sh_addralign);
+           }
+         else
+           printf ("%2u %3u %2lu\n",
+                   section->sh_link,
+                   section->sh_info,
+                   (unsigned long) section->sh_addralign);
+
+         if (link_too_big && ! * link_too_big)
+           warn (_("section %u: sh_link value of %u is larger than the number of sections\n"),
+                 i, section->sh_link);
        }
       else if (do_wide)
        {