* i387-tdep.c (i387_fill_fsave, i387_fill_fxsave): Remove.
[deliverable/binutils-gdb.git] / binutils / readelf.c
index b1f3fc63a581071c3b4615a9f07e6be010c79ae2..14dbb52f6730206265ea9e8ceca43c5a7e336200 100644 (file)
@@ -1,5 +1,5 @@
 /* readelf.c -- display contents of an ELF format file
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    Originally developed by Eric Youngdale <eric@andante.jic.com>
   ELF file than is provided by objdump.  In particular it can display DWARF
   debugging information which (at the moment) objdump cannot.  */
 \f
+#include "sysdep.h"
 #include <assert.h>
-#include <sys/types.h>
 #include <sys/stat.h>
-#include <stdio.h>
 #include <time.h>
 
+/* for PATH_MAX */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef PATH_MAX
+/* for MAXPATHLEN */
+# ifdef HAVE_SYS_PARAM_H
+#  include <sys/param.h>
+# endif
+# ifndef PATH_MAX
+#  ifdef MAXPATHLEN
+#   define PATH_MAX MAXPATHLEN
+#  else
+#   define PATH_MAX 1024
+#  endif
+# endif
+#endif
+
 #if __GNUC__ >= 2
 /* Define BFD64 here, even if our default architecture is 32 bit ELF
    as this will allow us to read in and parse 64bit and 32bit ELF files.
 #define BFD64
 #endif
 
+#include "bfd.h"
+#include "bucomm.h"
 #include "dwarf.h"
 
 #include "elf/common.h"
 #include "elf/external.h"
 #include "elf/internal.h"
 
+
+/* Included here, before RELOC_MACROS_GEN_FUNC is defined, so that
+   we can obtain the H8 reloc numbers.  We need these for the
+   get_reloc_size() function.  We include h8.h again after defining
+   RELOC_MACROS_GEN_FUNC so that we get the naming function as well.  */
+
+#include "elf/h8.h"
+#undef _ELF_H8_H
+
+/* Undo the effects of #including reloc-macros.h.  */
+
+#undef START_RELOC_NUMBERS
+#undef RELOC_NUMBER
+#undef FAKE_RELOC
+#undef EMPTY_RELOC
+#undef END_RELOC_NUMBERS
+#undef _RELOC_MACROS_H
+
 /* The following headers use the elf/reloc-macros.h file to
    automatically generate relocation recognition functions
    such as elf_mips_reloc_type()  */
 #include "elf/m68k.h"
 #include "elf/m68hc11.h"
 #include "elf/mcore.h"
+#include "elf/mep.h"
 #include "elf/mips.h"
 #include "elf/mmix.h"
 #include "elf/mn10200.h"
 #include "elf/score.h"
 #include "elf/sh.h"
 #include "elf/sparc.h"
+#include "elf/spu.h"
 #include "elf/v850.h"
 #include "elf/vax.h"
 #include "elf/x86-64.h"
 
 #include "aout/ar.h"
 
-#include "bucomm.h"
 #include "getopt.h"
 #include "libiberty.h"
 
@@ -134,7 +173,7 @@ static Elf_Internal_Sym *dynamic_symbols;
 static Elf_Internal_Syminfo *dynamic_syminfo;
 static unsigned long dynamic_syminfo_offset;
 static unsigned int dynamic_syminfo_nent;
-static char program_interpreter[64];
+static char program_interpreter[PATH_MAX];
 static bfd_vma dynamic_info[DT_JMPREL + 1];
 static bfd_vma dynamic_info_DT_GNU_HASH;
 static bfd_vma version_info[16];
