Always use a hex prefix when displaying the alignment of program headers.
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 61f2939fdc284fb7521cf700a35eba0a3cdea156..69d88892d707bff0bc7bb54dfa74d29c136b8a64 100644 (file)
 #include "elf/metag.h"
 #include "elf/microblaze.h"
 #include "elf/mips.h"
+#include "elf/riscv.h"
 #include "elf/mmix.h"
 #include "elf/mn10200.h"
 #include "elf/mn10300.h"
@@ -426,7 +427,7 @@ print_vma (bfd_vma vma, print_mode mode)
     {
     case FULL_HEX:
       nc = printf ("0x");
-      /* Drop through.  */
+      /* Fall through.  */
 
     case LONG_HEX:
 #ifdef BFD64
@@ -439,11 +440,11 @@ print_vma (bfd_vma vma, print_mode mode)
     case DEC_5:
       if (vma <= 99999)
        return printf ("%5" BFD_VMA_FMT "d", vma);
-      /* Drop through.  */
+      /* Fall through.  */
 
     case PREFIX_HEX:
       nc = printf ("0x");
-      /* Drop through.  */
+      /* Fall through.  */
 
     case HEX:
       return nc + printf ("%" BFD_VMA_FMT "x", vma);
@@ -556,7 +557,7 @@ print_symbol (int width, const char *symbol)
   return num_printed;
 }
 
-/* Returns a pointer to a static buffer containing a  printable version of
+/* Returns a pointer to a static buffer containing a printable version of
    the given section's name.  Like print_symbol, except that it does not try
    to print multibyte characters, it just interprets them as hex values.  */
 
@@ -775,6 +776,7 @@ guess_is_rela (unsigned int e_machine)
     case EM_OR1K:
     case EM_PPC64:
     case EM_PPC:
+    case EM_RISCV:
     case EM_RL78:
     case EM_RX:
     case EM_S390:
@@ -1292,6 +1294,7 @@ dump_relocations (FILE * file,
              rtype = elf_msp430x_reloc_type (type);
              break;
            }
+         /* Fall through.  */
        case EM_MSP430_OLD:
          rtype = elf_msp430_reloc_type (type);
          break;
@@ -1313,6 +1316,10 @@ dump_relocations (FILE * file,
          rtype = elf_mips_reloc_type (type);
          break;
 
+       case EM_RISCV:
+         rtype = elf_riscv_reloc_type (type);
+         break;
+
        case EM_ALPHA:
          rtype = elf_alpha_reloc_type (type);
          break;
@@ -1965,7 +1972,7 @@ get_solaris_dynamic_type (unsigned long type)
     case 0x7ffffffe: return "USED";
     case 0x7fffffff: return "FILTER";
 
-    default: return NULL;      
+    default: return NULL;
     }
 }
 
@@ -2010,6 +2017,7 @@ get_dynamic_type (unsigned long type)
 
     case DT_PREINIT_ARRAY: return "PREINIT_ARRAY";
     case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ";
+    case DT_SYMTAB_SHNDX: return "SYMTAB_SHNDX";
 
     case DT_CHECKSUM:  return "CHECKSUM";
     case DT_PLTPADSZ:  return "PLTPADSZ";
@@ -2325,6 +2333,7 @@ get_machine_name (unsigned e_machine)
     case EM_CR16:
     case EM_MICROBLAZE:
     case EM_MICROBLAZE_OLD:    return "Xilinx MicroBlaze";
+    case EM_RISCV:             return "RISC-V";
     case EM_RL78:              return "Renesas RL78";
     case EM_RX:                        return "Renesas RX";
     case EM_METAG:             return "Imagination Technologies Meta processor architecture";
@@ -2339,6 +2348,28 @@ get_machine_name (unsigned e_machine)
     case EM_TILEGX:            return "Tilera TILE-Gx multicore architecture family";
     case EM_CUDA:              return "NVIDIA CUDA architecture";
     case EM_XGATE:             return "Motorola XGATE embedded processor";
+    case EM_CLOUDSHIELD:       return "CloudShield architecture family";
+    case EM_COREA_1ST:         return "KIPO-KAIST Core-A 1st generation processor family";
+    case EM_COREA_2ND:         return "KIPO-KAIST Core-A 2nd generation processor family";
+    case EM_OPEN8:             return "Open8 8-bit RISC soft processor core";
+    case EM_VIDEOCORE5:                return "Broadcom VideoCore V processor";
+    case EM_56800EX:           return "Freescale 56800EX Digital Signal Controller (DSC)";
+    case EM_BA1:               return "Beyond BA1 CPU architecture";
+    case EM_BA2:               return "Beyond BA2 CPU architecture";
+    case EM_XCORE:             return "XMOS xCORE processor family";
+    case EM_MCHP_PIC:          return "Microchip 8-bit PIC(r) family";
+    case EM_KM32:              return "KM211 KM32 32-bit processor";
+    case EM_KMX32:             return "KM211 KMX32 32-bit processor";
+    case EM_KMX16:             return "KM211 KMX16 16-bit processor";
+    case EM_KMX8:              return "KM211 KMX8 8-bit processor";
+    case EM_KVARC:             return "KM211 KVARC processor";
+    case EM_CDP:               return "Paneve CDP architecture family";
+    case EM_COGE:              return "Cognitive Smart Memory Processor";
+    case EM_COOL:              return "Bluechip Systems CoolEngine";
+    case EM_NORC:              return "Nanoradio Optimized RISC";
+    case EM_CSR_KALIMBA:       return "CSR Kalimba architecture family";
+    case EM_Z80:               return "Zilog Z80";
+    case EM_AMDGPU:            return "AMD GPU architecture";
     default:
       snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
       return buff;
