(process_dynamic_segment): Read syminfo section if available.
authorUlrich Drepper <drepper@redhat.com>
Tue, 25 Aug 1998 23:47:11 +0000 (23:47 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 25 Aug 1998 23:47:11 +0000 (23:47 +0000)
(process_syminfo): New function.  Print syminfo information.
(process_file): Call process_syminfo and free syminfo data at the end.

binutils/readelf.c

index ba32e1ee3bef6fee11eaa67a925d4a3056da9cae..f656eeb093862c19b41b2796510a7d56fd788627 100644 (file)
@@ -73,6 +73,9 @@ unsigned int          rela_size;
 char *                 dynamic_strings;
 char *                 string_table;
 Elf_Internal_Sym *     dynamic_symbols;
+Elf_Internal_Syminfo * dynamic_syminfo;
+unsigned long int      dynamic_syminfo_offset;
+unsigned int           dynamic_syminfo_nent;
 char                   program_interpreter [64];
 int                    dynamic_info[DT_JMPREL + 1];
 int                    version_info[16];
@@ -1289,7 +1292,7 @@ process_program_headers (file)
       printf
        (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
       printf
-       (_("  Type        Offset  VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"));
+       (_("  Type        Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"));
     }
 
   loadaddr = -1;
@@ -1302,7 +1305,7 @@ process_program_headers (file)
       if (do_segments)
        {
          printf ("  %-11.11s ", get_segment_type (segment->p_type));
-         printf ("0x%5.5lx ", (unsigned long) segment->p_offset);
+         printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
          printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
          printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
          printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
@@ -1521,6 +1524,7 @@ process_section_headers (file)
      and dynamic string table.  */
   dynamic_symbols = NULL;
   dynamic_strings = NULL;
+  dynamic_syminfo = NULL;
   for (i = 0, section = section_headers;
        i < elf_header.e_shnum;
        i ++, section ++)
@@ -1697,26 +1701,70 @@ static void
 dynamic_segment_mips_val (entry)
      Elf_Internal_Dyn *entry;
 {
-  switch (entry->d_tag)
-    {
-    case DT_MIPS_LOCAL_GOTNO:
-    case DT_MIPS_CONFLICTNO:
-    case DT_MIPS_LIBLISTNO:
-    case DT_MIPS_SYMTABNO:
-    case DT_MIPS_UNREFEXTNO:
-    case DT_MIPS_HIPAGENO:
-    case DT_MIPS_DELTA_CLASS_NO:
-    case DT_MIPS_DELTA_INSTANCE_NO:
-    case DT_MIPS_DELTA_RELOC_NO:
-    case DT_MIPS_DELTA_SYM_NO:
-    case DT_MIPS_DELTA_CLASSSYM_NO:
-      if (do_dynamic)
+  if (do_dynamic)
+    switch (entry->d_tag)
+      {
+      case DT_MIPS_FLAGS:
+       if (entry->d_un.d_val == 0)
+         printf ("NONE\n");
+       else
+         {
+           static const char *opts[] =
+           {
+             "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
+             "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
+             "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
+             "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
+             "RLD_ORDER_SAFE"
+           };
+           unsigned int cnt;
+           int first = 1;
+           for (cnt = 0; cnt < sizeof (opts) / sizeof (opts[0]); ++cnt)
+             if (entry->d_un.d_val & (1 << cnt))
+               {
+                 printf ("%s%s", first ? "" : " ", opts[cnt]);
+                 first = 0;
+               }
+           puts ("");
+         }
+       break;
+
+      case DT_MIPS_IVERSION:
+       if (dynamic_strings != NULL)
+         printf ("Interface Version: %s\n",
+                 dynamic_strings + entry->d_un.d_val);
+       else
+         printf ("%#ld\n", (long) entry->d_un.d_ptr);
+       break;
+
+      case DT_MIPS_TIME_STAMP:
+       {
+         char timebuf[20];
+         time_t time = entry->d_un.d_val;
+         strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
+         printf ("Time Stamp: %s\n", timebuf);
+       }
+       break;
+
+      case DT_MIPS_RLD_VERSION:
+      case DT_MIPS_LOCAL_GOTNO:
+      case DT_MIPS_CONFLICTNO:
+      case DT_MIPS_LIBLISTNO:
+      case DT_MIPS_SYMTABNO:
+      case DT_MIPS_UNREFEXTNO:
+      case DT_MIPS_HIPAGENO:
+      case DT_MIPS_DELTA_CLASS_NO:
+      case DT_MIPS_DELTA_INSTANCE_NO:
+      case DT_MIPS_DELTA_RELOC_NO:
+      case DT_MIPS_DELTA_SYM_NO:
+      case DT_MIPS_DELTA_CLASSSYM_NO:
+      case DT_MIPS_COMPACT_SIZE:
        printf ("%#ld\n", (long) entry->d_un.d_ptr);
-      break;
-    default:
-      if (do_dynamic)
+       break;
+
+      default:
        printf ("%#lx\n", (long) entry->d_un.d_ptr);
-    }
+      }
 }
 
 /* Parse the dynamic segment */
@@ -1842,6 +1890,51 @@ process_dynamic_segment (file)
        }
     }
 