@@ -555,89 +594,91 @@ guess_is_rela (unsigned long e_machine)
   switch (e_machine)
     {
       /* Targets that use REL relocations.  */
-    case EM_ARM:
     case EM_386:
     case EM_486:
     case EM_960:
-    case EM_DLX:
-    case EM_OPENRISC:
-    case EM_OR32:
-    case EM_CYGNUS_M32R:
+    case EM_ARM:
     case EM_D10V:
     case EM_CYGNUS_D10V:
+    case EM_DLX:
     case EM_MIPS:
     case EM_MIPS_RS3_LE:
+    case EM_CYGNUS_M32R:
+    case EM_OPENRISC:
+    case EM_OR32:
     case EM_SCORE:
       return FALSE;
 
       /* Targets that use RELA relocations.  */
     case EM_68K:
-    case EM_H8_300:
-    case EM_H8_300H:
-    case EM_H8S:
-    case EM_SPARC32PLUS:
-    case EM_SPARCV9:
-    case EM_SPARC:
-    case EM_PPC:
-    case EM_PPC64:
-    case EM_V850:
-    case EM_CYGNUS_V850:
+    case EM_860:
+    case EM_ALPHA:
+    case EM_ALTERA_NIOS2:
+    case EM_AVR:
+    case EM_AVR_OLD:
+    case EM_BLACKFIN:
+    case EM_CRIS:
+    case EM_CRX:
     case EM_D30V:
     case EM_CYGNUS_D30V:
-    case EM_MN10200:
-    case EM_CYGNUS_MN10200:
-    case EM_MN10300:
-    case EM_CYGNUS_MN10300:
     case EM_FR30:
     case EM_CYGNUS_FR30:
     case EM_CYGNUS_FRV:
-    case EM_SH:
-    case EM_ALPHA:
-    case EM_MCORE:
+    case EM_H8S:
+    case EM_H8_300:
+    case EM_H8_300H:
     case EM_IA_64:
-    case EM_AVR:
-    case EM_AVR_OLD:
-    case EM_CRIS:
-    case EM_860:
-    case EM_X86_64:
-    case EM_S390:
-    case EM_S390_OLD:
-    case EM_MMIX:
-    case EM_MSP430:
-    case EM_MSP430_OLD:
-    case EM_XSTORMY16:
-    case EM_CRX:
-    case EM_VAX:
     case EM_IP2K:
     case EM_IP2K_OLD:
     case EM_IQ2000:
-    case EM_XTENSA:
-    case EM_XTENSA_OLD:
-    case EM_M32R:
     case EM_M32C:
+    case EM_M32R:
+    case EM_MCORE:
+    case EM_CYGNUS_MEP:
+    case EM_MMIX:
+    case EM_MN10200:
+    case EM_CYGNUS_MN10200:
+    case EM_MN10300:
+    case EM_CYGNUS_MN10300:
+    case EM_MSP430:
+    case EM_MSP430_OLD:
     case EM_MT:
-    case EM_BLACKFIN:
     case EM_NIOS32:
-    case EM_ALTERA_NIOS2:
+    case EM_PPC64:
+    case EM_PPC:
+    case EM_S390:
+    case EM_S390_OLD:
+    case EM_SH:
+    case EM_SPARC:
+    case EM_SPARC32PLUS:
+    case EM_SPARCV9:
+    case EM_SPU:
+    case EM_V850:
+    case EM_CYGNUS_V850:
+    case EM_VAX:
+    case EM_X86_64:
+    case EM_XSTORMY16:
+    case EM_XTENSA:
+    case EM_XTENSA_OLD:
       return TRUE;
 
+    case EM_68HC05:
+    case EM_68HC08:
+    case EM_68HC11:
+    case EM_68HC16:
+    case EM_FX66:
+    case EM_ME16:
     case EM_MMA:
-    case EM_PCP:
     case EM_NCPU:
     case EM_NDR1:
-    case EM_STARCORE:
-    case EM_ME16:
+    case EM_PCP:
     case EM_ST100:
-    case EM_TINYJ:
-    case EM_FX66:
-    case EM_ST9PLUS:
+    case EM_ST19:
     case EM_ST7:
-    case EM_68HC16:
-    case EM_68HC11:
-    case EM_68HC08:
-    case EM_68HC05:
+    case EM_ST9PLUS:
+    case EM_STARCORE:
     case EM_SVX:
-    case EM_ST19:
+    case EM_TINYJ:
     default:
       warn (_("Don't know about relocations on this machine architecture\n"));
       return FALSE;
@@ -670,7 +711,7 @@ slurp_rela_relocs (FILE *file,
       if (relas == NULL)
        {
          free (erelas);
-         error (_("out of memory parsing relocs"));
+         error (_("out of memory parsing relocs\n"));
          return 0;
        }
 
@@ -698,7 +739,7 @@ slurp_rela_relocs (FILE *file,
       if (relas == NULL)
        {
          free (erelas);
-         error (_("out of memory parsing relocs"));
+         error (_("out of memory parsing relocs\n"));
          return 0;
        }
 
@@ -742,7 +783,7 @@ slurp_rel_relocs (FILE *file,
       if (rels == NULL)
        {
          free (erels);
-         error (_("out of memory parsing relocs"));
+         error (_("out of memory parsing relocs\n"));
          return 0;
        }
 
@@ -770,7 +811,7 @@ slurp_rel_relocs (FILE *file,
       if (rels == NULL)
        {
          free (erels);
-         error (_("out of memory parsing relocs"));
+         error (_("out of memory parsing relocs\n"));
          return 0;
        }
 
@@ -972,6 +1013,10 @@ dump_relocations (FILE *file,
          rtype = elf_sparc_reloc_type (type);
          break;
 
+       case EM_SPU:
+         rtype = elf_spu_reloc_type (type);
+         break;
+
        case EM_V850:
        case EM_CYGNUS_V850:
          rtype = v850_reloc_type (type);
@@ -1142,6 +1187,10 @@ dump_relocations (FILE *file,
        case EM_BLACKFIN:
          rtype = elf_bfin_reloc_type (type);
          break;
+
+       case EM_CYGNUS_MEP:
+         rtype = elf_mep_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1638,6 +1687,7 @@ get_machine_name (unsigned e_machine)
     case EM_NONE:              return _("None");
     case EM_M32:               return "WE32100";
     case EM_SPARC:             return "Sparc";
+    case EM_SPU:               return "SPU";
     case EM_386:               return "Intel 80386";
     case EM_68K:               return "MC68000";
     case EM_88K:               return "MC88000";
@@ -1736,8 +1786,9 @@ get_machine_name (unsigned e_machine)
     case EM_NIOS32:            return "Altera Nios";
     case EM_ALTERA_NIOS2:      return "Altera Nios II";
     case EM_XC16X:             return "Infineon Technologies xc16x";
+    case EM_CYGNUS_MEP:         return "Toshiba MeP Media Engine";
     default:
-      snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_machine);
+      snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
       return buff;
     }
 }
@@ -1986,33 +2037,35 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
          break;
 
        case EM_68K:
-         if (e_flags & EF_M68K_CPU32)
-           strcat (buf, ", cpu32");
-         if (e_flags & EF_M68K_M68000)
+         if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_M68000)
            strcat (buf, ", m68000");
-         if (e_flags & EF_M68K_ISA_MASK)
+         else if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32)
+           strcat (buf, ", cpu32");
+         else if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO)
+           strcat (buf, ", fido_a");
+         else
            {
              char const *isa = _("unknown");
              char const *mac = _("unknown mac");
              char const *additional = NULL;
 
-             switch (e_flags & EF_M68K_ISA_MASK)
+             switch (e_flags & EF_M68K_CF_ISA_MASK)
                {
-               case EF_M68K_ISA_A_NODIV:
+               case EF_M68K_CF_ISA_A_NODIV:
                  isa = "A";
                  additional = ", nodiv";
                  break;
-               case EF_M68K_ISA_A:
+               case EF_M68K_CF_ISA_A:
                  isa = "A";
                  break;
-               case EF_M68K_ISA_A_PLUS:
+               case EF_M68K_CF_ISA_A_PLUS:
                  isa = "A+";
                  break;
-               case EF_M68K_ISA_B_NOUSP:
+               case EF_M68K_CF_ISA_B_NOUSP:
                  isa = "B";
                  additional = ", nousp";
                  break;
-               case EF_M68K_ISA_B:
+               case EF_M68K_CF_ISA_B:
                  isa = "B";
                  break;
                }
@@ -2020,17 +2073,17 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
              strcat (buf, isa);
              if (additional)
                strcat (buf, additional);
-             if (e_flags & EF_M68K_FLOAT)
+             if (e_flags & EF_M68K_CF_FLOAT)
                strcat (buf, ", float");
-             switch (e_flags & EF_M68K_MAC_MASK)
+             switch (e_flags & EF_M68K_CF_MAC_MASK)
                {
                case 0:
                  mac = NULL;
                  break;
-               case EF_M68K_MAC:
+               case EF_M68K_CF_MAC:
                  mac = "mac";
                  break;
-               case EF_M68K_EMAC:
+               case EF_M68K_CF_EMAC:
                  mac = "emac";
                  break;
                }
@@ -2701,11 +2754,11 @@ static struct option options[] =
 };
 
 static void
-usage (void)
+usage (FILE *stream)
 {
-  fprintf (stdout, _("Usage: readelf <option(s)> elf-file(s)\n"));
-  fprintf (stdout, _(" Display information about the contents of ELF format files\n"));
-  fprintf (stdout, _(" Options are:\n\
+  fprintf (stream, _("Usage: readelf <option(s)> elf-file(s)\n"));
+  fprintf (stream, _(" Display information about the contents of ELF format files\n"));
+  fprintf (stream, _(" Options are:\n\
   -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I\n\
   -h --file-header       Display the ELF file header\n\
   -l --program-headers   Display the program headers\n\
@@ -2729,19 +2782,21 @@ usage (void)
   --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
-  fprintf (stdout, _("\
+  fprintf (stream, _("\
   -i --instruction-dump=<number>\n\
                          Disassemble the contents of section <number>\n"));
 #endif
-  fprintf (stdout, _("\
+  fprintf (stream, _("\
   -I --histogram         Display histogram of bucket list lengths\n\
   -W --wide              Allow output width to exceed 80 characters\n\
   @<file>                Read options from <file>\n\
   -H --help              Display this information\n\
   -v --version           Display the version number of readelf\n"));
-  fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO);
+  
+  if (REPORT_BUGS_TO[0] && stream == stdout)
+    fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO);
 
-  exit (0);
+  exit (stream == stdout ? 0 : 1);
 }
 
 /* Record the fact that the user wants the contents of section number
@@ -2759,7 +2814,7 @@ request_dump (unsigned int section, int type)
       new_dump_sects = calloc (section + 1, 1);
 
       if (new_dump_sects == NULL)
-       error (_("Out of memory allocating dump request table."));
+       error (_("Out of memory allocating dump request table.\n"));
       else
        {
          /* Copy current flag settings.  */
@@ -2787,11 +2842,11 @@ request_dump_byname (const char *section, int type)
 
   new_request = malloc (sizeof (struct dump_list_entry));
   if (!new_request)
-    error (_("Out of memory allocating dump request table."));
+    error (_("Out of memory allocating dump request table.\n"));
 
   new_request->name = strdup (section);
   if (!new_request->name)
-    error (_("Out of memory allocating dump request table."));
+    error (_("Out of memory allocating dump request table.\n"));
 
   new_request->type = type;
 
@@ -2805,7 +2860,7 @@ parse_args (int argc, char **argv)
   int c;
 
   if (argc < 2)
-    usage ();
+    usage (stderr);
 
   while ((c = getopt_long
          (argc, argv, "ersuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
@@ -2819,7 +2874,7 @@ parse_args (int argc, char **argv)
          /* Long options.  */
          break;
        case 'H':
-         usage ();
+         usage (stdout);
          break;
 
        case 'a':
@@ -3060,7 +3115,7 @@ parse_args (int argc, char **argv)
          error (_("Invalid option '-%c'\n"), c);
          /* Drop through.  */
        case '?':
-         usage ();
+         usage (stderr);
        }
     }
 
@@ -3068,11 +3123,11 @@ parse_args (int argc, char **argv)
       && !do_segments && !do_header && !do_dump && !do_version
       && !do_histogram && !do_debugging && !do_arch && !do_notes
       && !do_section_groups)
-    usage ();
+    usage (stderr);
   else if (argc < 3)
     {
       warn (_("Nothing to do.\n"));
-      usage ();
+      usage (stderr);
     }
 }
 
@@ -3457,7 +3512,7 @@ process_program_headers (FILE *file)
              sec = find_section (".dynamic");
              if (sec == NULL || sec->sh_size == 0)
                {
-                 error (_("no .dynamic section in the dynamic segment"));
+                 error (_("no .dynamic section in the dynamic segment\n"));
                  break;
                }
 
@@ -3466,9 +3521,9 @@ process_program_headers (FILE *file)
 
              if (dynamic_addr < segment->p_offset
                  || dynamic_addr > segment->p_offset + segment->p_filesz)
-               warn (_("the .dynamic section is not contained within the dynamic segment"));
+               warn (_("the .dynamic section is not contained within the dynamic segment\n"));
              else if (dynamic_addr > segment->p_offset)
-               warn (_("the .dynamic section is not the first section in the dynamic segment."));
+               warn (_("the .dynamic section is not the first section in the dynamic segment.\n"));
            }
          else
            {
@@ -3485,8 +3540,15 @@ process_program_headers (FILE *file)
            error (_("Unable to find program interpreter name\n"));
          else
            {
+             char fmt [32];
+             int ret = snprintf (fmt, sizeof (fmt), "%%%ds", PATH_MAX);
+
+             if (ret >= (int) sizeof (fmt) || ret < 0)
+               error (_("Internal error: failed to create format string to display program interpreter\n"));
+
              program_interpreter[0] = 0;
-             fscanf (file, "%63s", program_interpreter);
+             if (fscanf (file, fmt, program_interpreter) <= 0)
+               error (_("Unable to read program interpreter name\n"));
 
              if (do_segments)
                printf (_("\n      [Requesting program interpreter: %s]"),
@@ -5803,7 +5865,7 @@ process_dynamic_section (FILE *file)
          else
            {
              if (fseek (file, 0, SEEK_END))
-               error (_("Unable to seek to end of file!"));
+               error (_("Unable to seek to end of file!\n"));
 
              section.sh_size = ftell (file) - section.sh_offset;
            }
@@ -6809,6 +6871,8 @@ get_symbol_type (unsigned int type)
     case STT_FILE:     return "FILE";
     case STT_COMMON:   return "COMMON";
     case STT_TLS:      return "TLS";
+    case STT_RELC:      return "RELC";
+    case STT_SRELC:     return "SRELC";
     default:
       if (type >= STT_LOPROC && type <= STT_HIPROC)
        {
@@ -6999,7 +7063,7 @@ process_symbol_table (FILE *file)
                                     sizeof nb + sizeof nc)),
                 SEEK_SET))
        {
-         error (_("Unable to seek to start of dynamic information"));
+         error (_("Unable to seek to start of dynamic information\n"));
          return 0;
        }
 
@@ -7225,7 +7289,7 @@ process_symbol_table (FILE *file)
                              check_def = 0;
                            }
                          else if (! is_nobits)
-                           error (_("bad dynamic symbol"));
+                           error (_("bad dynamic symbol\n"));
                          else
                            check_def = 1;
                        }
@@ -7308,7 +7372,7 @@ process_symbol_table (FILE *file)
       lengths = calloc (nbuckets, sizeof (*lengths));
       if (lengths == NULL)
        {
-         error (_("Out of memory"));
+         error (_("Out of memory\n"));
          return 0;
        }
       for (hn = 0; hn < nbuckets; ++hn)
@@ -7324,7 +7388,7 @@ process_symbol_table (FILE *file)
       counts = calloc (maxlength + 1, sizeof (*counts));
       if (counts == NULL)
        {
-         error (_("Out of memory"));
+         error (_("Out of memory\n"));
          return 0;
        }
 
@@ -7373,7 +7437,7 @@ process_symbol_table (FILE *file)
                                     sizeof nb)),
                 SEEK_SET))
        {
-         error (_("Unable to seek to start of dynamic information"));
+         error (_("Unable to seek to start of dynamic information\n"));
          return 0;
        }
 