@@ -2381,9 +2412,6 @@ decode_ARC_machine_flags (unsigned e_flags, unsigned e_machine, char buf[])
     case E_ARC_MACH_ARC700:
       strcat (buf, ", ARC700");
       break;
-    case E_ARC_MACH_NPS400:
-      strcat (buf, ", NPS400");
-      break;
 
       /* The only times we should end up here are (a) A corrupt ELF, (b) A
          new ELF with new architecture being read by an old version of
@@ -3286,6 +3314,13 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
          decode_NDS32_machine_flags (e_flags, buf, sizeof buf);
          break;
 
+       case EM_RISCV:
+         if (e_flags & EF_RISCV_RVC)
+           strcat (buf, ", RVC");
+         if (e_flags & EF_RISCV_SOFT_FLOAT)
+           strcat (buf, ", soft-float ABI");
+         break;
+
        case EM_SH:
          switch ((e_flags & EF_SH_MACH_MASK))
            {
@@ -3536,6 +3571,8 @@ get_osabi_name (unsigned int osabi)
     case ELFOSABI_NSK:         return "HP - Non-Stop Kernel";
     case ELFOSABI_AROS:                return "AROS";
     case ELFOSABI_FENIXOS:     return "FenixOS";
+    case ELFOSABI_CLOUDABI:    return "Nuxi CloudABI";
+    case ELFOSABI_OPENVOS:     return "Stratus Technologies OpenVOS";
     default:
       if (osabi >= 64)
        switch (elf_header.e_machine)
@@ -3760,7 +3797,7 @@ get_segment_type (unsigned long p_type)
          if (result != NULL)
            return result;
 
-         sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC);
+         sprintf (buff, "LOPROC+%#lx", p_type - PT_LOPROC);
        }
       else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS))
        {
@@ -3785,7 +3822,7 @@ get_segment_type (unsigned long p_type)
          if (result != NULL)
            return result;
 
-         sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
+         sprintf (buff, "LOOS+%#lx", p_type - PT_LOOS);
        }
       else
        snprintf (buff, sizeof (buff), _("<unknown>: %lx"), p_type);
@@ -4241,10 +4278,13 @@ request_dump_bynumber (unsigned int section, dump_type type)
        error (_("Out of memory allocating dump request table.\n"));
       else
        {
-         /* Copy current flag settings.  */
-         memcpy (new_dump_sects, dump_sects, num_dump_sects * sizeof (* dump_sects));
+         if (dump_sects)
+           {
+             /* Copy current flag settings.  */
+             memcpy (new_dump_sects, dump_sects, num_dump_sects * sizeof (* dump_sects));
 
-         free (dump_sects);
+             free (dump_sects);
+           }
 
          dump_sects = new_dump_sects;
          num_dump_sects = section + 1;
@@ -4450,7 +4490,7 @@ parse_args (int argc, char ** argv)
        default:
          /* xgettext:c-format */
          error (_("Invalid option '-%c'\n"), c);
-         /* Drop through.  */
+         /* Fall through.  */
        case '?':
          usage (stderr);
        }
@@ -4730,6 +4770,7 @@ process_program_headers (FILE * file)
 {
   Elf_Internal_Phdr * segment;
   unsigned int i;
+  Elf_Internal_Phdr * previous_load = NULL;
 
   if (elf_header.e_phnum == 0)
     {
@@ -4859,15 +4900,45 @@ process_program_headers (FILE * file)
                      (segment->p_flags & PF_R ? 'R' : ' '),
                      (segment->p_flags & PF_W ? 'W' : ' '),
                      (segment->p_flags & PF_X ? 'E' : ' '));
-             print_vma (segment->p_align, HEX);
+             print_vma (segment->p_align, PREFIX_HEX);
            }
-       }
 
