]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
Avoid spurious readelf error status from decode_arm_unwind.
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index bb6bb79d4e0370f05593bed3fb1cfa090b604d65..22d60e9a7f855a9216aef6908d0dffc54d4cf9e0 100644 (file)
@@ -321,6 +321,30 @@ static const char * get_symbol_version_string
     }                                          \
   while (0)
 \f
+/* Print a BFD_VMA to an internal buffer, for use in error messages.
+   BFD_FMA_FMT can't be used in translated strings.  */
+
+static const char *
+bfd_vmatoa (char *fmtch, bfd_vma value)
+{
+  /* bfd_vmatoa is used more then once in a printf call for output.
+     Cycle through an array of buffers.  */
+  static int buf_pos = 0;
+  static struct bfd_vmatoa_buf
+  {
+    char place[64];
+  } buf[4];
+  char *ret;
+  char fmt[32];
+
+  ret = buf[buf_pos++].place;
+  buf_pos %= ARRAY_SIZE (buf);
+
+  sprintf (fmt, "%%%s%s", BFD_VMA_FMT, fmtch);
+  snprintf (ret, sizeof (buf[0].place), fmt, value);
+  return ret;
+}
+
 /* Retrieve NMEMB structures, each SIZE bytes long from FILE starting at OFFSET +
    the offset of the current archive member, if we are examining an archive.
    Put the retrieved data into VAR, if it is not NULL.  Otherwise allocate a buffer
@@ -347,9 +371,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
          || (bfd_size_type) ((size_t) nmemb) != nmemb))
     {
       if (reason)
-       error (_("Size truncation prevents reading 0x%" BFD_VMA_FMT "x"
-                " elements of size 0x%" BFD_VMA_FMT "x for %s\n"),
-              nmemb, size, reason);
+       error (_("Size truncation prevents reading %s"
+                " elements of size %s for %s\n"),
+              bfd_vmatoa ("u", nmemb), bfd_vmatoa ("u", size), reason);
       return NULL;
     }
 
@@ -357,9 +381,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
   if (amt < nmemb)
     {
       if (reason)
-       error (_("Size overflow prevents reading 0x%" BFD_VMA_FMT "x"
-                " elements of size 0x%" BFD_VMA_FMT "x for %s\n"),
-              nmemb, size, reason);
+       error (_("Size overflow prevents reading %s"
+                " elements of size %s for %s\n"),
+              bfd_vmatoa ("u", nmemb), bfd_vmatoa ("u", size), reason);
       return NULL;
     }
 
@@ -369,9 +393,8 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
       || offset + archive_file_offset + amt > current_file_size)
     {
       if (reason)
-       error (_("Reading 0x%" BFD_VMA_FMT "x"
-                " bytes extends past end of file for %s\n"),
-              amt, reason);
+       error (_("Reading %s bytes extends past end of file for %s\n"),
+              bfd_vmatoa ("u", amt), reason);
       return NULL;
     }
 
@@ -394,9 +417,8 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
       if (mvar == NULL)
        {
          if (reason)
-           error (_("Out of memory allocating 0x%" BFD_VMA_FMT "x"
-                    " bytes for %s\n"),
-                  amt, reason);
+           error (_("Out of memory allocating %s bytes for %s\n"),
+                  bfd_vmatoa ("u", amt), reason);
          return NULL;
        }
 
@@ -406,8 +428,8 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
   if (fread (mvar, (size_t) size, (size_t) nmemb, file) != nmemb)
     {
       if (reason)
-       error (_("Unable to read in 0x%" BFD_VMA_FMT "x bytes of %s\n"),
-              amt, reason);
+       error (_("Unable to read in %s bytes of %s\n"),
+              bfd_vmatoa ("u", amt), reason);
       if (mvar != var)
        free (mvar);
       return NULL;
@@ -481,7 +503,7 @@ print_symbol (signed int width, const char *symbol)
 
   if (width < 0)
     {
-      /* Keep the width positive.  This also helps.  */
+      /* Keep the width positive.  This helps the code below.  */
       width = - width;
       extra_padding = TRUE;
     }