@@ -7397,7 +7461,7 @@ process_symbol_table (FILE *file)
                  + offset_from_vma (file, buckets_vma, 4)),
                 SEEK_SET))
        {
-         error (_("Unable to seek to start of dynamic information"));
+         error (_("Unable to seek to start of dynamic information\n"));
          return 0;
        }
 
@@ -7427,7 +7491,7 @@ process_symbol_table (FILE *file)
                                           + 4 * (ngnubuckets + maxchain), 4)),
                 SEEK_SET))
        {
-         error (_("Unable to seek to start of dynamic information"));
+         error (_("Unable to seek to start of dynamic information\n"));
          return 0;
        }
 
@@ -7451,7 +7515,7 @@ process_symbol_table (FILE *file)
                  + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
                 SEEK_SET))
        {
-         error (_("Unable to seek to start of dynamic information"));
+         error (_("Unable to seek to start of dynamic information\n"));
          return 0;
        }
 
@@ -7463,7 +7527,7 @@ process_symbol_table (FILE *file)
       lengths = calloc (ngnubuckets, sizeof (*lengths));
       if (lengths == NULL)
        {
-         error (_("Out of memory"));
+         error (_("Out of memory\n"));
          return 0;
        }
 
@@ -7488,7 +7552,7 @@ process_symbol_table (FILE *file)
       counts = calloc (maxlength + 1, sizeof (*counts));
       if (counts == NULL)
        {
-         error (_("Out of memory"));
+         error (_("Out of memory\n"));
          return 0;
        }
 