-      if (do_segments)
-       putc ('\n', stdout);
+         putc ('\n', stdout);
+       }
 
       switch (segment->p_type)
        {
+       case PT_LOAD:
+#if 0 /* Do not warn about out of order PT_LOAD segments.  Although officially
+        required by the ELF standard, several programs, including the Linux
+        kernel, make use of non-ordered segments.  */
+         if (previous_load
+             && previous_load->p_vaddr > segment->p_vaddr)
+           error (_("LOAD segments must be sorted in order of increasing VirtAddr\n"));
+#endif
+         if (segment->p_memsz < segment->p_filesz)
+           error (_("the segment's file size is larger than its memory size\n"));
+         previous_load = segment;
+         break;
+
+       case PT_PHDR:
+         /* PR 20815 - Verify that the program header is loaded into memory.  */
+         if (i > 0 && previous_load != NULL)
+           error (_("the PHDR segment must occur before any LOAD segment\n"));
+         if (elf_header.e_machine != EM_PARISC)
+           {
+             unsigned int j;
+
+             for (j = 1; j < elf_header.e_phnum; j++)
+               if (program_headers[j].p_vaddr <= segment->p_vaddr
+                   && (program_headers[j].p_vaddr + program_headers[j].p_memsz)
+                   >= (segment->p_vaddr + segment->p_filesz))
+                 break;
+             if (j == elf_header.e_phnum)
+               error (_("the PHDR segment is not covered by a LOAD segment\n"));
+           }
+         break;
+
        case PT_DYNAMIC:
          if (dynamic_addr)
            error (_("more than one dynamic segment\n"));
@@ -5402,7 +5473,7 @@ get_elf_section_flags (bfd_vma sh_flags)
       /* 20 */ { STRING_COMMA_LEN ("COMPRESSED") },
       /* ARM specific.  */
       /* 21 */ { STRING_COMMA_LEN ("ENTRYSECT") },
-      /* 22 */ { STRING_COMMA_LEN ("ARM_NOREAD") },
+      /* 22 */ { STRING_COMMA_LEN ("ARM_PURECODE") },
       /* 23 */ { STRING_COMMA_LEN ("COMDEF") }
     };
 
@@ -5478,7 +5549,7 @@ get_elf_section_flags (bfd_vma sh_flags)
                  switch (flag)
                    {
                    case SHF_ENTRYSECT: sindex = 21; break;
-                   case SHF_ARM_NOREAD: sindex = 22; break;
+                   case SHF_ARM_PURECODE: sindex = 22; break;
                    case SHF_COMDEF: sindex = 23; break;
                    default: break;
                    }