@@ -1520,7 +1542,7 @@ dump_relocations (FILE * file,
       if (rtype == NULL)
        printf (_("unrecognized: %-7lx"), (unsigned long) type & 0xffffffff);
       else
-       printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
+       printf (do_wide ? "%-22s" : "%-17.17s", rtype);
 
       if (elf_header.e_machine == EM_ALPHA
          && rtype != NULL
@@ -3325,6 +3347,7 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
            case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break;
            case E_MIPS_MACH_5400: strcat (buf, ", 5400"); break;
            case E_MIPS_MACH_5500: strcat (buf, ", 5500"); break;
+           case E_MIPS_MACH_5900: strcat (buf, ", 5900"); break;
            case E_MIPS_MACH_SB1:  strcat (buf, ", sb1");  break;
            case E_MIPS_MACH_9000: strcat (buf, ", 9000"); break;
            case E_MIPS_MACH_LS2E: strcat (buf, ", loongson-2e"); break;
@@ -3334,6 +3357,7 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
            case E_MIPS_MACH_OCTEON2: strcat (buf, ", octeon2"); break;
            case E_MIPS_MACH_OCTEON3: strcat (buf, ", octeon3"); break;
            case E_MIPS_MACH_XLR:  strcat (buf, ", xlr"); break;
+           case E_MIPS_MACH_IAMR2:  strcat (buf, ", interaptiv-mr2"); break;
            case 0:
            /* We simply ignore the field in this case to avoid confusion:
               MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
@@ -3725,6 +3749,16 @@ get_arm_segment_type (unsigned long type)
     }
 }
 
+static const char *
+get_s390_segment_type (unsigned long type)
+{
+  switch (type)
+    {
+    case PT_S390_PGSTE: return "S390_PGSTE";
+    default:            return NULL;
+    }
+}
+
 static const char *
 get_mips_segment_type (unsigned long type)
 {
@@ -3858,6 +3892,10 @@ get_segment_type (unsigned long p_type)
            case EM_TI_C6000:
              result = get_tic6x_segment_type (p_type);
              break;
+           case EM_S390:
+           case EM_S390_OLD:
+             result = get_s390_segment_type (p_type);
+             break;
            default:
              result = NULL;
              break;
@@ -5572,6 +5610,8 @@ get_elf_section_flags (bfd_vma sh_flags)
       /* 23 */ { STRING_COMMA_LEN ("COMDEF") },
       /* GNU specific.  */
       /* 24 */ { STRING_COMMA_LEN ("GNU_MBIND") },
+      /* VLE specific.  */
+      /* 25 */ { STRING_COMMA_LEN ("VLE") },
     };
 
   if (do_section_details)
@@ -5652,6 +5692,10 @@ get_elf_section_flags (bfd_vma sh_flags)
                    default: break;
                    }
                  break;
+               case EM_PPC:
+                 if (flag == SHF_PPC_VLE)
+                   sindex = 25;
+                 break;
 
                default:
                  break;
@@ -5709,6 +5753,9 @@ get_elf_section_flags (bfd_vma sh_flags)
              else if (elf_header.e_machine == EM_ARM
                       && flag == SHF_ARM_PURECODE)
                  *p = 'y';
+             else if (elf_header.e_machine == EM_PPC
+                      && flag == SHF_PPC_VLE)
+                 *p = 'v';
              else if (flag & SHF_MASKOS)
                {
                  *p = 'o';
@@ -6045,7 +6092,8 @@ process_section_headers (FILE * file)
        request_dump_bynumber (i, DEBUG_DUMP);
       else if (do_debug_frames && streq (name, ".eh_frame"))
        request_dump_bynumber (i, DEBUG_DUMP);
-      else if (do_gdb_index && streq (name, ".gdb_index"))
+      else if (do_gdb_index && (streq (name, ".gdb_index")
+                               || streq (name, ".debug_names")))
        request_dump_bynumber (i, DEBUG_DUMP);
       /* Trace sections for Itanium VMS.  */
       else if ((do_debugging || do_trace_info || do_trace_abbrevs
@@ -6444,6 +6492,8 @@ process_section_headers (FILE * file)
        printf (_("l (large), "));
       else if (elf_header.e_machine == EM_ARM)
        printf (_("y (purecode), "));
+      else if (elf_header.e_machine == EM_PPC)
+       printf (_("v (VLE), "));
       printf ("p (processor specific)\n");
     }
 
@@ -6690,7 +6740,7 @@ process_section_groups (FILE * file)
                      error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"),
                             entry, i, elf_header.e_shnum - 1);
                      if (num_group_errors == 10)
-                       warn (_("Futher error messages about overlarge group section indicies suppressed\n"));
+                       warn (_("Further error messages about overlarge group section indicies suppressed\n"));
                    }
                  continue;
                }