@@ -7600,6 +7664,7 @@ disassemble_section (Elf_Internal_Shdr *section, FILE *file)
 static int
 dump_section (Elf_Internal_Shdr *section, FILE *file)
 {
+  Elf_Internal_Shdr *relsec;
   bfd_size_type bytes;
   bfd_vma addr;
   unsigned char *data;
@@ -7623,6 +7688,26 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
   if (!start)
     return 0;
 
+  /* If the section being dumped has relocations against it the user might
+     be expecting these relocations to have been applied.  Check for this
+     case and issue a warning message in order to avoid confusion.
+     FIXME: Maybe we ought to have an option that dumps a section with
+     relocs applied ?  */
+  for (relsec = section_headers;
+       relsec < section_headers + elf_header.e_shnum;
+       ++relsec)
+    {
+      if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
+         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
+         || SECTION_HEADER (relsec->sh_info) != section
+         || relsec->sh_size == 0
+         || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
+       continue;
+
+      printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
+      break;
+    }
+  
   data = start;
 
   while (bytes)
@@ -7635,34 +7720,15 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
 
       printf ("  0x%8.8lx ", (unsigned long) addr);
 
-      switch (elf_header.e_ident[EI_DATA])
+      for (j = 0; j < 16; j++)
        {
-       default:
-       case ELFDATA2LSB:
-         for (j = 15; j >= 0; j --)
-           {
-             if (j < lbytes)
-               printf ("%2.2x", data[j]);
-             else
-               printf ("  ");
-
-             if (!(j & 0x3))
-               printf (" ");
-           }
-         break;
-
-       case ELFDATA2MSB:
-         for (j = 0; j < 16; j++)
-           {
-             if (j < lbytes)
-               printf ("%2.2x", data[j]);
-             else
-               printf ("  ");
+         if (j < lbytes)
+           printf ("%2.2x", data[j]);
+         else
+           printf ("  ");
 
-             if ((j & 3) == 3)
-               printf (" ");
-           }
-         break;
+         if ((j & 3) == 3)
+           printf (" ");
        }
 
       for (j = 0; j < lbytes; j++)
@@ -7683,9 +7749,47 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
 
   free (start);
 
+  putchar ('\n');
   return 1;
 }
 
