* readelf.c (byte_get_little_endian): Comment typo fix.
[binutils-gdb.git] / binutils / readelf.c
index f515a20d8ddf586ddbb9cafd9bc6ef1acbcfc94a..ab5955f61b5cf0eea7303f4edb0990e22c4f64eb 100644 (file)
 #include "elf/cris.h"
 #include "elf/d10v.h"
 #include "elf/d30v.h"
+#include "elf/dlx.h"
 #include "elf/fr30.h"
+#include "elf/frv.h"
 #include "elf/h8.h"
 #include "elf/hppa.h"
 #include "elf/i386.h"
+#include "elf/i370.h"
 #include "elf/i860.h"
 #include "elf/i960.h"
 #include "elf/ia64.h"
+#include "elf/ip2k.h"
 #include "elf/m32r.h"
 #include "elf/m68k.h"
+#include "elf/m68hc11.h"
 #include "elf/mcore.h"
 #include "elf/mips.h"
 #include "elf/mmix.h"
@@ -77,6 +82,7 @@
 #include "elf/sh.h"
 #include "elf/sparc.h"
 #include "elf/v850.h"
+#include "elf/vax.h"
 #include "elf/x86-64.h"
 #include "elf/xstormy16.h"
 
@@ -155,7 +161,7 @@ print_mode;
 
 /* Forward declarations for dumb compilers.  */
 static void              print_vma                   PARAMS ((bfd_vma, print_mode));
-static void              print_symbol                PARAMS ((int, char *));
+static void              print_symbol                PARAMS ((int, const char *));
 static bfd_vma (*         byte_get)                   PARAMS ((unsigned char *, int));
 static bfd_vma            byte_get_little_endian      PARAMS ((unsigned char *, int));
 static bfd_vma            byte_get_big_endian         PARAMS ((unsigned char *, int));
@@ -260,6 +266,7 @@ static int            process_corefile_note_segment  PARAMS ((FILE *, bfd_vma, bfd_vma))
 static int               process_corefile_note_segments PARAMS ((FILE *));
 static int               process_corefile_contents      PARAMS ((FILE *));
 static int               process_arch_specific          PARAMS ((FILE *));
+static int               process_gnu_liblist            PARAMS ((FILE *));
 
 typedef int Elf32_Word;
 
@@ -399,7 +406,7 @@ byte_get_little_endian (field, size)
     case 8:
       /* We want to extract data from an 8 byte wide field and
         place it into a 4 byte wide field.  Since this is a little
-        endian source we can juts use the 4 byte extraction code.  */
+        endian source we can just use the 4 byte extraction code.  */
       /* Fall through.  */
 #endif
     case 4:
@@ -521,17 +528,17 @@ print_vma (vma, mode)
 
 /* Display a symbol on stdout.  If do_wide is not true then
    format the symbol to be at most WIDTH characters,
-   truhncating as necessary.  If WIDTH is negative then
+   truncating as necessary.  If WIDTH is negative then
    format the string to be exactly - WIDTH characters,
    truncating or padding as necessary.  */
 
 static void
 print_symbol (width, symbol)
      int width;
