]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
Prevent seg fault with corrupt section name indicies
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index a689e9850f2d5cf958ece5d5cbf70044897c75a9..66f48fb2b45b53b3eb644ab4edc7af0f5f37379b 100644 (file)
@@ -1,5 +1,5 @@
 /* readelf.c -- display contents of an ELF format file
-   Copyright (C) 1998, 99, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1998, 99, 2000, 2001 Free Software Foundation, Inc.
 
    Originally developed by Eric Youngdale <eric@andante.jic.com>
    Modifications by Nick Clifton <nickc@cygnus.com>
@@ -73,6 +73,7 @@
 #include "elf/ia64.h"
 #include "elf/cris.h"
 #include "elf/i860.h"
+#include "elf/x86-64.h"
 
 #include "bucomm.h"
 #include "getopt.h"
@@ -84,6 +85,7 @@ unsigned int          rela_addr;
 unsigned int           rela_size;
 char *                 dynamic_strings;
 char *                 string_table;
+unsigned long          string_table_length;
 unsigned long           num_dynamic_syms;
 Elf_Internal_Sym *     dynamic_symbols;
 Elf_Internal_Syminfo * dynamic_syminfo;
@@ -231,7 +233,9 @@ typedef int Elf32_Word;
 #endif
 #define UNKNOWN -1
 
-#define SECTION_NAME(X)        (string_table + (X)->sh_name)
+#define SECTION_NAME(X)        ((X) == NULL ? "<none>" : \
+                                ((X)->sh_name >= string_table_length \
+                                 ? "<corrupt>" : string_table + (X)->sh_name))
 
 #define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
 
@@ -534,8 +538,8 @@ byte_get_big_endian (field, size)
     }
 }
 
+/* Guess the relocation size commonly used by the specific machines.  */
 
-/* Guess the relocation sized based on the sized commonly used by the specific machine.  */
 static int
 guess_is_rela (e_machine)
      unsigned long e_machine;
@@ -571,6 +575,7 @@ guess_is_rela (e_machine)
     case EM_AVR:
     case EM_CRIS:
     case EM_860:
+    case EM_X86_64:
       return TRUE;
 
     case EM_MMA:
@@ -872,6 +877,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          break;
 
        case EM_CYGNUS_ARC:
+       case EM_ARC:
          rtype = elf_arc_reloc_type (type);
          break;
 
@@ -893,6 +899,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        case EM_860:
          rtype = elf_i860_reloc_type (type);
          break;
+
+       case EM_X86_64:
+         rtype = elf_x86_64_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1224,7 +1234,7 @@ get_machine_name (e_machine)
     case EM_SH:                        return "Hitachi SH";
     case EM_SPARCV9:           return "Sparc v9";
     case EM_TRICORE:           return "Siemens Tricore";
-    case EM_ARC:               return "Argonaut RISC Core";
+    case EM_ARC:               return "ARC";
     case EM_H8_300:            return "Hitachi H8/300";
     case EM_H8_300H:           return "Hitachi H8/300H";
     case EM_H8S:               return "Hitachi H8S";
@@ -1236,7 +1246,7 @@ get_machine_name (e_machine)
     case EM_ALPHA:             return "Alpha";
     case EM_CYGNUS_D10V:        return "d10v";
     case EM_CYGNUS_D30V:        return "d30v";
-    case EM_CYGNUS_ARC:                return "Arc";
+    case EM_CYGNUS_ARC:                return "ARC";
     case EM_CYGNUS_M32R:       return "Mitsubishi M32r";
     case EM_CYGNUS_V850:       return "NEC v850";
     case EM_CYGNUS_MN10300:    return "mn10300";
@@ -1269,7 +1279,7 @@ get_machine_name (e_machine)
     case EM_MMIX:              return "Donald Knuth's educational 64-bit processor";
     case EM_HUANY:             return "Harvard Universitys's machine-independent object format";
     case EM_PRISM:             return "SiTera Prism";
-      
+    case EM_X86_64:            return "Advanced Micro Devices X86-64";
     default:
       sprintf (buff, _("<unknown>: %x"), e_machine);
       return buff;
@@ -1471,6 +1481,15 @@ get_machine_flags (e_flags, e_machine)
          if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
            strcat (buf, ", mips4");
 