@@ -5537,7 +5608,7 @@ get_elf_section_flags (bfd_vma sh_flags)
                  && flag == SHF_X86_64_LARGE)
                *p = 'l';
              else if (elf_header.e_machine == EM_ARM
-                      && flag == SHF_ARM_NOREAD)
+                      && flag == SHF_ARM_PURECODE)
                  *p = 'y';
              else if (flag & SHF_MASKOS)
                {
@@ -5625,6 +5696,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
   if (is_32bit_elf)
     {
       Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) buf;
+
       chdr->ch_type = BYTE_GET (echdr->ch_type);
       chdr->ch_size = BYTE_GET (echdr->ch_size);
       chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
@@ -5633,6 +5705,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
   else
     {
       Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) buf;
+
       chdr->ch_type = BYTE_GET (echdr->ch_type);
       chdr->ch_size = BYTE_GET (echdr->ch_size);
       chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
@@ -5923,6 +5996,124 @@ process_section_headers (FILE * file)
        i < elf_header.e_shnum;
        i++, section++)
     {
+      /* Run some sanity checks on the section header.  */
+
+      /* Check the sh_link field.  */
+      switch (section->sh_type)
+       {
+       case SHT_SYMTAB_SHNDX:
+       case SHT_GROUP:
+       case SHT_HASH:
+       case SHT_GNU_HASH:
+       case SHT_GNU_versym:
+       case SHT_REL:
+       case SHT_RELA:
+         if (section->sh_link < 1
+             || section->sh_link >= elf_header.e_shnum
+             || (section_headers[section->sh_link].sh_type != SHT_SYMTAB
+                 && section_headers[section->sh_link].sh_type != SHT_DYNSYM))
+           warn (_("[%2u]: Link field (%u) should index a symtab section.\n"),
+                 i, section->sh_link);
+         break;
+
+       case SHT_DYNAMIC:
+       case SHT_SYMTAB:
+       case SHT_DYNSYM:
+       case SHT_GNU_verneed:
+       case SHT_GNU_verdef:
+       case SHT_GNU_LIBLIST:
+         if (section->sh_link < 1
+             || section->sh_link >= elf_header.e_shnum
+             || section_headers[section->sh_link].sh_type != SHT_STRTAB)
+           warn (_("[%2u]: Link field (%u) should index a string section.\n"),
+                 i, section->sh_link);
+         break;
+
+       case SHT_INIT_ARRAY:
+       case SHT_FINI_ARRAY:
+       case SHT_PREINIT_ARRAY:
+         if (section->sh_type < SHT_LOOS && section->sh_link != 0)
+           warn (_("[%2u]: Unexpected value (%u) in link field.\n"),
+                 i, section->sh_link);
+         break;
+
+       default:
+         /* FIXME: Add support for target specific section types.  */
+#if 0    /* Currently we do not check other section types as there are too
+            many special cases.  Stab sections for example have a type
+            of SHT_PROGBITS but an sh_link field that links to the .stabstr
+            section.  */
+         if (section->sh_type < SHT_LOOS && section->sh_link != 0)
+           warn (_("[%2u]: Unexpected value (%u) in link field.\n"),
+                 i, section->sh_link);
+#endif
+         break;
+       }
+
+      /* Check the sh_info field.  */
+      switch (section->sh_type)
+       {
+       case SHT_REL:
+       case SHT_RELA:
+         if (section->sh_info < 1
+             || section->sh_info >= elf_header.e_shnum
+             || (section_headers[section->sh_info].sh_type != SHT_PROGBITS
+                 && section_headers[section->sh_info].sh_type != SHT_NOBITS
+                 && section_headers[section->sh_info].sh_type != SHT_NOTE
+                 && section_headers[section->sh_info].sh_type != SHT_INIT_ARRAY
+                 /* FIXME: Are other section types valid ?  */
+                 && section_headers[section->sh_info].sh_type < SHT_LOOS))
+           {
+             if (section->sh_info == 0
+                 && (streq (SECTION_NAME (section), ".rel.dyn")
+                     || streq (SECTION_NAME (section), ".rela.dyn")))
+               /* The .rel.dyn and .rela.dyn sections have an sh_info field
+                  of zero.  No idea why.  I would have expected the index
+                  of the .plt section.  */
+                  ;
+             else
+               warn (_("[%2u]: Info field (%u) should index a relocatable section.\n"),
+                     i, section->sh_info);
+           }
+         break;
+
+       case SHT_DYNAMIC:
+       case SHT_HASH:
+       case SHT_SYMTAB_SHNDX:
+       case SHT_INIT_ARRAY:
+       case SHT_FINI_ARRAY:
+       case SHT_PREINIT_ARRAY:
+         if (section->sh_info != 0)
+           warn (_("[%2u]: Unexpected value (%u) in info field.\n"),
+                 i, section->sh_info);
+         break;
+
+       case SHT_GROUP:
+       case SHT_SYMTAB:
+       case SHT_DYNSYM:
+         /* A symbol index - we assume that it is valid.  */
+         break;
+
+       default:
+         /* FIXME: Add support for target specific section types.  */
+         if (section->sh_type == SHT_NOBITS)
+           /* NOBITS section headers with non-zero sh_info fields can be
+              created when a binary is stripped of everything but its debug
+              information.  The stripped sections have their headers
+              preserved but their types set to SHT_NOBITS.  So do not check
+              this type of section.  */
+           ;
+         else if (section->sh_flags & SHF_INFO_LINK)
+           {
+             if (section->sh_info < 1 || section->sh_info >= elf_header.e_shnum)
+               warn (_("[%2u]: Expected link to another section in info field"), i);
+           }
+         else if (section->sh_type < SHT_LOOS && section->sh_info != 0)
+           warn (_("[%2u]: Unexpected value (%u) in info field.\n"),
+                 i, section->sh_info);
+         break;
+       }
+
       printf ("  [%2u] ", i);
       if (do_section_details)
        printf ("%s\n      ", printable_section_name (section));
@@ -6089,12 +6280,15 @@ process_section_headers (FILE * file)
              /* Minimum section size is 12 bytes for 32-bit compression
                 header + 12 bytes for compressed data header.  */
              unsigned char buf[24];
+
              assert (sizeof (buf) >= sizeof (Elf64_External_Chdr));
              if (get_data (&buf, (FILE *) file, section->sh_offset, 1,
                            sizeof (buf), _("compression header")))
                {
                  Elf_Internal_Chdr chdr;
-                 get_compression_header (&chdr, buf);
+
+                 (void) get_compression_header (&chdr, buf);
+
                  if (chdr.ch_type == ELFCOMPRESS_ZLIB)
                    printf ("       ZLIB, ");
                  else
@@ -6121,7 +6315,7 @@ process_section_headers (FILE * file)
          || elf_header.e_machine == EM_K1OM)
        printf (_("l (large), "));
       else if (elf_header.e_machine == EM_ARM)
-       printf (_("y (noread), "));
+       printf (_("y (purecode), "));
       printf ("p (processor specific)\n");
     }
 