-     char * symbol;
+     const char * symbol;
 {
   if (do_wide)
-    printf (symbol);
+    printf ("%s", symbol);
   else if (width < 0)
     printf ("%-*.*s", width, width, symbol);
   else
@@ -601,6 +608,7 @@ guess_is_rela (e_machine)
     case EM_386:
     case EM_486:
     case EM_960:
+    case EM_DLX:
     case EM_OPENRISC:
     case EM_OR32:
     case EM_M32R:
@@ -631,6 +639,7 @@ guess_is_rela (e_machine)
     case EM_CYGNUS_MN10300:
     case EM_FR30:
     case EM_CYGNUS_FR30:
+    case EM_CYGNUS_FRV:
     case EM_SH:
     case EM_ALPHA:
     case EM_MCORE:
@@ -644,6 +653,9 @@ guess_is_rela (e_machine)
     case EM_S390_OLD:
     case EM_MMIX:
     case EM_XSTORMY16:
+    case EM_VAX:
+    case EM_IP2K:
+    case EM_IP2K_OLD:
       return TRUE;
 
     case EM_MMA:
@@ -663,7 +675,6 @@ guess_is_rela (e_machine)
     case EM_68HC05:
     case EM_SVX:
     case EM_ST19:
-    case EM_VAX:
     default:
       warn (_("Don't know about relocations on this machine architecture\n"));
       return FALSE;
@@ -971,6 +982,11 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_i386_reloc_type (type);
          break;
 
+        case EM_68HC11:
+        case EM_68HC12:
+          rtype = elf_m68hc11_reloc_type (type);
+          break;
+
        case EM_68K:
          rtype = elf_m68k_reloc_type (type);
          break;
@@ -1006,6 +1022,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_d30v_reloc_type (type);
          break;
 
+       case EM_DLX:
+         rtype = elf_dlx_reloc_type (type);
+         break;
+
        case EM_SH:
          rtype = elf_sh_reloc_type (type);
          break;
@@ -1025,6 +1045,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_fr30_reloc_type (type);
          break;
 
+        case EM_CYGNUS_FRV:
+          rtype = elf_frv_reloc_type (type);
+          break;
+
        case EM_MCORE:
          rtype = elf_mcore_reloc_type (type);
          break;
@@ -1095,6 +1119,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_x86_64_reloc_type (type);
          break;
 
+       case EM_S370:
+         rtype = i370_reloc_type (type);
+         break;
+
        case EM_S390_OLD:
        case EM_S390:
          rtype = elf_s390_reloc_type (type);
@@ -1103,6 +1131,15 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        case EM_XSTORMY16:
          rtype = elf_xstormy16_reloc_type (type);
          break;
+
+       case EM_VAX:
+         rtype = elf_vax_reloc_type (type);
+         break;
+
+       case EM_IP2K:
+       case EM_IP2K_OLD:
+         rtype = elf_ip2k_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1129,7 +1166,35 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
              printf (is_32bit_elf ? "   " : " ");
 
              if (psym->st_name == 0)
-               print_symbol (22, SECTION_NAME (section_headers + psym->st_shndx));
+               {
+                 const char *sec_name = "<null>";
+                 char name_buf[40];
+
+                 if (ELF_ST_TYPE (psym->st_info) == STT_SECTION)
+                   {
+                     bfd_vma sec_index = (bfd_vma) -1;
+
+                     if (psym->st_shndx < SHN_LORESERVE)
+                       sec_index = psym->st_shndx;
+                     else if (psym->st_shndx > SHN_LORESERVE)
+                       sec_index = psym->st_shndx - (SHN_HIRESERVE + 1
+                                                     - SHN_LORESERVE);
+
+                     if (sec_index != (bfd_vma) -1)
+                       sec_name = SECTION_NAME (section_headers + sec_index);
+                     else if (psym->st_shndx == SHN_ABS)
+                       sec_name = "ABS";
+                     else if (psym->st_shndx == SHN_COMMON)
+                       sec_name = "COMMON";
+                     else
+                       {
+                         sprintf (name_buf, "<section 0x%x>",
+                                  (unsigned int) psym->st_shndx);
+                         sec_name = name_buf;
+                       }
+                   }
+                 print_symbol (22, sec_name);
+               }
              else if (strtab == NULL)
                printf (_("<string table index %3ld>"), psym->st_name);
              else
@@ -1365,6 +1430,12 @@ get_dynamic_type (type)
     case DT_USED:      return "USED";
     case DT_FILTER:    return "FILTER";
 
+    case DT_GNU_PRELINKED: return "GNU_PRELINKED";
+    case DT_GNU_CONFLICT: return "GNU_CONFLICT";
+    case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ";
+    case DT_GNU_LIBLIST: return "GNU_LIBLIST";
+    case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ";
+
     default:
       if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
        {
@@ -1502,6 +1573,7 @@ get_machine_name (e_machine)
     case EM_MN10200:           return "mn10200";
     case EM_CYGNUS_FR30:
     case EM_FR30:              return "Fujitsu FR30";
+    case EM_CYGNUS_FRV:                return "Fujitsu FR-V";
     case EM_PJ_OLD:
     case EM_PJ:                 return "picoJava";
     case EM_MMA:               return "Fujitsu Multimedia Accelerator";
@@ -1537,6 +1609,9 @@ get_machine_name (e_machine)
     case EM_XSTORMY16:         return "Sanyo Xstormy16 CPU core";
     case EM_OPENRISC:
     case EM_OR32:              return "OpenRISC";
+    case EM_DLX:               return "OpenDLX";
+    case EM_IP2K_OLD:
+    case EM_IP2K:               return "Ubicom IP2xxx 8-bit microcontrollers";
     default:
       sprintf (buff, _("<unknown>: %x"), e_machine);
       return buff;
@@ -1730,9 +1805,6 @@ get_machine_flags (e_flags, e_machine)
            case E_V850E_ARCH:
              strcat (buf, ", v850e");
              break;
-           case E_V850EA_ARCH:
-             strcat (buf, ", v850ea");
-             break;
            case E_V850_ARCH:
              strcat (buf, ", v850");
              break;
@@ -1777,8 +1849,11 @@ get_machine_flags (e_flags, e_machine)
            case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break;
            case E_MIPS_MACH_4010: strcat (buf, ", 4010"); break;
            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_4120: strcat (buf, ", 4120"); break;
+           case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break;
+           case E_MIPS_MACH_5400: strcat (buf, ", 5400"); break;
+           case E_MIPS_MACH_5500: strcat (buf, ", 5500"); break;
            case E_MIPS_MACH_SB1:  strcat (buf, ", sb1");  break;
            case 0:
            /* We simply ignore the field in this case to avoid confusion:
@@ -1901,6 +1976,15 @@ get_machine_flags (e_flags, e_machine)
          if ((e_flags & EF_IA_64_ABSOLUTE))
            strcat (buf, ", absolute");
          break;
+
+       case EM_VAX:
+         if ((e_flags & EF_VAX_NONPIC))
+           strcat (buf, ", non-PIC");
+         if ((e_flags & EF_VAX_DFLOAT))
+           strcat (buf, ", D-Float");
+         if ((e_flags & EF_VAX_GFLOAT))
+           strcat (buf, ", G-Float");
+         break;
        }
     }
 
@@ -2160,6 +2244,7 @@ get_section_type_name (sh_type)
     case 0x6ffffffc:           return "VERDEF";
     case 0x7ffffffd:           return "AUXILIARY";
     case 0x7fffffff:           return "FILTER";
+    case SHT_GNU_LIBLIST:      return "GNU_LIBLIST";
 
     default:
       if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
@@ -2199,6 +2284,8 @@ get_section_type_name (sh_type)
     }
 }
 
+#define OPTION_DEBUG_DUMP      512
+
 struct option options [] =
 {
   {"all",              no_argument, 0, 'a'},
@@ -2218,7 +2305,7 @@ struct option options [] =
   {"version-info",     no_argument, 0, 'V'},
   {"use-dynamic",      no_argument, 0, 'D'},
   {"hex-dump",         required_argument, 0, 'x'},
-  {"debug-dump",       optional_argument, 0, 'w'},
+  {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
   {"unwind",          no_argument, 0, 'u'},
 #ifdef SUPPORT_DISASSEMBLY
   {"instruction-dump", required_argument, 0, 'i'},
@@ -2253,7 +2340,8 @@ usage ()
   -A --arch-specific     Display architecture specific information (if any).\n\
   -D --use-dynamic       Use the dynamic section info when displaying symbols\n\
   -x --hex-dump=<number> Dump the contents of section <number>\n\
-  -w --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str,=loc]\n\
+  -w[liaprmfFso] or\n\
+  --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str,=loc]\n\
                          Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stdout, _("\
@@ -2451,6 +2539,88 @@ parse_args (argc, argv)
                  }
            }
          break;
+       case OPTION_DEBUG_DUMP:
+         do_dump ++;
+         if (optarg == 0)
+           do_debugging = 1;
+         else
+           {
+             static const char *debug_dump_opt[]
+               = { "line", "info", "abbrev", "pubnames", "ranges",
+                   "macro", "frames", "frames-interp", "str", "loc", NULL };
+             unsigned int index;
+             const char *p;
+
+             do_debugging = 0;
+
+             p = optarg;
+             while (*p)
+               {
+                 for (index = 0; debug_dump_opt[index]; index++)
+                   {
+                     size_t len = strlen (debug_dump_opt[index]);
+
+                     if (strncmp (p, debug_dump_opt[index], len) == 0
+                         && (p[len] == ',' || p[len] == '\0'))
+                       {
+                         switch (p[0])
+                           {
+                           case 'i':
+                             do_debug_info = 1;
+                             break;
+
+                           case 'a':
+                             do_debug_abbrevs = 1;
+                             break;
+
+                           case 'l':
+                             if (p[1] == 'i')
+                               do_debug_lines = 1;
+                             else
+                               do_debug_loc = 1;
+                             break;
+
+                           case 'p':
+                             do_debug_pubnames = 1;
+                             break;
+
+                           case 'r':
+                             do_debug_aranges = 1;
+                             break;
+
+                           case 'f':
+                             if (len > 6)
+                               do_debug_frames_interp = 1;
+                             do_debug_frames = 1;
+                             break;
+
+                           case 'm':
+                             do_debug_macinfo = 1;
+                             break;
+
+                           case 's':
+                             do_debug_str = 1;
+                             break;
+                           }
+
+                         p += len;
+                         break;
+                       }
+                   }
+
+                 if (debug_dump_opt[index] == NULL)
+                   {
+                     warn (_("Unrecognized debug option '%s'\n"), p);
+                     p = strchr (p, ',');
+                     if (p == NULL)
+                       break;
+                   }
+
+                 if (*p == ',')
+                   p++;
+               }
+           }
+         break;
 #ifdef SUPPORT_DISASSEMBLY
        case 'i':
          do_dump ++;
@@ -2764,8 +2934,10 @@ process_program_headers (file)
 
   if (do_segments)
     {
-      printf
-       (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
+      if (elf_header.e_phnum > 1)
+       printf (_("\nProgram Headers:\n"));
+      else
+       printf (_("\nProgram Headers:\n"));
 
       if (is_32bit_elf)
        printf
@@ -3270,6 +3442,7 @@ process_section_headers (file)
   dynamic_symbols = NULL;
   dynamic_strings = NULL;
   dynamic_syminfo = NULL;
+  symtab_shndx_hdr = NULL;
 
   for (i = 0, section = section_headers;
        i < elf_header.e_shnum;
@@ -3342,7 +3515,10 @@ process_section_headers (file)
   if (! do_sections)
     return 1;
 
-  printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
+  if (elf_header.e_shnum > 1)
+    printf (_("\nSection Headers:\n"));
+  else
+    printf (_("\nSection Header:\n"));
 
   if (is_32bit_elf)
     printf
@@ -3548,7 +3724,7 @@ process_relocs (file)
              if (string_table == NULL)
                printf ("%d", section->sh_name);
              else
-               printf ("'%s'", SECTION_NAME (section));
+               printf (_("'%s'"), SECTION_NAME (section));
 
              printf (_(" at offset 0x%lx contains %lu entries:\n"),
                 rel_offset, (unsigned long) (rel_size / section->sh_entsize));
@@ -3703,13 +3879,13 @@ dump_ia64_unwind (aux)
       print_vma (tp->start.offset, PREFIX_HEX);
       fputc ('-', stdout);
       print_vma (tp->end.offset, PREFIX_HEX);
-      printf ("), info at +0x%lx\n",
+      printf ("], info at +0x%lx\n",
              (unsigned long) (tp->info.offset - aux->seg_base));
 
       head = aux->info + (tp->info.offset - aux->info_addr);
       stamp = BYTE_GET8 ((unsigned char *) head);
 
-      printf ("  v%u, flags=0x%lx (%s%s ), len=%lu bytes\n",
+      printf ("  v%u, flags=0x%lx (%s%s), len=%lu bytes\n",
              (unsigned) UNW_VER (stamp),
              (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32),
              UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "",
@@ -3981,7 +4157,7 @@ process_unwind (file)
          if (string_table == NULL)
            printf ("%d", unwsec->sh_name);
          else
-           printf ("'%s'", SECTION_NAME (unwsec));
+           printf (_("'%s'"), SECTION_NAME (unwsec));
        }
       else
        {
@@ -3995,7 +4171,7 @@ process_unwind (file)
          if (string_table == NULL)
            printf ("%d", unwsec->sh_name);
          else
-           printf ("'%s'", SECTION_NAME (unwsec));
+           printf (_("'%s'"), SECTION_NAME (unwsec));
 
          printf (_(" at offset 0x%lx contains %lu entries:\n"),
                  (unsigned long) unwsec->sh_offset,
@@ -4152,6 +4328,7 @@ dynamic_segment_parisc_val (entry)
       print_vma (entry->d_un.d_ptr, PREFIX_HEX);
       break;
     }
+  putchar ('\n');
 }
 
 static int
@@ -4502,11 +4679,13 @@ process_dynamic_segment (file)
          if (do_dynamic)
            {
              printf (_("Flags:"));
+
              if (entry->d_un.d_val == 0)
                printf (_(" None\n"));
              else
                {
                  unsigned long int val = entry->d_un.d_val;
+
                  if (val & DTF_1_PARINIT)
                    {
                      printf (" PARINIT");
@@ -4528,11 +4707,13 @@ process_dynamic_segment (file)
          if (do_dynamic)
            {
              printf (_("Flags:"));
+
              if (entry->d_un.d_val == 0)
                printf (_(" None\n"));
              else
                {
                  unsigned long int val = entry->d_un.d_val;
+
                  if (val & DF_P1_LAZYLOAD)
                    {
                      printf (" LAZYLOAD");
@@ -4559,6 +4740,7 @@ process_dynamic_segment (file)
              else
                {
                  unsigned long int val = entry->d_un.d_val;
+
                  if (val & DF_1_NOW)
                    {
                      printf (" NOW");
@@ -4716,6 +4898,8 @@ process_dynamic_segment (file)
        case DT_MOVESZ  :
        case DT_INIT_ARRAYSZ:
        case DT_FINI_ARRAYSZ:
+       case DT_GNU_CONFLICTSZ:
+       case DT_GNU_LIBLISTSZ:
          if (do_dynamic)
            {
              print_vma (entry->d_un.d_val, UNSIGNED);
@@ -4762,6 +4946,22 @@ process_dynamic_segment (file)
 
        case DT_BIND_NOW:
          /* The value of this entry is ignored.  */
+         if (do_dynamic)
+           putchar ('\n');
+         break;
+
+       case DT_GNU_PRELINKED:
+         if (do_dynamic)
+           {
+             struct tm * tmp;
+             time_t time = entry->d_un.d_val;
+
+             tmp = gmtime (&time);
+             printf ("%04u-%02u-%02uT%02u:%02u:%02u\n",
+                     tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+                     tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+           }
          break;
 
        default:
@@ -7180,7 +7380,7 @@ decode_location_expression (data, pointer_size, length)
          printf ("DW_OP_nop");
          break;
 
-         /* DWARF 2.1 extensions.  */
+         /* DWARF 3 extensions.  */
        case DW_OP_push_object_address:
          printf ("DW_OP_push_object_address");
          break;
@@ -7192,8 +7392,13 @@ decode_location_expression (data, pointer_size, length)
          printf ("DW_OP_call4: <%lx>", (long) byte_get (data, 4));
          data += 4;
          break;
-       case DW_OP_calli:
-         printf ("DW_OP_calli");
+       case DW_OP_call_ref:
+         printf ("DW_OP_call_ref");
+         break;
+
+         /* GNU extensions.  */
+       case DW_OP_GNU_push_tls_address:
+         printf ("DW_OP_GNU_push_tls_address");
          break;
 
        default:
@@ -7268,13 +7473,16 @@ display_debug_loc (section, start, file)
   addr = section->sh_addr;
   bytes = section->sh_size;
   section_end = start + bytes;
+
   if (bytes == 0)
     {
       printf (_("\nThe .debug_loc section is empty.\n"));
       return 0;
     }
+
   printf (_("Contents of the .debug_loc section:\n\n"));
   printf (_("\n    Offset   Begin    End      Expression\n"));
+
   while (start < section_end)
     {
       unsigned long begin;
@@ -7373,7 +7581,6 @@ fetch_indirect_string (offset)
   return debug_str_contents + offset;
 }
 
-
 static int
 display_debug_str (section, start, file)
      Elf32_Internal_Shdr * section;
@@ -7434,7 +7641,6 @@ display_debug_str (section, start, file)
   return 1;
 }
 
-
 static unsigned char *
 read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
      unsigned long   attribute;
@@ -7563,8 +7769,8 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
       break;
 
     case DW_FORM_strp:
-      printf (_(" (indirect string, offset: 0x%lx): "), uvalue);
-      printf (fetch_indirect_string (uvalue));
+      printf (_(" (indirect string, offset: 0x%lx): %s"),
+             uvalue, fetch_indirect_string (uvalue));
       break;
 
     case DW_FORM_indirect:
@@ -7788,8 +7994,8 @@ display_debug_info (section, start, file)
          break;
        }
 
-      /* Check for RELA relocations in the abbrev_offset address, and
-         apply them.  */
+      /* Check for RELA relocations in the
+        abbrev_offset address, and apply them.  */
       for (relsec = section_headers;
           relsec < section_headers + elf_header.e_shnum;
           ++relsec)
@@ -7801,7 +8007,8 @@ display_debug_info (section, start, file)
          Elf_Internal_Sym *sym;
 
          if (relsec->sh_type != SHT_RELA
-             || SECTION_HEADER (relsec->sh_info) != section)
+             || SECTION_HEADER (relsec->sh_info) != section
+             || relsec->sh_size == 0)
            continue;
 
          if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