+/* Return the number of bytes affected by a given reloc.
+   This information is architecture and reloc dependent.
+   Returns 4 by default, although this is not always correct.
+   It should return 0 if a decision cannot be made.
+   FIXME: This is not the correct way to solve this problem.
+   The proper way is to have target specific reloc sizing functions
+   created by the reloc-macros.h header, in the same way that it
+   already creates the reloc naming functions.  */
+
+static unsigned int
+get_reloc_size (Elf_Internal_Rela * reloc)
+{
+  switch (elf_header.e_machine)
+    {
+    case EM_H8S:
+    case EM_H8_300:
+    case EM_H8_300H:
+    case EM_H8_500:
+      switch (ELF32_R_TYPE (reloc->r_info))
+       {
+         /* PR gas/3800 - without this information we do not correctly
+            decode the debug information generated by the h8300 assembler.  */
+       case R_H8_DIR16:
+         return 2;
+       default:
+         return 4;
+       }
+    default:
+      /* FIXME: We need to extend this switch statement to cope with other
+        architecture's relocs.  (When those relocs are used against debug
+        sections, and when their size is not 4).  But see the multiple
+        inclusions of <elf/h8.h> for an example of the hoops that we need
+        to jump through in order to obtain the reloc numbers.  */
+      return 4;
+    }
+}
+
 /* Apply addends of RELA relocations.  */
 
 static int