@@ -6131,19 +6325,32 @@ process_section_headers (FILE * file)
 static const char *
 get_group_flags (unsigned int flags)
 {
-  static char buff[32];
-  switch (flags)
-    {
-    case 0:
-      return "";
+  static char buff[128];
 
-    case GRP_COMDAT:
-      return "COMDAT ";
+  if (flags == 0)
+    return "";
+  else if (flags == GRP_COMDAT)
+    return "COMDAT ";
 
-   default:
-      snprintf (buff, sizeof (buff), _("[<unknown>: 0x%x] "), flags);
-      break;
+  snprintf (buff, 14, _("[0x%x: "), flags);
+
+  flags &= ~ GRP_COMDAT;
+  if (flags & GRP_MASKOS)
+    {
+      strcat (buff, "<OS specific>");
+      flags &= ~ GRP_MASKOS;
+    }
+
+  if (flags & GRP_MASKPROC)
+    {
+      strcat (buff, "<PROC specific>");
+      flags &= ~ GRP_MASKPROC;
     }
+
+  if (flags)
+    strcat (buff, "<unknown>");
+
+  strcat (buff, "]");
   return buff;
 }
 
@@ -8714,7 +8921,7 @@ dynamic_section_mips_val (Elf_Internal_Dyn * entry)
 
     case DT_MIPS_TIME_STAMP:
       {
-       char timebuf[20];
+       char timebuf[128];
        struct tm * tmp;
        time_t atime = entry->d_un.d_val;
 
@@ -8743,7 +8950,7 @@ dynamic_section_mips_val (Elf_Internal_Dyn * entry)
     case DT_MIPS_DELTA_SYM_NO:
     case DT_MIPS_DELTA_CLASSSYM_NO:
     case DT_MIPS_COMPACT_SIZE:
-      print_vma (entry->d_un.d_ptr, DEC);
+      print_vma (entry->d_un.d_val, DEC);
       break;
 
     default:
@@ -9558,6 +9765,7 @@ process_dynamic_section (FILE * file)
        case DT_SYMENT  :
        case DT_RELENT  :
          dynamic_info[entry->d_tag] = entry->d_un.d_val;
+         /* Fall through.  */
        case DT_PLTPADSZ:
        case DT_MOVEENT :
        case DT_MOVESZ  :
@@ -9762,7 +9970,7 @@ process_version_sections (FILE * file)
                int j;
                int isum;
 
-               /* Check for very large indicies.  */
+               /* Check for very large indices.  */
                if (idx > (size_t) (endbuf - (char *) edefs))
                  break;
 
@@ -10611,12 +10819,14 @@ print_dynamic_symbol (bfd_vma si, unsigned long hn)
 }
 
 static const char *
-get_symbol_version_string (FILE *file, int is_dynsym,
-                          const char *strtab,
-                          unsigned long int strtab_size,
-                          unsigned int si, Elf_Internal_Sym *psym,
-                          enum versioned_symbol_info *sym_info,
-                          unsigned short *vna_other)
+get_symbol_version_string (FILE *                       file,
+                          bfd_boolean                  is_dynsym,
+                          const char *                 strtab,
+                          unsigned long int            strtab_size,
+                          unsigned int                 si,
+                          Elf_Internal_Sym *           psym,
+                          enum versioned_symbol_info * sym_info,
+                          unsigned short *             vna_other)
 {
   unsigned char data[2];
   unsigned short vers_data;
@@ -11112,6 +11322,16 @@ process_symbol_table (FILE * file)
                }
 
              putchar ('\n');
+
+             if (ELF_ST_BIND (psym->st_info) == STB_LOCAL
+                 && si >= section->sh_info
+                 /* Irix 5 and 6 MIPS binaries are known to ignore this requirement.  */
+                 && elf_header.e_machine != EM_MIPS
+                 /* Solaris binaries have been found to violate this requirement as
+                    well.  Not sure if this is a bug or an ABI requirement.  */
+                 && elf_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
+               warn (_("local symbol %u found at index >= %s's sh_info value of %u\n"),
+                     si, printable_section_name (section), section->sh_info);
            }
 
          free (symtab);
@@ -11363,6 +11583,7 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
          case 10: /* R_MSP430_SYM_DIFF */
            if (uses_msp430x_relocs ())
              break;
+           /* Fall through.  */
          case 21: /* R_MSP430X_SYM_DIFF */
            saved_sym = symtab + get_reloc_symindex (reloc->r_info);
            return TRUE;
@@ -11613,6 +11834,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_PPC64_ADDR32.  */
     case EM_PPC:
       return reloc_type == 1; /* R_PPC_ADDR32.  */
+    case EM_RISCV:
+      return reloc_type == 1; /* R_RISCV_32.  */
     case EM_RL78:
       return reloc_type == 1; /* R_RL78_DIR32.  */
     case EM_RX:
@@ -11766,6 +11989,8 @@ is_64bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 80; /* R_PARISC_DIR64.  */
     case EM_PPC64:
       return reloc_type == 38; /* R_PPC64_ADDR64.  */
+    case EM_RISCV:
+      return reloc_type == 2; /* R_RISCV_64.  */
     case EM_SPARC32PLUS:
     case EM_SPARCV9:
     case EM_SPARC:
@@ -11833,6 +12058,8 @@ is_24bit_abs_reloc (unsigned int reloc_type)
     case EM_CYGNUS_MN10200:
     case EM_MN10200:
       return reloc_type == 4; /* R_MN10200_24.  */
+    case EM_FT32:
+      return reloc_type == 5; /* R_FT32_20.  */
     default:
       return FALSE;
     }
@@ -11878,6 +12105,7 @@ is_16bit_abs_reloc (unsigned int reloc_type)
     case EM_MSP430:
       if (uses_msp430x_relocs ())
        return reloc_type == 2; /* R_MSP430_ABS16.  */
+      /* Fall through.  */
     case EM_MSP430_OLD:
       return reloc_type == 5; /* R_MSP430_16_BYTE.  */
     case EM_NDS32:
@@ -11934,6 +12162,7 @@ is_none_reloc (unsigned int reloc_type)
     case EM_PARISC:  /* R_PARISC_NONE.  */
     case EM_PPC64:   /* R_PPC64_NONE.  */
     case EM_PPC:     /* R_PPC_NONE.  */
+    case EM_RISCV:   /* R_RISCV_NONE.  */
     case EM_S390:    /* R_390_NONE.  */
     case EM_S390_OLD:
     case EM_SH:      /* R_SH_NONE.  */
@@ -12006,7 +12235,7 @@ apply_relocations (void *                     file,
                   const Elf_Internal_Shdr *  section,
                   unsigned char *            start,
                   bfd_size_type              size,
-                  void **                     relocs_return,
+                  void **                    relocs_return,
                   unsigned long *            num_relocs_return)
 {
   Elf_Internal_Shdr * relsec;
@@ -12062,6 +12291,9 @@ apply_relocations (void *                     file,
        is_rela = FALSE;
 
       symsec = section_headers + relsec->sh_link;
+      if (symsec->sh_type != SHT_SYMTAB
+         && symsec->sh_type != SHT_DYNSYM)
+       return;
       symtab = GET_ELF_SYMBOLS ((FILE *) file, symsec, & num_syms);
 
       for (rp = relocs; rp < relocs + num_relocs; ++rp)
@@ -12574,8 +12806,19 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
       if ((sec->sh_flags & SHF_COMPRESSED) != 0)
        {
          Elf_Internal_Chdr chdr;
-         unsigned int compression_header_size
-           = get_compression_header (&chdr, start);
+         unsigned int compression_header_size;
+
+         if (size < (is_32bit_elf
+                     ? sizeof (Elf32_External_Chdr)
+                     : sizeof (Elf64_External_Chdr)))
+           {
+             warn (_("compressed section %s is too small to contain a compression header"),
+                   section->name);
+             return 0;
+           }
+
+         compression_header_size = get_compression_header (&chdr, start);
+
          if (chdr.ch_type != ELFCOMPRESS_ZLIB)
            {
              warn (_("section '%s' has unsupported compress type: %d\n"),
@@ -13238,47 +13481,77 @@ display_power_gnu_attribute (unsigned char * p,
                             const unsigned char * const end)
 {
   unsigned int len;
-  int val;
+  unsigned int val;
 
   if (tag == Tag_GNU_Power_ABI_FP)
     {
       val = read_uleb128 (p, &len, end);
       p += len;
       printf ("  Tag_GNU_Power_ABI_FP: ");
+      if (len == 0)
+       {
+         printf (_("<corrupt>\n"));
+         return p;
+       }
 
-      switch (val)
+      if (val > 15)
+       printf ("(%#x), ", val);
+
+      switch (val & 3)
        {
        case 0:
-         printf (_("Hard or soft float\n"));
+         printf (_("unspecified hard/soft float, "));
          break;
        case 1:
-         printf (_("Hard float\n"));
+         printf (_("hard float, "));
          break;
        case 2:
-         printf (_("Soft float\n"));
+         printf (_("soft float, "));
          break;
        case 3:
-         printf (_("Single-precision hard float\n"));
+         printf (_("single-precision hard float, "));
          break;
-       default:
-         printf ("??? (%d)\n", val);
+       }
+
+      switch (val & 0xC)
+       {
+       case 0:
+         printf (_("unspecified long double\n"));
+         break;
+       case 4:
+         printf (_("128-bit IBM long double\n"));
+         break;
+       case 8:
+         printf (_("64-bit long double\n"));
+         break;
+       case 12:
+         printf (_("128-bit IEEE long double\n"));
          break;
        }
       return p;
-   }
+    }
 
   if (tag == Tag_GNU_Power_ABI_Vector)
     {
       val = read_uleb128 (p, &len, end);
       p += len;
       printf ("  Tag_GNU_Power_ABI_Vector: ");
-      switch (val)
+      if (len == 0)
+       {
+         printf (_("<corrupt>\n"));
+         return p;
+       }
+
+      if (val > 3)
+       printf ("(%#x), ", val);
+
+      switch (val & 3)
        {
        case 0:
-         printf (_("Any\n"));
+         printf (_("unspecified\n"));
          break;
        case 1:
-         printf (_("Generic\n"));
+         printf (_("generic\n"));
          break;
        case 2:
          printf ("AltiVec\n");
@@ -13286,39 +13559,39 @@ display_power_gnu_attribute (unsigned char * p,
        case 3:
          printf ("SPE\n");
          break;
-       default:
-         printf ("??? (%d)\n", val);
-         break;
        }
       return p;
-   }
+    }
 
   if (tag == Tag_GNU_Power_ABI_Struct_Return)
     {
-      if (p == end)
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_GNU_Power_ABI_Struct_Return: ");
+      if (len == 0)
        {
-         warn (_("corrupt Tag_GNU_Power_ABI_Struct_Return\n"));
+         printf (_("<corrupt>\n"));
          return p;
        }
 
-      val = read_uleb128 (p, &len, end);
-      p += len;
-      printf ("  Tag_GNU_Power_ABI_Struct_Return: ");
-      switch (val)
-       {
-       case 0:
-         printf (_("Any\n"));
-         break;
-       case 1:
-         printf ("r3/r4\n");
-         break;
-       case 2:
-         printf (_("Memory\n"));
-         break;
-       default:
-         printf ("??? (%d)\n", val);
-         break;
-       }
+      if (val > 2)
+       printf ("(%#x), ", val);
+
+      switch (val & 3)
+       {
+       case 0:
+         printf (_("unspecified\n"));
+         break;
+       case 1:
+         printf ("r3/r4\n");
+         break;
+       case 2:
+         printf (_("memory\n"));
+         break;
+       case 3:
+         printf ("???\n");
+         break;
+       }
       return p;
     }
 
@@ -14067,6 +14340,7 @@ process_attributes (FILE * file,
                      goto do_numlist;
                    case 3:
                      printf (_("Symbol Attributes:"));
+                     /* Fall through.  */
                    do_numlist:
                      for (;;)
                        {
@@ -14490,7 +14764,7 @@ process_mips_specific (FILE * file)
            {
              Elf32_Lib liblist;
              time_t atime;
-             char timebuf[20];
+             char timebuf[128];
              struct tm * tmp;
 
              liblist.l_name = BYTE_GET (elib[cnt].l_name);
@@ -14577,7 +14851,7 @@ process_mips_specific (FILE * file)
               cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (* iopt));
          if (iopt == NULL)
            {
-             error (_("Out of memory allocatinf space for MIPS options\n"));
+             error (_("Out of memory allocating space for MIPS options\n"));
              return 0;
            }
 
@@ -15144,7 +15418,7 @@ process_gnu_liblist (FILE * file)
            {
              Elf32_Lib liblist;
              time_t atime;
-             char timebuf[20];
+             char timebuf[128];
              struct tm * tmp;
 
              liblist.l_name = BYTE_GET (elib[cnt].l_name);
@@ -15361,8 +15635,7 @@ print_core_note (Elf_Internal_Note *pnote)
 static const char *
 get_gnu_elf_note_type (unsigned e_type)
 {
-  static char buff[64];
-
+  /* NB/ Keep this switch statement in sync with print_gnu_note ().  */
   switch (e_type)
     {
     case NT_GNU_ABI_TAG:
@@ -15374,16 +15647,19 @@ get_gnu_elf_note_type (unsigned e_type)
     case NT_GNU_GOLD_VERSION:
       return _("NT_GNU_GOLD_VERSION (gold version)");
     default:
-      break;
-    }
+      {
+       static char buff[64];
 
-  snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
-  return buff;
+       snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+       return buff;
+      }
+    }
 }
 
 static int
 print_gnu_note (Elf_Internal_Note *pnote)
 {
+  /* NB/ Keep this switch statement in sync with get_gnu_elf_note_type ().  */
   switch (pnote->type)
     {
     case NT_GNU_BUILD_ID:
@@ -15457,6 +15733,42 @@ print_gnu_note (Elf_Internal_Note *pnote)
        printf ("\n");
       }
       break;
+
+    case NT_GNU_HWCAP:
+      {
+       unsigned long num_entries, mask;
+
+       /* Hardware capabilities information.  Word 0 is the number of entries.
+          Word 1 is a bitmask of enabled entries.  The rest of the descriptor
+          is a series of entries, where each entry is a single byte followed
+          by a nul terminated string.  The byte gives the bit number to test
+          if enabled in the bitmask.  */
+       printf (_("      Hardware Capabilities: "));
+       if (pnote->descsz < 8)
+         {
+           printf (_("<corrupt GNU_HWCAP>\n"));
+           break;
+         }
+       num_entries = byte_get ((unsigned char *) pnote->descdata, 4);
+       mask = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       printf (_("num entries: %ld, enabled mask: %lx\n"), num_entries, mask);
+       /* FIXME: Add code to display the entries... */
+      }
+      break;
+
+    default:
+      /* Handle unrecognised types.  An error message should have already been
+        created by get_gnu_elf_note_type(), so all that we need to do is to
+        display the data.  */
+      {
+       unsigned long i;
+
+       printf (_("    Description data: "));
+       for (i = 0; i < pnote->descsz; ++i)
+         printf ("%02x ", pnote->descdata[i] & 0xff);
+       printf ("\n");
+      }
+      break;
     }
 
   return 1;
@@ -15541,7 +15853,7 @@ print_v850_note (Elf_Internal_Note * pnote)
   return 0;
 }
 
-static int 
+static int
 process_netbsd_elf_note (Elf_Internal_Note * pnote)
 {
   unsigned int version;
@@ -15554,11 +15866,11 @@ process_netbsd_elf_note (Elf_Internal_Note * pnote)
         printf ("  NetBSD\t\t0x%08lx\tIDENT %u (%u.%u%s%c)\n", pnote->descsz,
                version, version / 100000000, (version / 1000000) % 100,
                (version / 10000) % 100 > 26 ? "Z" : "",
-               'A' + (version / 10000) % 26); 
+               'A' + (version / 10000) % 26);
       else
        printf ("  NetBSD\t\t0x%08lx\tIDENT %u (%u.%u.%u)\n", pnote->descsz,
                version, version / 100000000, (version / 1000000) % 100,
-               (version / 100) % 100); 
+               (version / 100) % 100);
       return 1;
 
     case NT_NETBSD_MARCH:
@@ -15839,7 +16151,9 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
 
    If the value of namesz is zero, there is no name present.  */
 static int
-process_note (Elf_Internal_Note * pnote)
+process_note (Elf_Internal_Note * pnote,
+             FILE * file ATTRIBUTE_UNUSED,
+             Elf_Internal_Shdr * section ATTRIBUTE_UNUSED)
 {
   const char * name = pnote->namesz ? pnote->namedata : "(NONE)";
   const char * nt;
@@ -15884,7 +16198,9 @@ process_note (Elf_Internal_Note * pnote)
        note type strings.  */
     nt = get_note_type (pnote->type);
 
-  printf ("  %-20s 0x%08lx\t%s\n", name, pnote->descsz, nt);
+  printf ("  ");
+  print_symbol (-20, name);
+  printf (" 0x%08lx\t%s\n", pnote->descsz, nt);
 
   if (const_strneq (pnote->namedata, "IPF/VMS"))
     return print_ia64_vms_note (pnote);
@@ -15894,13 +16210,25 @@ process_note (Elf_Internal_Note * pnote)
     return print_stapsdt_note (pnote);
   else if (const_strneq (pnote->namedata, "CORE"))
     return print_core_note (pnote);
-  else
-    return 1;
-}
 
+  else if (pnote->descsz)
+    {
+      unsigned long i;
+
+      printf (_("   description data: "));
+      for (i = 0; i < pnote->descsz; i++)
+       printf ("%02x ", pnote->descdata[i]);
+      printf ("\n");
+    }
+
+  return 1;
+}
 
 static int
-process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
+process_notes_at (FILE *              file,
+                 Elf_Internal_Shdr * section,
+                 bfd_vma             offset,
+                 bfd_vma             length)
 {
   Elf_External_Note * pnotes;
   Elf_External_Note * external;
@@ -15910,15 +16238,26 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
   if (length <= 0)
     return 0;
 
-  pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
-                                          _("notes"));
+  if (section)
+    {
+      pnotes = (Elf_External_Note *) get_section_contents (section, file);
+      if (pnotes)
+       apply_relocations (file, section, (unsigned char *) pnotes, length, NULL, NULL);
+    }
+  else
+    pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
+                                            _("notes"));
   if (pnotes == NULL)
     return 0;
 
   external = pnotes;
 
-  printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"),
-         (unsigned long) offset, (unsigned long) length);
+  if (section)
+    printf (_("\nDisplaying notes found in: %s\n"), printable_section_name (section));
+  else
+    printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"),
+           (unsigned long) offset, (unsigned long) length);
+
   printf (_("  %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
 
   end = (char *) pnotes + length;
@@ -16018,7 +16357,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
          inote.namedata = temp;
        }
 
-      res &= process_note (& inote);
+      res &= process_note (& inote, file, section);
 
       if (temp != NULL)
        {
@@ -16047,9 +16386,9 @@ process_corefile_note_segments (FILE * file)
        i++, segment++)
     {
       if (segment->p_type == PT_NOTE)
-       res &= process_corefile_note_segment (file,
-                                             (bfd_vma) segment->p_offset,
-                                             (bfd_vma) segment->p_filesz);
+       res &= process_notes_at (file, NULL,
+                                (bfd_vma) segment->p_offset,
+                                (bfd_vma) segment->p_filesz);
     }
 
   return res;
@@ -16150,9 +16489,9 @@ process_note_sections (FILE * file)
     {
       if (section->sh_type == SHT_NOTE)
        {
-         res &= process_corefile_note_segment (file,
-                                               (bfd_vma) section->sh_offset,
-                                               (bfd_vma) section->sh_size);
+         res &= process_notes_at (file, section,
+                                  (bfd_vma) section->sh_offset,
+                                  (bfd_vma) section->sh_size);
          n++;
        }
 
@@ -16211,6 +16550,7 @@ process_arch_specific (FILE * file)
       return process_nds32_specific (file);
       break;
     case EM_PPC:
+    case EM_PPC64:
       return process_power_specific (file);
       break;
     case EM_S390:
@@ -16243,8 +16583,8 @@ get_file_header (FILE * file)
   /* Determine how to read the rest of the header.  */
   switch (elf_header.e_ident[EI_DATA])
     {
-    default: /* fall through */
-    case ELFDATANONE: /* fall through */
+    default:
+    case ELFDATANONE:
     case ELFDATA2LSB:
       byte_get = byte_get_little_endian;
       byte_put = byte_put_little_endian;
This page took 0.042876 seconds and 4 git commands to generate.