@@ -7822,7 +8029,8 @@ display_debug_info (section, start, file)
                {
                  sym = symtab + ELF32_R_SYM (rp->r_info);
 
-                 if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
+                 if (ELF32_R_SYM (rp->r_info) != 0
+                     && ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
                    {
                      warn (_("Skipping unexpected symbol type %u\n"),
                            ELF32_ST_TYPE (sym->st_info));
@@ -7833,7 +8041,8 @@ display_debug_info (section, start, file)
                {
                  sym = symtab + ELF64_R_SYM (rp->r_info);
 
-                 if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
+                 if (ELF64_R_SYM (rp->r_info) != 0
+                     && ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
                    {
                      warn (_("Skipping unexpected symbol type %u\n"),
                            ELF64_ST_TYPE (sym->st_info));
@@ -7841,7 +8050,7 @@ display_debug_info (section, start, file)
                    }
                }
 
-             compunit.cu_abbrev_offset += rp->r_addend;
+             compunit.cu_abbrev_offset = rp->r_addend;
              break;
            }
 
@@ -7868,7 +8077,6 @@ display_debug_info (section, start, file)
       free_abbrevs ();
 
       /* Read in the abbrevs used by this compilation unit.  */
-
       {
        Elf32_Internal_Shdr * sec;
        unsigned char *       begin;
@@ -8201,7 +8409,11 @@ display_debug_frames (section, start, file)
       length = byte_get (start, 4); start += 4;
 
       if (length == 0)
-       return 1;
+       {
+         printf ("\n%08lx ZERO terminator\n\n",
+                   (unsigned long)(saved_start - section_start));
+         return 1;
+       }
 
       if (length == 0xffffffff)
        {
@@ -8355,6 +8567,8 @@ display_debug_frames (section, start, file)
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
          fc->pc_begin = byte_get (start, encoded_ptr_size);
+         if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
+           fc->pc_begin += section->sh_addr + (start - section_start);
          start += encoded_ptr_size;
          fc->pc_range = byte_get (start, encoded_ptr_size);
          start += encoded_ptr_size;
@@ -8461,15 +8675,20 @@ display_debug_frames (section, start, file)
                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_offset_extended_sf:
+                 reg = LEB (); SLEB ();
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_def_cfa_sf:
+                 LEB (); SLEB ();
+                 break;
+               case DW_CFA_def_cfa_offset_sf:
+                 SLEB ();
+                 break;
                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);
@@ -8529,6 +8748,8 @@ display_debug_frames (section, start, file)
 
            case DW_CFA_set_loc:
              vma = byte_get (start, encoded_ptr_size);
+             if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
+               vma += section->sh_addr + (start - section_start);
              start += encoded_ptr_size;
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
@@ -8664,9 +8885,31 @@ display_debug_frames (section, start, file)
                printf ("  DW_CFA_nop\n");
              break;
 
-#ifndef DW_CFA_GNU_window_save
-#define DW_CFA_GNU_window_save 0x2d
-#endif
+           case DW_CFA_offset_extended_sf:
+             reg = LEB ();
+             l = SLEB ();
+             frame_need_space (fc, reg);
+             if (! do_debug_frames_interp)
+               printf ("  DW_CFA_offset_extended_sf: r%ld at cfa%+ld\n",
+                       reg, l * fc->data_factor);
+             fc->col_type[reg] = DW_CFA_offset;
+             fc->col_offset[reg] = l * fc->data_factor;
+             break;
+
+           case DW_CFA_def_cfa_sf:
+             fc->cfa_reg = LEB ();
+             fc->cfa_offset = SLEB ();
+             if (! do_debug_frames_interp)
+               printf ("  DW_CFA_def_cfa_sf: r%d ofs %d\n",
+                       fc->cfa_reg, fc->cfa_offset);
+             break;
+
+           case DW_CFA_def_cfa_offset_sf:
+             fc->cfa_offset = SLEB ();
+             if (! do_debug_frames_interp)
+               printf ("  DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
+             break;
+
            case DW_CFA_GNU_window_save:
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_GNU_window_save\n");
@@ -8689,6 +8932,17 @@ display_debug_frames (section, start, file)
              fc->col_offset[reg] = l * fc->data_factor;
              break;
 
+           /* FIXME: How do we handle these? */
+           case DW_CFA_def_cfa_expression:
+             fprintf (stderr, "unsupported DW_CFA_def_cfa_expression\n");
+             start = block_end;
+             break;
+
+           case DW_CFA_expression:
+             fprintf (stderr, "unsupported DW_CFA_expression\n");
+             start = block_end;
+             break;
+
            default:
              fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op);
              start = block_end;
@@ -9227,7 +9481,7 @@ process_mips_specific (file)
 
       if (dynamic_symbols == NULL)
        {
-         error (_("conflict list with without table"));
+         error (_("conflict list found without a dynamic symbol table"));
          return 0;
        }
 
@@ -9292,6 +9546,86 @@ process_mips_specific (file)
   return 1;
 }
 
+static int
+process_gnu_liblist (file)
+     FILE * file;
+{
+  Elf_Internal_Shdr * section, * string_sec;
+  Elf32_External_Lib * elib;
+  char * strtab;
+  size_t cnt;
+  unsigned i;
+
+  if (! do_arch)
+    return 0;
+
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum;
+       i++, section ++)
+    {
+      switch (section->sh_type)
+       {
+       case SHT_GNU_LIBLIST:
+         elib = ((Elf32_External_Lib *)
+                get_data (NULL, file, section->sh_offset, section->sh_size,
+                          _("liblist")));
+
+         if (elib == NULL)
+           break;
+         string_sec = SECTION_HEADER (section->sh_link);
+
+         strtab = (char *) get_data (NULL, file, string_sec->sh_offset,
+                                     string_sec->sh_size,
+                                     _("liblist string table"));
+
+         if (strtab == NULL
+             || section->sh_entsize != sizeof (Elf32_External_Lib))
+           {
+             free (elib);
+             break;
+           }
+
+         printf (_("\nLibrary list section '%s' contains %lu entries:\n"),
+                 SECTION_NAME (section),
+                 (long) (section->sh_size / sizeof (Elf32_External_Lib)));
+
+         puts ("     Library              Time Stamp          Checksum   Version Flags");
+
+         for (cnt = 0; cnt < section->sh_size / sizeof (Elf32_External_Lib);
+              ++cnt)
+           {
+             Elf32_Lib liblist;
+             time_t time;
+             char timebuf[20];
+             struct tm * tmp;
+
+             liblist.l_name = BYTE_GET (elib[cnt].l_name);
+             time = BYTE_GET (elib[cnt].l_time_stamp);
+             liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
+             liblist.l_version = BYTE_GET (elib[cnt].l_version);
+             liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
+
+             tmp = gmtime (&time);
+             sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
+                      tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+                      tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+             printf ("%3lu: ", (unsigned long) cnt);
+             if (do_wide)
+               printf ("%-20s", strtab + liblist.l_name);
+             else
+               printf ("%-20.20s", strtab + liblist.l_name);
+             printf (" %s %#010lx %-7ld %-7ld\n", timebuf, liblist.l_checksum,
+                     liblist.l_version, liblist.l_flags);
+           }
+
+         free (elib);
+       }
+    }
+
+  return 1;
+}
+
 static const char *
 get_note_type (e_type)
      unsigned e_type;
@@ -9310,7 +9644,7 @@ get_note_type (e_type)
     case NT_PSINFO:    return _("NT_PSINFO (psinfo structure)");
     case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)");
     case NT_LWPSINFO:  return _("NT_LWPSINFO (lwpsinfo_t structure)");
-    case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus strcuture)");
+    case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus structure)");
     default:
       sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
       return buff;
@@ -9661,12 +9995,15 @@ get_file_header (file)
       elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
     }
 
-  /* There may be some extensions in the first section header.  Don't
-     bomb if we can't read it.  */
-  if (is_32bit_elf)
-    get_32bit_section_headers (file, 1);
-  else
-    get_64bit_section_headers (file, 1);
+  if (elf_header.e_shoff)
+    {
+      /* There may be some extensions in the first section header.  Don't
+        bomb if we can't read it.  */
+      if (is_32bit_elf)
+       get_32bit_section_headers (file, 1);
+      else
+       get_64bit_section_headers (file, 1);
+    }
 
   return 1;
 }
@@ -9736,6 +10073,8 @@ process_file (file_name)
 
   process_corefile_contents (file);
 
+  process_gnu_liblist (file);
+
   process_arch_specific (file);
 
   fclose (file);