@@ -8681,7 +8731,7 @@ decode_arm_unwind (struct arm_unw_aux_info *  aux,
   unsigned int more_words = 0;
   struct absaddr addr;
   bfd_vma sym_name = (bfd_vma) -1;
-  bfd_boolean res = FALSE;
+  bfd_boolean res = TRUE;
 
   if (remaining == 0)
     {
@@ -10137,9 +10187,8 @@ process_version_sections (FILE * file)
        case SHT_GNU_verdef:
          {
            Elf_External_Verdef * edefs;
-           unsigned int idx;
-           unsigned int cnt;
-           unsigned int end;
+           unsigned long idx;
+           unsigned long cnt;
            char * endbuf;
 
            found = TRUE;
@@ -10161,23 +10210,16 @@ process_version_sections (FILE * file)
              break;
            endbuf = (char *) edefs + section->sh_size;
 
-           /* PR 17531: file: id:000001,src:000172+005151,op:splice,rep:2.  */
-           end = (section->sh_info < section->sh_size
-                  ? section->sh_info : section->sh_size);
-           for (idx = cnt = 0; cnt < end; ++cnt)
+           for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
              {
                char * vstart;
                Elf_External_Verdef * edef;
                Elf_Internal_Verdef ent;
                Elf_External_Verdaux * eaux;
                Elf_Internal_Verdaux aux;
-               unsigned int isum;
+               unsigned long isum;
                int j;
 
-               /* Check for very large indices.  */
-               if (idx > (size_t) (endbuf - (char *) edefs))
-                 break;
-
                vstart = ((char *) edefs) + idx;
                if (vstart + sizeof (*edef) > endbuf)
                  break;
@@ -10192,19 +10234,20 @@ process_version_sections (FILE * file)
                ent.vd_aux     = BYTE_GET (edef->vd_aux);
                ent.vd_next    = BYTE_GET (edef->vd_next);
 
-               printf (_("  %#06x: Rev: %d  Flags: %s"),
+               printf (_("  %#06lx: Rev: %d  Flags: %s"),
                        idx, ent.vd_version, get_ver_flags (ent.vd_flags));
 
                printf (_("  Index: %d  Cnt: %d  "),
                        ent.vd_ndx, ent.vd_cnt);
 
-               /* Check for overflow and underflow.  */
-               if (ent.vd_aux + sizeof (* eaux) > (size_t) (endbuf - vstart)
-                   || (vstart + ent.vd_aux < vstart))
+               /* Check for overflow.  */
+               if (ent.vd_aux > (size_t) (endbuf - vstart))
                  break;
 
                vstart += ent.vd_aux;
 
+               if (vstart + sizeof (*eaux) > endbuf)
+                 break;
                eaux = (Elf_External_Verdaux *) vstart;
 
                aux.vda_name = BYTE_GET (eaux->vda_name);
@@ -10219,6 +10262,14 @@ process_version_sections (FILE * file)
 
                for (j = 1; j < ent.vd_cnt; j++)
                  {
+                   if (aux.vda_next < sizeof (*eaux)
+                       && !(j == ent.vd_cnt - 1 && aux.vda_next == 0))
+                     {
+                       warn (_("Invalid vda_next field of %lx\n"),
+                             aux.vda_next);
+                       j = ent.vd_cnt;
+                       break;
+                     }
                    /* Check for overflow.  */
                    if (aux.vda_next > (size_t) (endbuf - vstart))
                      break;
@@ -10226,18 +10277,18 @@ process_version_sections (FILE * file)
                    isum   += aux.vda_next;
                    vstart += aux.vda_next;
 
-                   eaux = (Elf_External_Verdaux *) vstart;
                    if (vstart + sizeof (*eaux) > endbuf)
                      break;
+                   eaux = (Elf_External_Verdaux *) vstart;
 
                    aux.vda_name = BYTE_GET (eaux->vda_name);
                    aux.vda_next = BYTE_GET (eaux->vda_next);
 
                    if (VALID_DYNAMIC_NAME (aux.vda_name))
-                     printf (_("  %#06x: Parent %d: %s\n"),
+                     printf (_("  %#06lx: Parent %d: %s\n"),
                              isum, j, GET_DYNAMIC_NAME (aux.vda_name));
                    else
-                     printf (_("  %#06x: Parent %d, name index: %ld\n"),
+                     printf (_("  %#06lx: Parent %d, name index: %ld\n"),
                              isum, j, aux.vda_name);
                  }
 
@@ -10246,7 +10297,14 @@ process_version_sections (FILE * file)
 
                /* PR 17531:
                   file: id:000001,src:000172+005151,op:splice,rep:2.  */
-               if (idx + ent.vd_next < idx)
+               if (ent.vd_next < sizeof (*edef)
+                   && !(cnt == section->sh_info - 1 && ent.vd_next == 0))
+                 {
+                   warn (_("Invalid vd_next field of %lx\n"), ent.vd_next);
+                   cnt = section->sh_info;
+                   break;
+                 }
+               if (ent.vd_next > (size_t) (endbuf - ((char *) edefs + idx)))
                  break;
 
                idx += ent.vd_next;
@@ -10262,8 +10320,8 @@ process_version_sections (FILE * file)
        case SHT_GNU_verneed:
          {
            Elf_External_Verneed * eneed;
-           unsigned int idx;
-           unsigned int cnt;
+           unsigned long idx;
+           unsigned long cnt;
            char * endbuf;
 
            found = TRUE;
@@ -10289,13 +10347,10 @@ process_version_sections (FILE * file)
              {
                Elf_External_Verneed * entry;
                Elf_Internal_Verneed ent;
-               unsigned int isum;
+               unsigned long isum;
                int j;
                char * vstart;
 
-               if (idx > (size_t) (endbuf - (char *) eneed))
-                 break;
-
                vstart = ((char *) eneed) + idx;
                if (vstart + sizeof (*entry) > endbuf)
                  break;
@@ -10308,7 +10363,7 @@ process_version_sections (FILE * file)
                ent.vn_aux     = BYTE_GET (entry->vn_aux);
                ent.vn_next    = BYTE_GET (entry->vn_next);
 
-               printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
+               printf (_("  %#06lx: Version: %d"), idx, ent.vn_version);
 
                if (VALID_DYNAMIC_NAME (ent.vn_file))
                  printf (_("  File: %s"), GET_DYNAMIC_NAME (ent.vn_file));
@@ -10338,24 +10393,26 @@ process_version_sections (FILE * file)
                    aux.vna_next  = BYTE_GET (eaux->vna_next);
 
                    if (VALID_DYNAMIC_NAME (aux.vna_name))
-                     printf (_("  %#06x:   Name: %s"),
+                     printf (_("  %#06lx:   Name: %s"),
                              isum, GET_DYNAMIC_NAME (aux.vna_name));
                    else
-                     printf (_("  %#06x:   Name index: %lx"),
+                     printf (_("  %#06lx:   Name index: %lx"),
                              isum, aux.vna_name);
 
                    printf (_("  Flags: %s  Version: %d\n"),
                            get_ver_flags (aux.vna_flags), aux.vna_other);
 
-                   /* Check for overflow.  */
-                   if (aux.vna_next > (size_t) (endbuf - vstart)
-                       || (aux.vna_next == 0 && j < ent.vn_cnt - 1))
+                   if (aux.vna_next < sizeof (*eaux)
+                       && !(j == ent.vn_cnt - 1 && aux.vna_next == 0))
                      {
                        warn (_("Invalid vna_next field of %lx\n"),
                              aux.vna_next);
                        j = ent.vn_cnt;
                        break;
                      }
+                   /* Check for overflow.  */
+                   if (aux.vna_next > (size_t) (endbuf - vstart))
+                     break;
                    isum   += aux.vna_next;
                    vstart += aux.vna_next;
                  }
@@ -10363,12 +10420,15 @@ process_version_sections (FILE * file)
                if (j < ent.vn_cnt)
                  warn (_("Missing Version Needs auxillary information\n"));
 
-               if (ent.vn_next == 0 && cnt < section->sh_info - 1)
+               if (ent.vn_next < sizeof (*entry)
+                   && !(cnt == section->sh_info - 1 && ent.vn_next == 0))
                  {
-                   warn (_("Corrupt Version Needs structure - offset to next structure is zero with entries still left to be processed\n"));
+                   warn (_("Invalid vn_next field of %lx\n"), ent.vn_next);
                    cnt = section->sh_info;
                    break;
                  }
+               if (ent.vn_next > (size_t) (endbuf - ((char *) eneed + idx)))
+                 break;
                idx += ent.vn_next;
              }
 
@@ -10919,9 +10979,8 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size)
   if (sizeof (size_t) < sizeof (bfd_size_type)
       && (bfd_size_type) ((size_t) number) != number)
     {
-      error (_("Size truncation prevents reading %" BFD_VMA_FMT "u"
-              " elements of size %u\n"),
-            number, ent_size);
+      error (_("Size truncation prevents reading %s elements of size %u\n"),
+            bfd_vmatoa ("u", number), ent_size);
       return NULL;
     }
 
@@ -10929,23 +10988,23 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size)
      attempting to allocate memory when the read is bound to fail.  */
   if (ent_size * number > current_file_size)
     {
-      error (_("Invalid number of dynamic entries: %" BFD_VMA_FMT "u\n"),
-            number);
+      error (_("Invalid number of dynamic entries: %s\n"),
+            bfd_vmatoa ("u", number));
       return NULL;
     }
 
   e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
   if (e_data == NULL)
     {
-      error (_("Out of memory reading %" BFD_VMA_FMT "u dynamic entries\n"),
-            number);
+      error (_("Out of memory reading %s dynamic entries\n"),
+            bfd_vmatoa ("u", number));
       return NULL;
     }
 
   if (fread (e_data, ent_size, (size_t) number, file) != number)
     {
-      error (_("Unable to read in %" BFD_VMA_FMT "u bytes of dynamic data\n"),
-            number * ent_size);
+      error (_("Unable to read in %s bytes of dynamic data\n"),
+            bfd_vmatoa ("u", number * ent_size));
       free (e_data);
       return NULL;
     }
@@ -10953,9 +11012,8 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size)
   i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
   if (i_data == NULL)
     {
-      error (_("Out of memory allocating space for %" BFD_VMA_FMT "u"
-              " dynamic entries\n"),
-            number);
+      error (_("Out of memory allocating space for %s dynamic entries\n"),
+            bfd_vmatoa ("u", number));
       free (e_data);
       return NULL;
     }
@@ -11378,6 +11436,7 @@ process_symbol_table (FILE * file)
       if (dynamic_info[DT_HASH])
        {
          bfd_vma si;
+         char *visited;
 
          printf (_("\nSymbol table for image:\n"));
          if (is_32bit_elf)
@@ -11385,14 +11444,22 @@ process_symbol_table (FILE * file)
          else
            printf (_("  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name\n"));
 
+         visited = xcmalloc (nchains, 1);
+         memset (visited, 0, nchains);
          for (hn = 0; hn < nbuckets; hn++)
            {
-             if (! buckets[hn])
-               continue;
-
-             for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
-               print_dynamic_symbol (si, hn);
+             for (si = buckets[hn]; si > 0; si = chains[si])
+               {
+                 print_dynamic_symbol (si, hn);
+                 if (si >= nchains || visited[si])
+                   {
+                     error (_("histogram chain is corrupt\n"));
+                     break;
+                   }
+                 visited[si] = 1;
+               }
            }
+         free (visited);
        }
 
       if (dynamic_info_DT_GNU_HASH)
@@ -11551,7 +11618,7 @@ process_symbol_table (FILE * file)
       unsigned long maxlength = 0;
       unsigned long nzero_counts = 0;
       unsigned long nsyms = 0;
-      unsigned long chained;
+      char *visited;
 
       printf (_("\nHistogram for bucket list length (total of %lu buckets):\n"),
              (unsigned long) nbuckets);
@@ -11562,28 +11629,26 @@ process_symbol_table (FILE * file)
          error (_("Out of memory allocating space for histogram buckets\n"));
          return FALSE;
        }
+      visited = xcmalloc (nchains, 1);
+      memset (visited, 0, nchains);
 
       printf (_(" Length  Number     %% of total  Coverage\n"));
       for (hn = 0; hn < nbuckets; ++hn)
        {
-         for (si = buckets[hn], chained = 0;
-              si > 0 && si < nchains && si < nbuckets && chained <= nchains;
-              si = chains[si], ++chained)
+         for (si = buckets[hn]; si > 0; si = chains[si])
            {
              ++nsyms;
              if (maxlength < ++lengths[hn])
                ++maxlength;
+             if (si >= nchains || visited[si])
+               {
+                 error (_("histogram chain is corrupt\n"));
+                 break;
+               }
+             visited[si] = 1;
            }
-
-           /* PR binutils/17531: A corrupt binary could contain broken
-              histogram data.  Do not go into an infinite loop trying
-              to process it.  */
-           if (chained > nchains)
-             {
-               error (_("histogram chain is corrupt\n"));
-               break;
-             }
        }
+      free (visited);
 
       counts = (unsigned long *) calloc (maxlength + 1, sizeof (*counts));
       if (counts == NULL)
@@ -12053,8 +12118,10 @@ is_32bit_abs_reloc (unsigned int reloc_type)
     case EM_H8_300H:
       return reloc_type == 1; /* R_H8_DIR32.  */
     case EM_IA_64:
-      return reloc_type == 0x65 /* R_IA64_SECREL32LSB.  */
-       || reloc_type == 0x25;  /* R_IA64_DIR32LSB.  */
+      return (reloc_type == 0x64    /* R_IA64_SECREL32MSB.  */
+             || reloc_type == 0x65 /* R_IA64_SECREL32LSB.  */
+             || reloc_type == 0x24 /* R_IA64_DIR32MSB.  */
+             || reloc_type == 0x25 /* R_IA64_DIR32LSB.  */);
     case EM_IP2K_OLD:
     case EM_IP2K:
       return reloc_type == 2; /* R_IP2K_32.  */
@@ -12267,7 +12334,8 @@ is_64bit_abs_reloc (unsigned int reloc_type)
     case EM_ALPHA:
       return reloc_type == 2; /* R_ALPHA_REFQUAD.  */
     case EM_IA_64:
-      return reloc_type == 0x27; /* R_IA64_DIR64LSB.  */
+      return (reloc_type == 0x26    /* R_IA64_DIR64MSB.  */
+             || reloc_type == 0x27 /* R_IA64_DIR64LSB.  */);
     case EM_PARISC:
       return reloc_type == 80; /* R_PARISC_DIR64.  */
     case EM_PPC64:
@@ -12277,7 +12345,8 @@ is_64bit_abs_reloc (unsigned int reloc_type)
     case EM_SPARC32PLUS:
     case EM_SPARCV9:
     case EM_SPARC:
-      return reloc_type == 54; /* R_SPARC_UA64.  */
+      return reloc_type == 32 /* R_SPARC_64.  */
+       || reloc_type == 54; /* R_SPARC_UA64.  */
     case EM_X86_64:
     case EM_L1OM:
     case EM_K1OM:
@@ -12307,7 +12376,8 @@ is_64bit_pcrel_reloc (unsigned int reloc_type)
     case EM_ALPHA:
       return reloc_type == 11; /* R_ALPHA_SREL64.  */
     case EM_IA_64:
-      return reloc_type == 0x4f; /* R_IA64_PCREL64LSB.  */
+      return (reloc_type == 0x4e    /* R_IA64_PCREL64MSB.  */
+             || reloc_type == 0x4f /* R_IA64_PCREL64LSB.  */);
     case EM_PARISC:
       return reloc_type == 72; /* R_PARISC_PCREL64.  */
     case EM_PPC64:
@@ -12744,7 +12814,7 @@ get_section_contents (Elf_Internal_Shdr * section, FILE * file)
 
   if (num_bytes == 0 || section->sh_type == SHT_NOBITS)
     {
-      printf (_("\nSection '%s' has no data to dump.\n"),
+      printf (_("Section '%s' has no data to dump.\n"),
              printable_section_name (section));
       return NULL;
     }
@@ -12818,10 +12888,11 @@ dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
   unsigned char *      start;
   bfd_boolean          some_strings_shown;
 
-  real_start = start = (unsigned char *) get_section_contents (section,
-                                                              file);
+  real_start = start = (unsigned char *) get_section_contents (section, file);
   if (start == NULL)
-    return FALSE;
+    /* PR 21820: Do not fail if the section was empty.  */
+    return (section->sh_size == 0 || section->sh_type == SHT_NOBITS) ? TRUE : FALSE;
+
   num_bytes = section->sh_size;
 
   printf (_("\nString dump of section '%s':\n"), printable_section_name (section));
@@ -12967,7 +13038,8 @@ dump_section_as_bytes (Elf_Internal_Shdr * section,
 
   real_start = start = (unsigned char *) get_section_contents (section, file);
   if (start == NULL)
-    return FALSE;
+    /* PR 21820: Do not fail if the section was empty.  */
+    return (section->sh_size == 0 || section->sh_type == SHT_NOBITS) ? TRUE : FALSE;
 
   section_size = section->sh_size;
 
@@ -13698,7 +13770,7 @@ typedef struct
 
 static const char * arm_attr_tag_CPU_arch[] =
   {"Pre-v4", "v4", "v4T", "v5T", "v5TE", "v5TEJ", "v6", "v6KZ", "v6T2",
-   "v6K", "v7", "v6-M", "v6S-M", "v7E-M", "v8", "", "v8-M.baseline",
+   "v6K", "v7", "v6-M", "v6S-M", "v7E-M", "v8", "v8-R", "v8-M.baseline",
    "v8-M.mainline"};
 static const char * arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
 static const char * arm_attr_tag_THUMB_ISA_use[] =
@@ -15117,6 +15189,9 @@ print_mips_isa_ext (unsigned int isa_ext)
     case AFL_EXT_LOONGSON_2F:
       fputs ("ST Microelectronics Loongson 2F", stdout);
       break;
+    case AFL_EXT_INTERAPTIV_MR2:
+      fputs ("Imagination interAptiv MR2", stdout);
+      break;
     default:
       fprintf (stdout, "%s (%d)", _("Unknown"), isa_ext);
     }
@@ -15277,7 +15352,7 @@ process_mips_specific (FILE * file)
              printf ("\n");
            }
 
-         if (ent < end)
+         if (data != NULL && ent < end)
            {
              printf (_(" Local entries:\n"));
              printf ("  %*s %10s %*s\n",
@@ -15807,7 +15882,7 @@ process_mips_specific (FILE * file)
        }
       printf ("\n");
 
-      if (ent < local_end)
+      if (data != NULL && ent < local_end)
        {
          printf (_(" Local entries:\n"));
          printf ("  %*s %10s %*s\n",
@@ -15823,7 +15898,7 @@ process_mips_specific (FILE * file)
          printf ("\n");
        }
 
-      if (gotsym < symtabno)
+      if (data != NULL && gotsym < symtabno)
        {
          int sym_width;
 
@@ -16112,6 +16187,32 @@ get_note_type (unsigned e_type)
        return _("NT_PPC_VMX (ppc Altivec registers)");
       case NT_PPC_VSX:
        return _("NT_PPC_VSX (ppc VSX registers)");
+      case NT_PPC_TAR:
+       return _("NT_PPC_TAR (ppc TAR register)");
+      case NT_PPC_PPR:
+       return _("NT_PPC_PPR (ppc PPR register)");
+      case NT_PPC_DSCR:
+       return _("NT_PPC_DSCR (ppc DSCR register)");
+      case NT_PPC_EBB:
+       return _("NT_PPC_EBB (ppc EBB registers)");
+      case NT_PPC_PMU:
+       return _("NT_PPC_PMU (ppc PMU registers)");
+      case NT_PPC_TM_CGPR:
+       return _("NT_PPC_TM_CGPR (ppc checkpointed GPR registers)");
+      case NT_PPC_TM_CFPR:
+       return _("NT_PPC_TM_CFPR (ppc checkpointed floating point registers)");
+      case NT_PPC_TM_CVMX:
+       return _("NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)");
+      case NT_PPC_TM_CVSX:
+       return _("NT_PPC_TM_VSX (ppc checkpointed VSX registers)");
+      case NT_PPC_TM_SPR:
+       return _("NT_PPC_TM_SPR (ppc TM special purpose registers)");
+      case NT_PPC_TM_CTAR:
+       return _("NT_PPC_TM_CTAR (ppc checkpointed TAR register)");
+      case NT_PPC_TM_CPPR:
+       return _("NT_PPC_TM_CPPR (ppc checkpointed PPR register)");
+      case NT_PPC_TM_CDSCR:
+       return _("NT_PPC_TM_CDSCR (ppc checkpointed DSCR register)");
       case NT_386_TLS:
        return _("NT_386_TLS (x86 TLS information)");
       case NT_386_IOPERM:
@@ -16140,6 +16241,10 @@ get_note_type (unsigned e_type)
        return _("NT_S390_VXRS_LOW (s390 vector registers 0-15 upper half)");
       case NT_S390_VXRS_HIGH:
        return _("NT_S390_VXRS_HIGH (s390 vector registers 16-31)");
+      case NT_S390_GS_CB:
+       return _("NT_S390_GS_CB (s390 guarded-storage registers)");
+      case NT_S390_GS_BC:
+       return _("NT_S390_GS_BC (s390 guarded-storage broadcast control)");
       case NT_ARM_VFP:
        return _("NT_ARM_VFP (arm VFP registers)");
       case NT_ARM_TLS:
@@ -16194,7 +16299,11 @@ print_core_note (Elf_Internal_Note *pnote)
   unsigned char *descdata, *filenames, *descend;
 
   if (pnote->type != NT_FILE)
-    return TRUE;
+    {
+      if (do_wide)
+       printf ("\n");
+      return TRUE;
+    }
 
 #ifndef BFD64
   if (!is_32bit_elf)
@@ -16337,6 +16446,47 @@ decode_x86_isa (unsigned int bitmask)
     }
 }
 
+static void
+decode_x86_feature (unsigned int type, unsigned int bitmask)
+{
+  while (bitmask)
+    {
+      unsigned int bit = bitmask & (- bitmask);
+
+      bitmask &= ~ bit;
+      switch (bit)
+       {
+       case GNU_PROPERTY_X86_FEATURE_1_IBT:
+         switch (type)
+           {
+           case GNU_PROPERTY_X86_FEATURE_1_AND:
+             printf ("IBT");
+             break;
+           default:
+             /* This should never happen.  */
+             abort ();
+           }
+         break;
+       case GNU_PROPERTY_X86_FEATURE_1_SHSTK:
+         switch (type)
+           {
+           case GNU_PROPERTY_X86_FEATURE_1_AND:
+             printf ("SHSTK");
+             break;
+           default:
+             /* This should never happen.  */
+             abort ();
+           }
+         break;
+       default:
+         printf (_("<unknown: %x>"), bit);
+         break;
+       }
+      if (bitmask)
+       printf (", ");
+    }
+}
+
 static void
 print_gnu_property_note (Elf_Internal_Note * pnote)
 {
@@ -16391,6 +16541,14 @@ print_gnu_property_note (Elf_Internal_Note * pnote)
                    decode_x86_isa (byte_get (ptr, 4));
                  goto next;
 
+               case GNU_PROPERTY_X86_FEATURE_1_AND:
+                 printf ("x86 feature: ");
+                 if (datasz != 4)
+                   printf (_("<corrupt length: %#x> "), datasz);
+                 else
+                   decode_x86_feature (type, byte_get (ptr, 4));
+                 goto next;
+
                default:
                  break;
                }
@@ -16710,6 +16868,8 @@ get_freebsd_elfcore_note_type (unsigned e_type)
       return _("NT_PROCSTAT_PSSTRINGS (ps_strings data)");
     case NT_FREEBSD_PROCSTAT_AUXV:
       return _("NT_PROCSTAT_AUXV (auxv data)");
+    case NT_FREEBSD_PTLWPINFO:
+      return _("NT_PTLWPINFO (ptrace_lwpinfo structure)");
     }
   return get_note_type (e_type);
 }
@@ -17118,7 +17278,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
   const char * expected_types;
   const char * name = pnote->namedata;
   const char * text;
-  int          left;
+  signed int   left;
 
   if (name == NULL || pnote->namesz < 2)
     {
@@ -17127,6 +17287,16 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       return FALSE;
     }
 
+  left = 20;
+
+  /* Version 2 of the spec adds a "GA" prefix to the name field.  */
+  if (name[0] == 'G' && name[1] == 'A')
+    {
+      printf ("GA");
+      name += 2;
+      left -= 2;
+    }
+
   switch ((name_type = * name))
     {
     case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
@@ -17134,6 +17304,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
     case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
     case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
       printf ("%c", * name);
+      left --;
       break;
     default:
       error (_("unrecognised attribute type in name field: %d\n"), name_type);
@@ -17141,7 +17312,6 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       return FALSE;
     }
 
-  left = 19;
   ++ name;
   text = NULL;
 
@@ -17201,6 +17371,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       else
        {
          static char tmpbuf [128];
+
          error (_("unrecognised byte in name field: %d\n"), * name);
          sprintf (tmpbuf, _("<unknown:_%d>"), * name);
          text = tmpbuf;
@@ -17211,10 +17382,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
     }
 
   if (text)
-    {
-      printf ("%s", text);
-      left -= strlen (text);
-    }
+    left -= printf ("%s", text);
 
   if (strchr (expected_types, name_type) == NULL)
     warn (_("attribute does not have an expected type (%c)\n"), name_type);
@@ -17385,8 +17553,11 @@ process_note (Elf_Internal_Note *  pnote,
 
   printf ("  ");
 
-  if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
-      || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
+  if (((const_strneq (pnote->namedata, "GA")
+       && strchr ("*$!+", pnote->namedata[2]) != NULL)
+       || strchr ("*$!+", pnote->namedata[0]) != NULL)
+      && (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
+         || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC))
     print_gnu_build_attribute_name (pnote);
   else
     print_symbol (-20, name);
@@ -17404,8 +17575,11 @@ process_note (Elf_Internal_Note *  pnote,
     return print_stapsdt_note (pnote);
   else if (const_strneq (pnote->namedata, "CORE"))
     return print_core_note (pnote);
-  else if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
-          || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
+  else if (((const_strneq (pnote->namedata, "GA")
+            && strchr ("*$!+", pnote->namedata[2]) != NULL)
+           || strchr ("*$!+", pnote->namedata[0]) != NULL)
+          && (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
+              || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC))
     return print_gnu_build_attribute_description (pnote, file);
 
   if (pnote->descsz)
@@ -17415,6 +17589,8 @@ process_note (Elf_Internal_Note *  pnote,
       printf (_("   description data: "));
       for (i = 0; i < pnote->descsz; i++)
        printf ("%02x ", pnote->descdata[i]);
+      if (!do_wide)
+       printf ("\n");
     }
 
   if (do_wide)