* readelf.c (get_segment_type): Display "GNU_STACK", not just
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 1c4e57dcb8579bfb7834e4a742c45788b9cec163..fbafd2bac39b95532659622d424ff3c34c2ace29 100644 (file)
@@ -1,5 +1,5 @@
 /* readelf.c -- display contents of an ELF format file
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
    Originally developed by Eric Youngdale <eric@andante.jic.com>
    Modifications by Nick Clifton <nickc@redhat.com>
@@ -119,6 +119,7 @@ long archive_file_offset;
 unsigned long archive_file_size;
 unsigned long dynamic_addr;
 bfd_size_type dynamic_size;
+unsigned int dynamic_nent;
 char *dynamic_strings;
 char *string_table;
 unsigned long string_table_length;
@@ -133,7 +134,7 @@ bfd_vma version_info[16];
 Elf_Internal_Ehdr elf_header;
 Elf_Internal_Shdr *section_headers;
 Elf_Internal_Phdr *program_headers;
-Elf_Internal_Dyn *dynamic_segment;
+Elf_Internal_Dyn *dynamic_section;
 Elf_Internal_Shdr *symtab_shndx_hdr;
 int show_name;
 int do_dynamic;
@@ -205,8 +206,6 @@ print_mode;
 static bfd_vma (*byte_get) (unsigned char *, int);
 static void (*byte_put) (unsigned char *, bfd_vma, int);
 
-typedef int Elf32_Word;
-
 #define UNKNOWN -1
 
 #define SECTION_NAME(X)        ((X) == NULL ? "<none>" : \
@@ -1009,10 +1008,10 @@ dump_relocations (FILE *file,
          rtype = elf_i386_reloc_type (type);
          break;
 
-        case EM_68HC11:
-        case EM_68HC12:
-          rtype = elf_m68hc11_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);
@@ -1072,9 +1071,9 @@ dump_relocations (FILE *file,
          rtype = elf_fr30_reloc_type (type);
          break;
 
-        case EM_CYGNUS_FRV:
-          rtype = elf_frv_reloc_type (type);
-          break;
+       case EM_CYGNUS_FRV:
+         rtype = elf_frv_reloc_type (type);
+         break;
 
        case EM_MCORE:
          rtype = elf_mcore_reloc_type (type);
@@ -1552,9 +1551,9 @@ get_file_type (unsigned e_type)
     {
     case ET_NONE:      return _("NONE (None)");
     case ET_REL:       return _("REL (Relocatable file)");
-    case ET_EXEC:       return _("EXEC (Executable file)");
-    case ET_DYN:        return _("DYN (Shared object file)");
-    case ET_CORE:       return _("CORE (Core file)");
+    case ET_EXEC:      return _("EXEC (Executable file)");
+    case ET_DYN:       return _("DYN (Shared object file)");
+    case ET_CORE:      return _("CORE (Core file)");
 
     default:
       if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
@@ -1829,6 +1828,10 @@ decode_ARM_machine_flags (unsigned e_flags, char buf[])
              strcat (buf, ", software FP");
              break;
 
+           case EF_ARM_VFP_FLOAT:
+             strcat (buf, ", VFP");
+             break;
+
            case EF_ARM_MAVERICK_FLOAT:
              strcat (buf, ", Maverick FP");
              break;
@@ -2188,7 +2191,7 @@ get_segment_type (unsigned long p_type)
 
     case PT_GNU_EH_FRAME:
                        return "GNU_EH_FRAME";
-    case PT_GNU_STACK: return "STACK";
+    case PT_GNU_STACK: return "GNU_STACK";
     case PT_GNU_RELRO:  return "GNU_RELRO";
 
     default:
@@ -2453,7 +2456,7 @@ usage (void)
   -n --notes             Display the core notes (if present)\n\
   -r --relocs            Display the relocations (if present)\n\
   -u --unwind            Display the unwind info (if present)\n\
-  -d --dynamic           Display the dynamic segment (if present)\n\
+  -d --dynamic           Display the dynamic section (if present)\n\
   -V --version-info      Display the version sections (if present)\n\
   -A --arch-specific     Display architecture specific information (if any).\n\
   -D --use-dynamic       Use the dynamic section info when displaying symbols\n\
@@ -3143,8 +3146,41 @@ process_program_headers (FILE *file)
          if (dynamic_addr)
            error (_("more than one dynamic segment\n"));
 
-         dynamic_addr = segment->p_offset;
-         dynamic_size = segment->p_filesz;
+         /* Try to locate the .dynamic section. If there is
+            a section header table, we can easily locate it.  */
+         if (section_headers != NULL)
+           {
+             Elf_Internal_Shdr *sec;
+             unsigned int j;
+
+             for (j = 0, sec = section_headers;
+                  j < elf_header.e_shnum;
+                  j++, sec++)
+               if (strcmp (SECTION_NAME (sec), ".dynamic") == 0)
+                 break;
+
+             if (j == elf_header.e_shnum || sec->sh_size == 0)
+               {
+                 error (_("no .dynamic section in the dynamic segment"));
+                 break;
+               }
+
+             dynamic_addr = sec->sh_offset;
+             dynamic_size = sec->sh_size;
+
+             if (dynamic_addr < segment->p_offset
+                 || dynamic_addr > segment->p_offset + segment->p_filesz)
+               warn (_("the .dynamic section is not contained within the dynamic segment"));
+             else if (dynamic_addr > segment->p_offset)
+               warn (_("the .dynamic section is not the first section in the dynamic segment."));
+           }
+         else
+           {
+             /* Otherwise, we can only assume that the .dynamic
+                section is the first section in the DYNAMIC segment.  */
+             dynamic_addr = segment->p_offset;
+             dynamic_size = segment->p_filesz;
+           }
          break;
 
        case PT_INTERP:
@@ -3822,7 +3858,7 @@ process_section_groups (FILE *file)
                  error (_("Bad sh_info in group section `%s'\n"), name);
                  continue;
                }
-             
+
              group_name = SECTION_NAME (section_headers + sec_index);
              strtab = NULL;
            }
@@ -3848,8 +3884,8 @@ process_section_groups (FILE *file)
          if (do_section_groups)
            {
              printf ("\n%s group section `%s' [%s] contains %u sections:\n",
-                     get_group_flags (entry), name, group_name, size); 
-             
+                     get_group_flags (entry), name, group_name, size);
+
              printf (_("   [Index]    Name\n"));
            }
 
@@ -3878,8 +3914,8 @@ process_section_groups (FILE *file)
                  sec = SECTION_HEADER (entry);
                  printf ("   [%5u]   %s\n",
                          entry, SECTION_NAME (sec));
-               } 
-             
+               }
+
              g = xmalloc (sizeof (struct group_list));
              g->section_index = entry;
              g->next = group->root;
@@ -4468,7 +4504,7 @@ process_unwind (FILE *file)
 }
 
 static void
-dynamic_segment_mips_val (Elf_Internal_Dyn *entry)
+dynamic_section_mips_val (Elf_Internal_Dyn *entry)
 {
   switch (entry->d_tag)
     {
@@ -4542,7 +4578,7 @@ dynamic_segment_mips_val (Elf_Internal_Dyn *entry)
 
 
 static void
-dynamic_segment_parisc_val (Elf_Internal_Dyn *entry)
+dynamic_section_parisc_val (Elf_Internal_Dyn *entry)
 {
   switch (entry->d_tag)
     {
@@ -4598,7 +4634,7 @@ dynamic_segment_parisc_val (Elf_Internal_Dyn *entry)
 }
 
 static void
-dynamic_segment_ia64_val (Elf_Internal_Dyn *entry)
+dynamic_section_ia64_val (Elf_Internal_Dyn *entry)
 {
   switch (entry->d_tag)
     {
@@ -4617,39 +4653,42 @@ dynamic_segment_ia64_val (Elf_Internal_Dyn *entry)
 }
 
 static int
-get_32bit_dynamic_segment (FILE *file)
+get_32bit_dynamic_section (FILE *file)
 {
-  Elf32_External_Dyn *edyn;
+  Elf32_External_Dyn *edyn, *ext;
   Elf_Internal_Dyn *entry;
-  bfd_size_type i;
 
   edyn = get_data (NULL, file, dynamic_addr, dynamic_size,
-                  _("dynamic segment"));
+                  _("dynamic section"));
   if (!edyn)
     return 0;
 
-  /* SGI's ELF has more than one section in the DYNAMIC segment.  Determine
-     how large this .dynamic is now.  We can do this even before the byte
-     swapping since the DT_NULL tag is recognizable.  */
-  dynamic_size = 0;
-  while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
-    ;
-
-  dynamic_segment = malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
+/* SGI's ELF has more than one section in the DYNAMIC segment, and we
+   might not have the luxury of section headers.  Look for the DT_NULL
+   terminator to determine the number of entries.  */
+  for (ext = edyn, dynamic_nent = 0;
+       (char *) ext < (char *) edyn + dynamic_size;
+       ext++)
+    {
+      dynamic_nent++;
+      if (BYTE_GET (ext->d_tag) == DT_NULL)
+       break;
+    }
 
-  if (dynamic_segment == NULL)
+  dynamic_section = malloc (dynamic_nent * sizeof (*entry));
+  if (dynamic_section == NULL)
     {
       error (_("Out of memory\n"));
       free (edyn);
       return 0;
     }
 
-  for (i = 0, entry = dynamic_segment;
-       i < dynamic_size;
-       i++, entry++)
+  for (ext = edyn, entry = dynamic_section;
+       entry < dynamic_section + dynamic_nent;
+       ext++, entry++)
     {
-      entry->d_tag      = BYTE_GET (edyn[i].d_tag);
-      entry->d_un.d_val = BYTE_GET (edyn[i].d_un.d_val);
+      entry->d_tag      = BYTE_GET (ext->d_tag);
+      entry->d_un.d_val = BYTE_GET (ext->d_un.d_val);
     }
 
   free (edyn);
@@ -4658,39 +4697,42 @@ get_32bit_dynamic_segment (FILE *file)
 }
 
 static int
-get_64bit_dynamic_segment (FILE *file)
+get_64bit_dynamic_section (FILE *file)
 {
-  Elf64_External_Dyn *edyn;
+  Elf64_External_Dyn *edyn, *ext;
   Elf_Internal_Dyn *entry;
-  bfd_size_type i;
 
   edyn = get_data (NULL, file, dynamic_addr, dynamic_size,
-                  _("dynamic segment"));
+                  _("dynamic section"));
   if (!edyn)
     return 0;
 
-  /* SGI's ELF has more than one section in the DYNAMIC segment.  Determine
-     how large this .dynamic is now.  We can do this even before the byte
-     swapping since the DT_NULL tag is recognizable.  */
-  dynamic_size = 0;
-  while (*(bfd_vma *) edyn[dynamic_size++].d_tag != DT_NULL)
-    ;
-
-  dynamic_segment = malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
+/* SGI's ELF has more than one section in the DYNAMIC segment, and we
+   might not have the luxury of section headers.  Look for the DT_NULL
+   terminator to determine the number of entries.  */
+  for (ext = edyn, dynamic_nent = 0;
+       (char *) ext < (char *) edyn + dynamic_size;
+       ext++)
+    {
+      dynamic_nent++;
+      if (BYTE_GET8 (ext->d_tag) == DT_NULL)
+       break;
+    }
 
-  if (dynamic_segment == NULL)
+  dynamic_section = malloc (dynamic_nent * sizeof (*entry));
+  if (dynamic_section == NULL)
     {
       error (_("Out of memory\n"));
       free (edyn);
       return 0;
     }
 
-  for (i = 0, entry = dynamic_segment;
-       i < dynamic_size;
-       i++, entry++)
+  for (ext = edyn, entry = dynamic_section;
+       entry < dynamic_section + dynamic_nent;
+       ext++, entry++)
     {
-      entry->d_tag      = BYTE_GET8 (edyn[i].d_tag);
-      entry->d_un.d_val = BYTE_GET8 (edyn[i].d_un.d_val);
+      entry->d_tag      = BYTE_GET8 (ext->d_tag);
+      entry->d_un.d_val = BYTE_GET8 (ext->d_un.d_val);
     }
 
   free (edyn);
@@ -4730,35 +4772,35 @@ get_dynamic_flags (bfd_vma flags)
   return buff;
 }
 
-/* Parse and display the contents of the dynamic segment.  */
+/* Parse and display the contents of the dynamic section.  */
+
 static int
-process_dynamic_segment (FILE *file)
+process_dynamic_section (FILE *file)
 {
   Elf_Internal_Dyn *entry;
-  bfd_size_type i;
 
   if (dynamic_size == 0)
     {
       if (do_dynamic)
-       printf (_("\nThere is no dynamic segment in this file.\n"));
+       printf (_("\nThere is no dynamic section in this file.\n"));
 
       return 1;
     }
 
   if (is_32bit_elf)
     {
-      if (! get_32bit_dynamic_segment (file))
+      if (! get_32bit_dynamic_section (file))
        return 0;
     }
-  else if (! get_64bit_dynamic_segment (file))
+  else if (! get_64bit_dynamic_section (file))
     return 0;
 
   /* Find the appropriate symbol table.  */
   if (dynamic_symbols == NULL)
     {
-      for (i = 0, entry = dynamic_segment;
-          i < dynamic_size;
-          ++i, ++entry)
+      for (entry = dynamic_section;
+          entry < dynamic_section + dynamic_nent;
+          ++entry)
        {
          Elf_Internal_Shdr section;
 
@@ -4802,9 +4844,9 @@ process_dynamic_segment (FILE *file)
   /* Similarly find a string table.  */
   if (dynamic_strings == NULL)
     {
-      for (i = 0, entry = dynamic_segment;
-          i < dynamic_size;
-          ++i, ++entry)
+      for (entry = dynamic_section;
+          entry < dynamic_section + dynamic_nent;
+          ++entry)
        {
          unsigned long offset;
          long str_tab_len;
@@ -4848,9 +4890,9 @@ process_dynamic_segment (FILE *file)
     {
       unsigned long syminsz = 0;
 
-      for (i = 0, entry = dynamic_segment;
-          i < dynamic_size;
-          ++i, ++entry)
+      for (entry = dynamic_section;
+          entry < dynamic_section + dynamic_nent;
+          ++entry)
        {
          if (entry->d_tag == DT_SYMINENT)
            {
@@ -4867,7 +4909,7 @@ process_dynamic_segment (FILE *file)
 
       if (dynamic_syminfo_offset != 0 && syminsz != 0)
        {
-         Elf_External_Syminfo *extsyminfo;
+         Elf_External_Syminfo *extsyminfo, *extsym;
          Elf_Internal_Syminfo *syminfo;
 
          /* There is a syminfo section.  Read the data.  */
@@ -4884,11 +4926,12 @@ process_dynamic_segment (FILE *file)
            }
 
          dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
-         for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
-              ++i, ++syminfo)
+         for (syminfo = dynamic_syminfo, extsym = extsyminfo;
+              syminfo < dynamic_syminfo + dynamic_syminfo_nent;
+              ++syminfo, ++extsym)
            {
-             syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
-             syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
+             syminfo->si_boundto = BYTE_GET (extsym->si_boundto);
+             syminfo->si_flags = BYTE_GET (extsym->si_flags);
            }
 
          free (extsyminfo);
@@ -4896,14 +4939,14 @@ process_dynamic_segment (FILE *file)
     }
 
   if (do_dynamic && dynamic_addr)
-    printf (_("\nDynamic segment at offset 0x%lx contains %ld entries:\n"),
-           dynamic_addr, (long) dynamic_size);
+    printf (_("\nDynamic section at offset 0x%lx contains %u entries:\n"),
+           dynamic_addr, dynamic_nent);
   if (do_dynamic)
     printf (_("  Tag        Type                         Name/Value\n"));
 
-  for (i = 0, entry = dynamic_segment;
-       i < dynamic_size;
-       i++, entry++)
+  for (entry = dynamic_section;
+       entry < dynamic_section + dynamic_nent;
+       entry++)
     {
       if (do_dynamic)
        {
@@ -5268,13 +5311,13 @@ process_dynamic_segment (FILE *file)
                {
                case EM_MIPS:
                case EM_MIPS_RS3_LE:
-                 dynamic_segment_mips_val (entry);
+                 dynamic_section_mips_val (entry);
                  break;
                case EM_PARISC:
-                 dynamic_segment_parisc_val (entry);
+                 dynamic_section_parisc_val (entry);
                  break;
                case EM_IA_64:
-                 dynamic_segment_ia64_val (entry);
+                 dynamic_section_ia64_val (entry);
                  break;
                default:
                  print_vma (entry->d_un.d_val, PREFIX_HEX);
@@ -6260,11 +6303,11 @@ process_syminfo (FILE *file ATTRIBUTE_UNUSED)
          break;
        default:
          if (dynamic_syminfo[i].si_boundto > 0
-             && dynamic_syminfo[i].si_boundto < dynamic_size)
+             && dynamic_syminfo[i].si_boundto < dynamic_nent)
            {
              print_symbol (10,
                            dynamic_strings
-                           + (dynamic_segment
+                           + (dynamic_section
                               [dynamic_syminfo[i].si_boundto].d_un.d_val));
              putchar (' ' );
            }
@@ -7083,9 +7126,9 @@ get_TAG_name (unsigned long tag)
     case DW_TAG_partial_unit:          return "DW_TAG_partial_unit";
     case DW_TAG_imported_unit:         return "DW_TAG_imported_unit";
       /* UPC values.  */
-    case DW_TAG_upc_shared_type:        return "DW_TAG_upc_shared_type";
-    case DW_TAG_upc_strict_type:        return "DW_TAG_upc_strict_type";
-    case DW_TAG_upc_relaxed_type:       return "DW_TAG_upc_relaxed_type";
+    case DW_TAG_upc_shared_type:       return "DW_TAG_upc_shared_type";
+    case DW_TAG_upc_strict_type:       return "DW_TAG_upc_strict_type";
+    case DW_TAG_upc_relaxed_type:      return "DW_TAG_upc_relaxed_type";
     default:
       {
        static char buffer[100];
@@ -8111,7 +8154,7 @@ read_and_display_attr_value (unsigned long attribute,
          data += offset_size;
        }
       else
-        {
+       {
          error (_("Internal error: DWARF version is not 2 or 3.\n"));
        }
       break;
@@ -8686,7 +8729,7 @@ display_debug_aranges (Elf_Internal_Shdr *section,
          initial_length_size = 12;
        }
       else
-        {
+       {
          offset_size = 4;
          initial_length_size = 4;
        }
@@ -8968,7 +9011,14 @@ display_debug_frames (Elf_Internal_Shdr *section,
            {
              fc->code_factor = LEB ();
              fc->data_factor = SLEB ();
-             fc->ra = byte_get (start, 1); start += 1;
+             if (version == 1)
+               {
+                 fc->ra = GET (1);
+               }
+             else
+               {
+                 fc->ra = LEB ();
+               }
              augmentation_data_len = LEB ();
              augmentation_data = start;
              start += augmentation_data_len;
@@ -8978,13 +9028,27 @@ display_debug_frames (Elf_Internal_Shdr *section,
              start += addr_size;
              fc->code_factor = LEB ();
              fc->data_factor = SLEB ();
-             fc->ra = byte_get (start, 1); start += 1;
+             if (version == 1)
+               {
+                 fc->ra = GET (1);
+               }
+             else
+               {
+                 fc->ra = LEB ();
+               }
            }
          else
            {
              fc->code_factor = LEB ();
              fc->data_factor = SLEB ();
-             fc->ra = byte_get (start, 1); start += 1;
+             if (version == 1)
+               {
+                 fc->ra = GET (1);
+               }
+             else
+               {
+                 fc->ra = LEB ();
+               }
            }
          cie = fc;
 
@@ -9109,7 +9173,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
              unsigned long i;
              printf ("  Augmentation data:    ");
              for (i = 0; i < augmentation_data_len; ++i)
-               printf (" %02x", augmentation_data[i]);
+               printf (" %02x", augmentation_data[i]);
              putchar ('\n');
              putchar ('\n');
            }
@@ -9139,7 +9203,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
                op &= 0xc0;
 
              /* Warning: if you add any more cases to this switch, be
-                sure to add them to the corresponding switch below.  */
+                sure to add them to the corresponding switch below.  */
              switch (op)
                {
                case DW_CFA_advance_loc:
@@ -9240,7 +9304,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
        }
 
       /* Now we know what registers are used, make a second pass over
-         the chunk, this time actually printing out the info.  */
+        the chunk, this time actually printing out the info.  */
 
       while (start < block_end)
        {
@@ -9679,11 +9743,11 @@ process_mips_specific (FILE *file)
   size_t conflicts_offset = 0;
 
   /* We have a lot of special sections.  Thanks SGI!  */
-  if (dynamic_segment == NULL)
+  if (dynamic_section == NULL)
     /* No information available.  */
     return 0;
 
-  for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
+  for (entry = dynamic_section; entry->d_tag != DT_NULL; ++entry)
     switch (entry->d_tag)
       {
       case DT_MIPS_LIBLIST:
@@ -10529,7 +10593,7 @@ process_object (char *file_name, FILE *file)
     }
 
   if (process_program_headers (file))
-    process_dynamic_segment (file);
+    process_dynamic_section (file);
 
   process_relocs (file);
 
This page took 0.034524 seconds and 4 git commands to generate.