* readelf.c (byte_get_little_endian): Comment typo fix.
[binutils-gdb.git] / binutils / readelf.c
index 45ce308fe8725477a467348019286375abcfc233..ab5955f61b5cf0eea7303f4edb0990e22c4f64eb 100644 (file)
 #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"
@@ -79,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"
 
@@ -157,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));
@@ -262,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;
 
@@ -401,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:
@@ -523,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
@@ -648,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:
@@ -667,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;
@@ -975,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;
@@ -1107,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);
@@ -1115,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)
@@ -1141,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
@@ -1377,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))
        {
@@ -1551,6 +1610,8 @@ get_machine_name (e_machine)
     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;
@@ -1744,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;
@@ -1791,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:
@@ -1915,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;
        }
     }
 
@@ -2174,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))
@@ -2213,6 +2284,8 @@ get_section_type_name (sh_type)
     }
 }
 
+#define OPTION_DEBUG_DUMP      512
+
 struct option options [] =
 {
   {"all",              no_argument, 0, 'a'},
@@ -2232,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'},
@@ -2267,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, _("\
@@ -2465,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 ++;
@@ -3286,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;
@@ -3722,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" : "",
@@ -4171,6 +4328,7 @@ dynamic_segment_parisc_val (entry)
       print_vma (entry->d_un.d_ptr, PREFIX_HEX);
       break;
     }
+  putchar ('\n');
 }
 
 static int
@@ -4521,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");
@@ -4547,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");
@@ -4578,6 +4740,7 @@ process_dynamic_segment (file)
              else
                {
                  unsigned long int val = entry->d_un.d_val;
+
                  if (val & DF_1_NOW)
                    {
                      printf (" NOW");
@@ -4735,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);
@@ -4781,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:
@@ -7199,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;
@@ -7211,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:
@@ -7287,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;
@@ -7392,7 +7581,6 @@ fetch_indirect_string (offset)
   return debug_str_contents + offset;
 }
 
-
 static int
 display_debug_str (section, start, file)
      Elf32_Internal_Shdr * section;
@@ -7453,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;
@@ -7582,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:
@@ -7807,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)
@@ -7820,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,
@@ -7841,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));
@@ -7852,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));
@@ -7860,7 +8050,7 @@ display_debug_info (section, start, file)
                    }
                }
 
-             compunit.cu_abbrev_offset += rp->r_addend;
+             compunit.cu_abbrev_offset = rp->r_addend;
              break;
            }
 
@@ -7887,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;
@@ -8220,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)
        {
@@ -8374,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;
@@ -8553,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);
@@ -9349,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;
@@ -9796,6 +10073,8 @@ process_file (file_name)
 
   process_corefile_contents (file);
 
+  process_gnu_liblist (file);
+
   process_arch_specific (file);
 
   fclose (file);