+  /* And find the syminfo section if available.  */
+  if (dynamic_syminfo == NULL)
+    {
+      unsigned int syminsz = 0;
+
+      for (i = 0, entry = dynamic_segment;
+          i < dynamic_size;
+          ++i, ++ entry)
+       {
+         if (entry->d_tag == DT_SYMINENT)
+           assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
+         else if (entry->d_tag == DT_SYMINSZ)
+           syminsz = entry->d_un.d_val;
+         else if (entry->d_tag == DT_SYMINFO)
+           dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
+       }
+
+      if (dynamic_syminfo_offset != 0 && syminsz != 0)
+       {
+         Elf_External_Syminfo *extsyminfo;
+         Elf_Internal_Syminfo *syminfo;
+
+         /* There is a syminfo section.  Read the data.  */
+         GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo,
+                         Elf_External_Syminfo *, "symbol information");
+
+         dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
+         if (dynamic_syminfo == NULL)
+           {
+             error (_("Out of memory\n"));
+             return 0;
+           }
+
+         dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
+         for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
+              ++i, ++syminfo)
+           {
+             syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
+             syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
+           }
+
+         free (extsyminfo);
+       }
+    }
+
   if (do_dynamic && dynamic_addr)
     printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
            dynamic_addr, dynamic_size);
@@ -2950,6 +3043,61 @@ process_symbol_table (file)
   return 1;
 }
 
+static int
+process_syminfo (file)
+     FILE * file;
+{
+  int i;
+
+  if (dynamic_syminfo == NULL
+      || !do_dynamic)
+    /* No syminfo, this is ok.  */
+    return 1;
+
+  /* There better should be a dynamic symbol section.  */
+  if (dynamic_symbols == NULL || dynamic_strings == NULL)
+    return 0;
+
+  if (dynamic_addr)
+    printf (_("\nDynamic info segment at offset 0x%x contains %d entries:\n"),
+           dynamic_syminfo_offset, dynamic_syminfo_nent);
+
+  printf (_(" Num: Name                                BoundTo Flags\n"));
+  for (i = 0; i < dynamic_syminfo_nent; ++i)
+    {
+      unsigned short int flags = dynamic_syminfo[i].si_flags;
+
+      printf ("%4d: %-35s ", i,
+             dynamic_strings + dynamic_symbols[i].st_name);
+
+      switch (dynamic_syminfo[i].si_boundto)
+       {
+       case SYMINFO_BT_SELF:
+         fputs ("SELF    ", stdout);
+         break;
+       case SYMINFO_BT_PARENT:
+         fputs ("PARENT  ", stdout);
+         break;
+       default:
+         printf ("%-7d ", dynamic_syminfo[i].si_boundto);
+         break;
+       }
+
+      if (flags & SYMINFO_FLG_DIRECT)
+       printf (" DIRECT");
+      if (flags & SYMINFO_FLG_PASSTHRU)
+       printf (" PASSTHRU");
+      if (flags & SYMINFO_FLG_COPY)
+       printf (" COPY");
+      if (flags & SYMINFO_FLG_LAZYLOAD)
+       printf (" LAZYLOAD");
+
+      puts ("");
+    }
+
+  return 1;
+}
+
 static int
 process_section_contents (file)
      FILE * file;
@@ -3116,14 +3264,14 @@ process_mips_specific (file)
                      elib, Elf32_External_Lib *, "liblist");
 
       printf ("\nSection '.liblist' contains %d entries:\n", liblistno);
-      fputs ("     Library              Time Stamp       Checksum   Version Flags\n",
+      fputs ("     Library              Time Stamp          Checksum   Version Flags\n",
             stdout);
 
       for (cnt = 0; cnt < liblistno; ++cnt)
        {
          Elf32_Lib liblist;
          time_t time;
-         char timebuf[17];
+         char timebuf[20];
 
          liblist.l_name = BYTE_GET (elib[cnt].l_name);
          time = BYTE_GET (elib[cnt].l_time_stamp);
@@ -3131,7 +3279,7 @@ process_mips_specific (file)
          liblist.l_version = BYTE_GET (elib[cnt].l_version);
          liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
 
-         strftime (timebuf, 17, "%Y-%m-%dT%H:%M", gmtime (&time));
+         strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
 
          printf ("%3d: %-20s %s %#10lx %-7ld %#lx\n", cnt,
                  dynamic_strings + liblist.l_name, timebuf,
@@ -3438,6 +3586,8 @@ process_file (file_name)
 
   process_symbol_table (file);
 
+  process_syminfo (file);
+
   process_version_sections (file);
 
   process_section_contents (file);
@@ -3469,6 +3619,12 @@ process_file (file_name)
       free (dynamic_symbols);
       dynamic_symbols = NULL;
     }
+
+  if (dynamic_syminfo)
+    {
+      free (dynamic_syminfo);
+      dynamic_syminfo = NULL;
+    }
 }
 
 #ifdef SUPPORT_DISASSEMBLY