+         if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_5)
+           strcat (buf, ", mips5");
+
+         if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32)
+           strcat (buf, ", mips32");
+
+         if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64)
+           strcat (buf, ", mips64");
+
          switch ((e_flags & EF_MIPS_MACH))
            {
            case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break;
@@ -1478,7 +1497,9 @@ get_machine_flags (e_flags, e_machine)
            case E_MIPS_MACH_4100: strcat (buf, ", 4100"); break;
            case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break;
            case E_MIPS_MACH_4111: strcat (buf, ", 4111"); break;
-           case E_MIPS_MACH_MIPS32: strcat (buf, ", mips32"); break;
+           case E_MIPS_MACH_MIPS32_4K: strcat (buf, ", mips32-4k"); break;
+           case E_MIPS_MACH_SB1:  strcat (buf, ", sb1");  break;
+           default: strcat (buf, " UNKNOWN"); break;
            }
          break;
 
@@ -2694,12 +2715,10 @@ process_section_headers (file)
 
   if (section->sh_size != 0)
     {
-      unsigned long string_table_offset;
-
-      string_table_offset = section->sh_offset;
-
       GET_DATA_ALLOC (section->sh_offset, section->sh_size,
                      string_table, char *, "string table");
+
+      string_table_length = section->sh_size;
     }
 
   /* Scan the sections for the dynamic symbol table
@@ -2754,6 +2773,10 @@ process_section_headers (file)
              )
            request_dump (i, DEBUG_DUMP);
        }
+      /* linkonce section to be combined with .debug_info at link time.  */
+      else if ((do_debugging || do_debug_info)
+              && strncmp (name, ".gnu.linkonce.wi.", 17) == 0)
+       request_dump (i, DEBUG_DUMP);
       else if (do_debug_frames && strcmp (name, ".eh_frame") == 0)
        request_dump (i, DEBUG_DUMP);
     }
@@ -4639,13 +4662,13 @@ process_symbol_table (file)
 
   if (do_histogram && buckets != NULL)
     {
-      int *lengths;
-      int *counts;
-      int hn;
-      int si;
-      int maxlength = 0;
-      int nzero_counts = 0;
-      int nsyms = 0;
+      int * lengths;
+      int * counts;
+      int   hn;
+      int   si;
+      int   maxlength = 0;
+      int   nzero_counts = 0;
+      int   nsyms = 0;
 
       printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
              nbuckets);