@@ -7695,14 +7799,13 @@ debug_apply_rela_addends (void *file,
 {
   Elf_Internal_Shdr *relsec;
   unsigned char *end = start + section->sh_size;
-  /* FIXME: The relocation field size is relocation type dependent.  */
-  unsigned int reloc_size = 4;
 
   if (!is_relocatable)
     return 1;
 
-  if (section->sh_size < reloc_size)
-    return 1;
+  /* SH uses RELA but uses in place value instead of the addend field.  */
+  if (elf_header.e_machine == EM_SH)
+    return 0;
 
   for (relsec = section_headers;
        relsec < section_headers + elf_header.e_shnum;
@@ -7731,6 +7834,16 @@ debug_apply_rela_addends (void *file,
       for (rp = rela; rp < rela + nrelas; ++rp)
        {
          unsigned char *loc;
+         unsigned int reloc_size;
+
+         reloc_size = get_reloc_size (rp);
+         if (reloc_size == 0)
+           {
+             warn (_("skipping relocation of unknown size against offset 0x%lx in section %s\n"),
+                   (unsigned long) rp->r_offset,
+                   SECTION_NAME (section));
+             continue;
+           }
 
          loc = start + rp->r_offset;
          if ((loc + reloc_size) > end)
@@ -7747,6 +7860,10 @@ debug_apply_rela_addends (void *file,
 
              if (ELF32_R_SYM (rp->r_info) != 0
                  && ELF32_ST_TYPE (sym->st_info) != STT_SECTION
+                 /* Relocations against symbols without type can happen.
+                    Gcc -feliminate-dwarf2-dups may generate symbols
+                    without type for debug info.  */
+                 && ELF32_ST_TYPE (sym->st_info) != STT_NOTYPE
                  /* Relocations against object symbols can happen,
                     eg when referencing a global array.  For an
                     example of this see the _clz.o binary in libgcc.a.  */
@@ -7776,6 +7893,7 @@ debug_apply_rela_addends (void *file,
 
              if (ELF64_R_SYM (rp->r_info) != 0
                  && ELF64_ST_TYPE (sym->st_info) != STT_SECTION
+                 && ELF64_ST_TYPE (sym->st_info) != STT_NOTYPE
                  && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT)
                {
                  warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"),
@@ -8436,7 +8554,7 @@ process_mips_specific (FILE *file)
          iopt = cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (*iopt));
          if (iopt == NULL)
            {
-             error (_("Out of memory"));
+             error (_("Out of memory\n"));
              return 0;
            }
 
@@ -8621,14 +8739,14 @@ process_mips_specific (FILE *file)
 
       if (dynamic_symbols == NULL)
        {
-         error (_("conflict list found without a dynamic symbol table"));
+         error (_("conflict list found without a dynamic symbol table\n"));
          return 0;
        }
 
       iconf = cmalloc (conflictsno, sizeof (*iconf));
       if (iconf == NULL)
        {
-         error (_("Out of memory"));
+         error (_("Out of memory\n"));
          return 0;
        }
 
@@ -9585,7 +9703,7 @@ main (int argc, char **argv)
       /* Make a copy of the dump_sects array.  */
       cmdline_dump_sects = malloc (num_dump_sects);
       if (cmdline_dump_sects == NULL)
-       error (_("Out of memory allocating dump request table."));
+       error (_("Out of memory allocating dump request table.\n"));
       else
        {
          memcpy (cmdline_dump_sects, dump_sects, num_dump_sects);
This page took 0.052024 seconds and 4 git commands to generate.