@@ -5663,7 +5686,7 @@ display_debug_abbrev (section, start, file)
      unsigned char *       start;
      FILE *                file ATTRIBUTE_UNUSED;
 {
-  abbrev_entry * entry;
+  abbrev_entry *  entry;
   unsigned char * end = start + section->sh_size;
 
   printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
@@ -5716,12 +5739,12 @@ static void
 decode_location_expression (data, pointer_size, length)
      unsigned char * data;
      unsigned int    pointer_size;
-     unsigned long length;
+     unsigned long   length;
 {
-  unsigned op;
-  int           bytes_read;
-  unsigned long uvalue;
-  unsigned char *end = data + length;
+  unsigned        op;
+  int             bytes_read;
+  unsigned long   uvalue;
+  unsigned char * end = data + length;
 
   while (data < end)
     {
@@ -6312,18 +6335,18 @@ display_debug_info (section, start, file)
       cu_offset = start - section_begin;
       start += compunit.cu_length + sizeof (external->cu_length);
 
+      printf (_("  Compilation Unit @ %lx:\n"), cu_offset);
+      printf (_("   Length:        %ld\n"), compunit.cu_length);
+      printf (_("   Version:       %d\n"), compunit.cu_version);
+      printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
+      printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
+
       if (compunit.cu_version != 2)
        {
          warn (_("Only version 2 DWARF debug information is currently supported.\n"));
          continue;
        }
 
-      printf (_("  Compilation Unit:\n"));
-      printf (_("   Length:        %ld\n"), compunit.cu_length);
-      printf (_("   Version:       %d\n"), compunit.cu_version);
-      printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
-      printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
-
       if (first_abbrev != NULL)
        free_abbrevs ();
 
@@ -6452,7 +6475,7 @@ display_debug_aranges (section, start, file)
       ranges = start + sizeof (* external);
 
       /* Must pad to an alignment boundary that is twice the pointer size.  */
-      excess = sizeof (*external) % (2 * arange.ar_pointer_size);
+      excess = sizeof (* external) % (2 * arange.ar_pointer_size);
       if (excess)
        ranges += (2 * arange.ar_pointer_size) - excess;
 
@@ -6483,41 +6506,46 @@ display_debug_aranges (section, start, file)
 
 typedef struct Frame_Chunk
 {
-  struct Frame_Chunk *next;
-  unsigned char *chunk_start;
-  int ncols;
-  /* DW_CFA_{undefined,same_value,offset,register}  */
-  unsigned char *col_type;
-  int *col_offset;
-  char *augmentation;
-  unsigned int code_factor;
-  unsigned int data_factor;
-  unsigned long pc_begin;
-  unsigned long pc_range;
-  int cfa_reg;
-  int cfa_offset
-  int ra;
+  struct Frame_Chunk * next;
+  unsigned char *      chunk_start;
+  int                  ncols;
+  /* DW_CFA_{undefined,same_value,offset,register,unreferenced}  */
+  short int *          col_type;
+  int *                col_offset;
+  char *               augmentation;
+  unsigned int         code_factor;
+  unsigned int         data_factor;
+  unsigned long        pc_begin;
+  unsigned long        pc_range;
+  int                  cfa_reg;
+  int                  cfa_offset;
+  int                  ra;
 }
 Frame_Chunk;
 
+/* A marker for a col_type that means this column was never referenced
+   in the frame info.  */
+#define DW_CFA_unreferenced (-1)
+
 static void
 frame_need_space (fc, reg)
-     Frame_Chunk *fc;
+     Frame_Chunk * fc;
      int reg;
 {
   int prev = fc->ncols;
 
   if (reg < fc->ncols)
     return;
+
   fc->ncols = reg + 1;
-  fc->col_type = (unsigned char *) xrealloc (fc->col_type,
-                                            fc->ncols * sizeof (unsigned char));
+  fc->col_type = (short int *) xrealloc (fc->col_type,
+                                        fc->ncols * sizeof (short int));
   fc->col_offset = (int *) xrealloc (fc->col_offset,
                                     fc->ncols * sizeof (int));
 
   while (prev < fc->ncols)
     {
-      fc->col_type[prev] = DW_CFA_undefined;
+      fc->col_type[prev] = DW_CFA_unreferenced;
       fc->col_offset[prev] = 0;
       prev++;
     }
@@ -6525,57 +6553,69 @@ frame_need_space (fc, reg)
 
 static void
 frame_display_row (fc, need_col_headers, max_regs)
-     Frame_Chunk *fc;
-     int *need_col_headers;
-     int *max_regs;
+     Frame_Chunk * fc;
+     int *         need_col_headers;
+     int *         max_regs;
 {
   int r;
   char tmp[100];
 
-  if (*max_regs < fc->ncols)
-    *max_regs = fc->ncols;
-  if (*need_col_headers)
+  if (* max_regs < fc->ncols)
+    * max_regs = fc->ncols;
+
+  if (* need_col_headers)
     {
-      *need_col_headers = 0;
+      * need_col_headers = 0;
+
       printf ("   LOC   CFA      ");
-      for (r=0; r<*max_regs; r++)
-       if (r == fc->ra)
-         printf ("ra   ");
-       else
-         printf ("r%-4d", r);
+
+      for (r = 0; r < * max_regs; r++)
+       if (fc->col_type[r] != DW_CFA_unreferenced)
+         {
+           if (r == fc->ra)
+             printf ("ra   ");
+           else
+             printf ("r%-4d", r);
+         }
+
       printf ("\n");
     }
+
   printf ("%08x ", (unsigned int) fc->pc_begin);
   sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
   printf ("%-8s ", tmp);
-  for (r=0; r<fc->ncols; r++)
+
+  for (r = 0; r < fc->ncols; r++)
     {
-      switch (fc->col_type[r])
+      if (fc->col_type[r] != DW_CFA_unreferenced)
        {
-       case DW_CFA_undefined:
-         strcpy (tmp, "u");
-         break;
-       case DW_CFA_same_value:
-         strcpy (tmp, "u");
-         break;
-       case DW_CFA_offset:
-         sprintf (tmp, "c%+d", fc->col_offset[r]);
-         break;
-       case DW_CFA_register:
-         sprintf (tmp, "r%d", fc->col_offset[r]);
-         break;
-       default:
-         strcpy (tmp, "n/a");
-         break;
+         switch (fc->col_type[r])
+           {
+           case DW_CFA_undefined:
+             strcpy (tmp, "u");
+             break;
+           case DW_CFA_same_value:
+             strcpy (tmp, "s");
+             break;
+           case DW_CFA_offset:
+             sprintf (tmp, "c%+d", fc->col_offset[r]);
+             break;
+           case DW_CFA_register:
+             sprintf (tmp, "r%d", fc->col_offset[r]);
+             break;
+           default:
+             strcpy (tmp, "n/a");
+             break;
+           }
+         printf ("%-5s", tmp);
        }
-      printf ("%-5s", tmp);
     }
   printf ("\n");
 }
 
 #define GET(N) byte_get (start, N); start += N
-#define LEB()  read_leb128 (start, &length_return, 0); start += length_return
-#define SLEB() read_leb128 (start, &length_return, 1); start += length_return
+#define LEB()  read_leb128 (start, & length_return, 0); start += length_return
+#define SLEB() read_leb128 (start, & length_return, 1); start += length_return
 
 static int
 display_debug_frames (section, start, file)
@@ -6584,21 +6624,25 @@ display_debug_frames (section, start, file)
      FILE *                file ATTRIBUTE_UNUSED;
 {
   unsigned char * end = start + section->sh_size;
-  unsigned char *section_start = start;
-  Frame_Chunk *chunks = 0;
-  Frame_Chunk *remembered_state = 0, *rs;
-  int is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0);
-  int length_return;
-  int max_regs = 0;
+  unsigned char * section_start = start;
+  Frame_Chunk *   chunks = 0;
+  Frame_Chunk *   remembered_state = 0;
+  Frame_Chunk *   rs;
+  int             is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0);
+  int             length_return;
+  int             max_regs = 0;
 
   printf (_("The section %s contains:\n"), SECTION_NAME (section));
 
   while (start < end)
     {
-      unsigned char *saved_start, *block_end;
-      unsigned long length, cie_id;
-      Frame_Chunk *fc, *cie;
-      int need_col_headers = 1;
+      unsigned char * saved_start;
+      unsigned char * block_end;
+      unsigned long   length;
+      unsigned long   cie_id;
+      Frame_Chunk *   fc;
+      Frame_Chunk *   cie;
+      int             need_col_headers = 1;
 
       saved_start = start;
       length = byte_get (start, 4); start += 4;
@@ -6620,13 +6664,18 @@ display_debug_frames (section, start, file)
          chunks = fc;
          fc->chunk_start = saved_start;
          fc->ncols = 0;
-         fc->col_type = (unsigned char *) xmalloc (sizeof (unsigned char));
+         fc->col_type = (short int *) xmalloc (sizeof (short int));
          fc->col_offset = (int *) xmalloc (sizeof (int));
          frame_need_space (fc, max_regs-1);
 
          start ++; /* version */
          fc->augmentation = start;
-         while (*start) start++; start++; /* skip past NUL */
+
+         while (* start)
+           start++;
+
+         start++; /* skip past NUL */
+
          if (fc->augmentation[0] == 'z')
            {
              int xtra;
@@ -6658,9 +6707,10 @@ display_debug_frames (section, start, file)
        }
       else
        {
-         unsigned char *look_for;
+         unsigned char *    look_for;
          static Frame_Chunk fde_fc;
-         fc = &fde_fc;
+
+         fc = & fde_fc;
          memset (fc, 0, sizeof (Frame_Chunk));
 
          look_for = is_eh ? start-4-cie_id : (unsigned char *) cie_id;
@@ -6674,18 +6724,18 @@ display_debug_frames (section, start, file)
              warn ("Invalid CIE pointer %08x in FDE at %08x\n", cie_id, saved_start);
              start = block_end;
              fc->ncols = 0;
-             fc->col_type = (unsigned char *) xmalloc (sizeof (unsigned char));
+             fc->col_type = (short int *) xmalloc (sizeof (short int));
              fc->col_offset = (int *) xmalloc (sizeof (int));
-             frame_need_space (fc, max_regs-1);
+             frame_need_space (fc, max_regs - 1);
              cie = fc;
              fc->augmentation = "";
            }
          else
            {
              fc->ncols = cie->ncols;
-             fc->col_type = (unsigned char *) xmalloc (fc->ncols * sizeof (unsigned char));
+             fc->col_type = (short int *) xmalloc (fc->ncols * sizeof (short int));
              fc->col_offset = (int *) xmalloc (fc->ncols * sizeof (int));
-             memcpy (fc->col_type, cie->col_type, fc->ncols);
+             memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
              memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
              fc->augmentation = cie->augmentation;
              fc->code_factor = cie->code_factor;
@@ -6713,6 +6763,107 @@ display_debug_frames (section, start, file)
       /* This exists for readelf maintainers.  */
 #define FDEBUG 0
 
+      {
+       /* Start by making a pass over the chunk, allocating storage
+           and taking note of what registers are used.  */
+       unsigned char * tmp = start;
+
+       while (start < block_end)
+         {
+           unsigned op, opa;
+           unsigned long reg;
+           bfd_vma vma;
+           
+           op = * start ++;
+           opa = op & 0x3f;
+           if (op & 0xc0)
+             op &= 0xc0;
+           
+           /* Warning: if you add any more cases to this switch, be
+              sure to add them to the corresponding switch below.  */
+           switch (op)
+             {
+             case DW_CFA_advance_loc:
+               break;
+             case DW_CFA_offset:
+               LEB ();
+               frame_need_space (fc, opa);
+               fc->col_type[opa] = DW_CFA_undefined;
+               break;
+             case DW_CFA_restore:
+               frame_need_space (fc, opa);
+               fc->col_type[opa] = DW_CFA_undefined;
+               break;
+             case DW_CFA_set_loc:
+               start += sizeof (vma);
+               break;
+             case DW_CFA_advance_loc1:
+               start += 1;
+               break;
+             case DW_CFA_advance_loc2:
+               start += 2;
+               break;
+             case DW_CFA_advance_loc4:
+               start += 4;
+               break;
+             case DW_CFA_offset_extended:
+               reg = LEB (); LEB ();
+               frame_need_space (fc, reg);
+               fc->col_type[reg] = DW_CFA_undefined;
+               break;
+             case DW_CFA_restore_extended:
+               reg = LEB ();
+               frame_need_space (fc, reg);
+               fc->col_type[reg] = DW_CFA_undefined;
+               break;
+             case DW_CFA_undefined:
+               reg = LEB ();
+               frame_need_space (fc, reg);
+               fc->col_type[reg] = DW_CFA_undefined;
+               break;
+             case DW_CFA_same_value:
+               reg = LEB ();
+               frame_need_space (fc, reg);
+               fc->col_type[reg] = DW_CFA_undefined;
+               break;
+             case DW_CFA_register:
+               reg = LEB (); LEB ();
+               frame_need_space (fc, reg);
+               fc->col_type[reg] = DW_CFA_undefined;
+               break;
+             case DW_CFA_def_cfa:
+               LEB (); LEB ();
+               break;
+             case DW_CFA_def_cfa_register:
+               LEB ();
+               break;
+             case DW_CFA_def_cfa_offset:
+               LEB ();
+               break;
+#ifndef DW_CFA_GNU_args_size
+#define DW_CFA_GNU_args_size 0x2e
+#endif
+             case DW_CFA_GNU_args_size:
+               LEB ();
+               break;          
+#ifndef DW_CFA_GNU_negative_offset_extended
+#define DW_CFA_GNU_negative_offset_extended 0x2f
+#endif
+             case DW_CFA_GNU_negative_offset_extended:
+               reg = LEB (); LEB ();      
+               frame_need_space (fc, reg);
+               fc->col_type[reg] = DW_CFA_undefined;
+               
+             default:
+               break;
+             }
+         }
+       start = tmp;
+      }
+
+      /* Now we know what registers are used, make a second pass over
+         the chunk, this time actually printing out the info.  */
+
       while (start < block_end)
        {
          unsigned op, opa;
@@ -6725,6 +6876,8 @@ display_debug_frames (section, start, file)
          if (op & 0xc0)
            op &= 0xc0;
 
+           /* Warning: if you add any more cases to this switch, be
+              sure to add them to the corresponding switch above.  */
          switch (op)
            {
            case DW_CFA_advance_loc:
@@ -6737,7 +6890,6 @@ display_debug_frames (section, start, file)
              break;
 
            case DW_CFA_offset:
-             frame_need_space (fc, opa);
              roffs = LEB ();
 #if FDEBUG
              printf ("  DW_CFA_offset: r%d = cfa[%d*%d]\n", opa, roffs, fc->data_factor);
@@ -6747,7 +6899,6 @@ display_debug_frames (section, start, file)
              break;
 
            case DW_CFA_restore:
-             frame_need_space (fc, opa);
 #if FDEBUG
              printf ("  DW_CFA_restore: r%d\n", opa);
 #endif
@@ -6797,7 +6948,6 @@ display_debug_frames (section, start, file)
            case DW_CFA_offset_extended:
              reg = LEB ();
              roffs = LEB ();
-             frame_need_space (fc, reg);
 #if FDEBUG
              printf ("  DW_CFA_offset_extended: r%d = cfa[%d*%d]\n", reg, roffs, fc->data_factor);
 #endif
@@ -6807,7 +6957,6 @@ display_debug_frames (section, start, file)
 
            case DW_CFA_restore_extended:
              reg = LEB ();
-             frame_need_space (fc, reg);
 #if FDEBUG
              printf ("  DW_CFA_restore_extended: r%d\n", reg);
 #endif
@@ -6817,7 +6966,6 @@ display_debug_frames (section, start, file)
 
            case DW_CFA_undefined:
              reg = LEB ();
-             frame_need_space (fc, reg);
 #if FDEBUG
              printf ("  DW_CFA_undefined: r%d\n", reg);
 #endif
@@ -6827,7 +6975,6 @@ display_debug_frames (section, start, file)
 
            case DW_CFA_same_value:
              reg = LEB ();
-             frame_need_space (fc, reg);
 #if FDEBUG
              printf ("  DW_CFA_same_value: r%d\n", reg);
 #endif
@@ -6838,9 +6985,8 @@ display_debug_frames (section, start, file)
            case DW_CFA_register:
              reg = LEB ();
              roffs = LEB ();
-             frame_need_space (fc, reg);
 #if FDEBUG
-             printf ("  DW_CFA_ame_value: r%d\n", reg);
+             printf ("  DW_CFA_register: r%d\n", reg);
 #endif
              fc->col_type[reg] = DW_CFA_register;
              fc->col_offset[reg] = roffs;
@@ -6852,7 +6998,7 @@ display_debug_frames (section, start, file)
 #endif
              rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
              rs->ncols = fc->ncols;
-             rs->col_type = (unsigned char *) xmalloc (rs->ncols);
+             rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int));
              rs->col_offset = (int *) xmalloc (rs->ncols * sizeof (int));
              memcpy (rs->col_type, fc->col_type, rs->ncols);
              memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
@@ -7033,6 +7179,9 @@ display_debug_section (section, file)
                  "debug section data");
 
   /* See if we know how to display the contents of this section.  */
+  if (strncmp (name, ".gnu.linkonce.wi.", 17) == 0)
+    name = ".debug_info";  
+
   for (i = NUM_ELEM (debug_displays); i--;)
     if (strcmp (debug_displays[i].name, name) == 0)
       {
@@ -7269,7 +7418,7 @@ process_mips_specific (file)
                      Elf_External_Options *, "options");
 
       iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
-                                             * sizeof (*iopt));
+                                             * sizeof (* iopt));
       if (iopt == NULL)
        {
          error (_("Out of memory"));
@@ -7297,7 +7446,7 @@ process_mips_specific (file)
        }
 
       printf (_("\nSection '%s' contains %d entries:\n"),
-             string_table + sect->sh_name, cnt);
+             SECTION_NAME (sect), cnt);
 
       option = iopt;
 
@@ -7316,8 +7465,8 @@ process_mips_specific (file)
              if (elf_header.e_machine == EM_MIPS)
                {
                  /* 32bit form.  */
-                 Elf32_External_RegInfo *ereg;
-                 Elf32_RegInfo reginfo;
+                 Elf32_External_RegInfo * ereg;
+                 Elf32_RegInfo            reginfo;
 
                  ereg = (Elf32_External_RegInfo *) (option + 1);
                  reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
@@ -7434,7 +7583,7 @@ process_mips_specific (file)
              break;
            }
 
-         len = sizeof (*eopt);
+         len = sizeof (* eopt);
          while (len < option->size)
            if (((char *) option)[len] >= ' '
                && ((char *) option)[len] < 0x7f)
@@ -7462,7 +7611,7 @@ process_mips_specific (file)
          return 0;
        }
 
-      iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (*iconf));
+      iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (* iconf));
       if (iconf == NULL)
        {
          error (_("Out of memory"));
@@ -7471,7 +7620,7 @@ process_mips_specific (file)
 
       if (is_32bit_elf)
        {
-         GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf32),
+         GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (* econf32),
                          econf32, Elf32_External_Conflict *, "conflict");
 
          for (cnt = 0; cnt < conflictsno; ++cnt)
@@ -7479,7 +7628,7 @@ process_mips_specific (file)
        }
       else
        {
-         GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf64),
+         GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (* econf64),
                          econf64, Elf64_External_Conflict *, "conflict");
 
          for (cnt = 0; cnt < conflictsno; ++cnt)
@@ -7856,6 +8005,7 @@ process_file (file_name)
     {
       free (string_table);
       string_table = NULL;
+      string_table_length = 0;
     }
 
   if (dynamic_strings)