]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
Add new Dutch translation.
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index ca996acf4cfbf11e7c4fd0b858e43cd1df2f193a..5780bfae1f705ba07c55e08fe18ef21082960b14 100644 (file)
@@ -1,5 +1,5 @@
 /* readelf.c -- display contents of an ELF format file
-   Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
    Originally developed by Eric Youngdale <eric@andante.jic.com>
    Modifications by Nick Clifton <nickc@redhat.com>
 #include "elf/mmix.h"
 #include "elf/mn10200.h"
 #include "elf/mn10300.h"
+#include "elf/msp430.h"
 #include "elf/or32.h"
 #include "elf/pj.h"
 #include "elf/ppc.h"
+#include "elf/ppc64.h"
 #include "elf/s390.h"
 #include "elf/sh.h"
 #include "elf/sparc.h"
 #include "elf/vax.h"
 #include "elf/x86-64.h"
 #include "elf/xstormy16.h"
+#include "elf/iq2000.h"
+#include "elf/xtensa.h"
 
 #include "bucomm.h"
 #include "getopt.h"
+#include "libiberty.h"
 
 char *program_name = "readelf";
-unsigned int dynamic_addr;
+unsigned long dynamic_addr;
 bfd_size_type dynamic_size;
-unsigned int rela_addr;
-unsigned int rela_size;
 char *dynamic_strings;
 char *string_table;
 unsigned long string_table_length;
@@ -103,11 +106,11 @@ Elf_Internal_Syminfo *dynamic_syminfo;
 unsigned long dynamic_syminfo_offset;
 unsigned int dynamic_syminfo_nent;
 char program_interpreter[64];
-int dynamic_info[DT_JMPREL + 1];
-int version_info[16];
-int loadaddr = 0;
+bfd_vma dynamic_info[DT_JMPREL + 1];
+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_Shdr *symtab_shndx_hdr;
 int show_name;
@@ -160,222 +163,238 @@ typedef enum print_mode
 print_mode;
 
 /* Forward declarations for dumb compilers.  */
-static void print_vma               
+static void print_vma
   PARAMS ((bfd_vma, print_mode));
-static void print_symbol                    
+static void print_symbol
   PARAMS ((int, const char *));
-static bfd_vma (*byte_get)                  
+static bfd_vma (*byte_get)
   PARAMS ((unsigned char *, int));
-static bfd_vma byte_get_little_endian     
+static bfd_vma byte_get_little_endian
   PARAMS ((unsigned char *, int));
-static bfd_vma byte_get_big_endian        
+static bfd_vma byte_get_big_endian
   PARAMS ((unsigned char *, int));
-static const char *get_mips_dynamic_type      
+static bfd_vma byte_get_signed
+  PARAMS ((unsigned char *, int));
+static void (*byte_put)
+  PARAMS ((unsigned char *, bfd_vma, int));
+static void byte_put_little_endian
+  PARAMS ((unsigned char *, bfd_vma, int));
+static void byte_put_big_endian
+  PARAMS ((unsigned char *, bfd_vma, int));
+static const char *get_mips_dynamic_type
+  PARAMS ((unsigned long));
+static const char *get_sparc64_dynamic_type
   PARAMS ((unsigned long));
-static const char *get_sparc64_dynamic_type   
+static const char *get_ppc64_dynamic_type
   PARAMS ((unsigned long));
-static const char *get_ppc64_dynamic_type     
+static const char *get_parisc_dynamic_type
   PARAMS ((unsigned long));
-static const char *get_parisc_dynamic_type    
+static const char *get_ia64_dynamic_type
   PARAMS ((unsigned long));
-static const char *get_dynamic_type           
+static const char *get_dynamic_type
   PARAMS ((unsigned long));
-static int slurp_rela_relocs        
+static int slurp_rela_relocs
   PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **,
           unsigned long *));
-static int slurp_rel_relocs         
+static int slurp_rel_relocs
   PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **,
           unsigned long *));
-static int dump_relocations           
+static int dump_relocations
   PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *,
           unsigned long, char *, int));
-static char *get_file_type              
+static char *get_file_type
   PARAMS ((unsigned));
-static char *get_machine_name           
+static char *get_machine_name
   PARAMS ((unsigned));
-static void decode_ARM_machine_flags   
+static void decode_ARM_machine_flags
   PARAMS ((unsigned, char[]));
-static char *get_machine_flags          
+static char *get_machine_flags
   PARAMS ((unsigned, unsigned));
-static const char *get_mips_segment_type      
+static const char *get_mips_segment_type
   PARAMS ((unsigned long));
-static const char *get_parisc_segment_type    
+static const char *get_parisc_segment_type
   PARAMS ((unsigned long));
-static const char *get_ia64_segment_type      
+static const char *get_ia64_segment_type
   PARAMS ((unsigned long));
-static const char *get_segment_type           
+static const char *get_segment_type
   PARAMS ((unsigned long));
-static const char *get_mips_section_type_name 
+static const char *get_mips_section_type_name
   PARAMS ((unsigned int));
 static const char *get_parisc_section_type_name
   PARAMS ((unsigned int));
-static const char *get_ia64_section_type_name 
+static const char *get_ia64_section_type_name
   PARAMS ((unsigned int));
-static const char *get_section_type_name      
+static const char *get_section_type_name
   PARAMS ((unsigned int));
-static const char *get_symbol_binding         
+static const char *get_symbol_binding
   PARAMS ((unsigned int));
-static const char *get_symbol_type            
+static const char *get_symbol_type
   PARAMS ((unsigned int));
-static const char *get_symbol_visibility      
+static const char *get_symbol_visibility
   PARAMS ((unsigned int));
-static const char *get_symbol_index_type      
+static const char *get_symbol_index_type
   PARAMS ((unsigned int));
-static const char *get_dynamic_flags        
+static const char *get_dynamic_flags
   PARAMS ((bfd_vma));
-static void usage                      
+static void usage
   PARAMS ((void));
-static void parse_args                 
+static void parse_args
   PARAMS ((int, char **));
-static int process_file_header        
+static int process_file_header
   PARAMS ((void));
-static int process_program_headers    
+static int process_program_headers
   PARAMS ((FILE *));
-static int process_section_headers    
+static int process_section_headers
   PARAMS ((FILE *));
-static int process_unwind           
+static int process_unwind
   PARAMS ((FILE *));
-static void dynamic_segment_mips_val   
+static void dynamic_segment_mips_val
+  PARAMS ((Elf_Internal_Dyn *));
+static void dynamic_segment_parisc_val
   PARAMS ((Elf_Internal_Dyn *));
-static void dynamic_segment_parisc_val 
+static void dynamic_segment_ia64_val
   PARAMS ((Elf_Internal_Dyn *));
-static int process_dynamic_segment    
+static int process_dynamic_segment
   PARAMS ((FILE *));
-static int process_symbol_table       
+static int process_symbol_table
   PARAMS ((FILE *));
-static int process_syminfo            
+static int process_syminfo
   PARAMS ((FILE *));
-static int process_section_contents   
+static int process_section_contents
   PARAMS ((FILE *));
-static void process_mips_fpe_exception 
+static void process_mips_fpe_exception
   PARAMS ((int));
-static int process_mips_specific      
+static int process_mips_specific
   PARAMS ((FILE *));
-static int process_file               
+static int process_file
   PARAMS ((char *));
-static int process_relocs             
+static int process_relocs
   PARAMS ((FILE *));
-static int process_version_sections   
+static int process_version_sections
   PARAMS ((FILE *));
-static char *get_ver_flags              
+static char *get_ver_flags
   PARAMS ((unsigned int));
-static int get_32bit_section_headers  
+static int get_32bit_section_headers
   PARAMS ((FILE *, unsigned int));
-static int get_64bit_section_headers  
+static int get_64bit_section_headers
   PARAMS ((FILE *, unsigned int));
-static int get_32bit_program_headers  
+static int get_32bit_program_headers
   PARAMS ((FILE *, Elf_Internal_Phdr *));
-static int get_64bit_program_headers  
+static int get_64bit_program_headers
   PARAMS ((FILE *, Elf_Internal_Phdr *));
-static int get_file_header            
+static int get_program_headers
   PARAMS ((FILE *));
-static Elf_Internal_Sym *get_32bit_elf_symbols      
+static int get_file_header
+  PARAMS ((FILE *));
+static Elf_Internal_Sym *get_32bit_elf_symbols
   PARAMS ((FILE *, Elf_Internal_Shdr *));
-static Elf_Internal_Sym *get_64bit_elf_symbols      
+static Elf_Internal_Sym *get_64bit_elf_symbols
   PARAMS ((FILE *, Elf_Internal_Shdr *));
-static const char *get_elf_section_flags            
+static const char *get_elf_section_flags
   PARAMS ((bfd_vma));
-static int *get_dynamic_data           
+static int *get_dynamic_data
   PARAMS ((FILE *, unsigned int));
-static int get_32bit_dynamic_segment  
+static int get_32bit_dynamic_segment
   PARAMS ((FILE *));
-static int get_64bit_dynamic_segment  
+static int get_64bit_dynamic_segment
   PARAMS ((FILE *));
+static long offset_from_vma
+  PARAMS ((FILE *, bfd_vma vma, bfd_size_type size));
 #ifdef SUPPORT_DISASSEMBLY
-static int disassemble_section        
+static int disassemble_section
   PARAMS ((Elf_Internal_Shdr *, FILE *));
 #endif
-static int dump_section               
+static int dump_section
   PARAMS ((Elf_Internal_Shdr *, FILE *));
-static int display_debug_section      
+static int display_debug_section
   PARAMS ((Elf_Internal_Shdr *, FILE *));
-static int display_debug_info         
+static int display_debug_info
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
 static int display_debug_not_supported
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int prescan_debug_info         
+static int prescan_debug_info
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_lines        
+static int display_debug_lines
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_pubnames     
+static int display_debug_pubnames
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_abbrev       
+static int display_debug_abbrev
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_aranges      
+static int display_debug_aranges
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_frames       
+static int display_debug_frames
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_macinfo      
+static int display_debug_macinfo
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_str          
+static int display_debug_str
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_loc          
+static int display_debug_loc
   PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static unsigned char *process_abbrev_section     
+static unsigned char *process_abbrev_section
   PARAMS ((unsigned char *, unsigned char *));
-static void load_debug_str             
+static void load_debug_str
   PARAMS ((FILE *));
-static void free_debug_str             
+static void free_debug_str
   PARAMS ((void));
-static const char *fetch_indirect_string      
+static const char *fetch_indirect_string
   PARAMS ((unsigned long));
-static void load_debug_loc             
+static void load_debug_loc
   PARAMS ((FILE *));
-static void free_debug_loc             
+static void free_debug_loc
   PARAMS ((void));
-static unsigned long read_leb128                
+static unsigned long read_leb128
   PARAMS ((unsigned char *, int *, int));
-static int process_extended_line_op   
+static int process_extended_line_op
   PARAMS ((unsigned char *, int, int));
-static void reset_state_machine        
+static void reset_state_machine
   PARAMS ((int));
-static char *get_TAG_name               
+static char *get_TAG_name
   PARAMS ((unsigned long));
-static char *get_AT_name                
+static char *get_AT_name
   PARAMS ((unsigned long));
-static char *get_FORM_name              
+static char *get_FORM_name
   PARAMS ((unsigned long));
-static void free_abbrevs               
+static void free_abbrevs
   PARAMS ((void));
-static void add_abbrev                 
+static void add_abbrev
   PARAMS ((unsigned long, unsigned long, int));
-static void add_abbrev_attr            
+static void add_abbrev_attr
   PARAMS ((unsigned long, unsigned long));
-static unsigned char *read_and_display_attr      
+static unsigned char *read_and_display_attr
   PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long,
-          unsigned long));
+          unsigned long, unsigned long, int));
 static unsigned char *read_and_display_attr_value
   PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long,
-          unsigned long));
-static unsigned char *display_block              
+          unsigned long, unsigned long, int));
+static unsigned char *display_block
   PARAMS ((unsigned char *, unsigned long));
-static void decode_location_expression 
+static void decode_location_expression
   PARAMS ((unsigned char *, unsigned int, unsigned long));
-static void request_dump               
+static void request_dump
   PARAMS ((unsigned int, int));
-static const char *get_elf_class              
+static const char *get_elf_class
   PARAMS ((unsigned int));
-static const char *get_data_encoding          
+static const char *get_data_encoding
   PARAMS ((unsigned int));
-static const char *get_osabi_name             
+static const char *get_osabi_name
   PARAMS ((unsigned int));
-static int guess_is_rela              
+static int guess_is_rela
   PARAMS ((unsigned long));
-static const char *get_note_type                       
+static const char *get_note_type
   PARAMS ((unsigned int));
-static const char *get_netbsd_elfcore_note_type  
+static const char *get_netbsd_elfcore_note_type
   PARAMS ((unsigned int));
-static int process_note                        
+static int process_note
   PARAMS ((Elf_Internal_Note *));
-static int process_corefile_note_segment 
+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   
+static int process_corefile_contents
   PARAMS ((FILE *));
-static int process_arch_specific               
+static int process_arch_specific
   PARAMS ((FILE *));
-static int process_gnu_liblist         
+static int process_gnu_liblist
   PARAMS ((FILE *));
 
 typedef int Elf32_Word;
@@ -402,7 +421,7 @@ typedef int Elf32_Word;
 
 #define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I))
 
-#define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order!  */
 
 #define BYTE_GET(field)        byte_get (field, sizeof (field))
 
@@ -466,7 +485,7 @@ get_data (var, file, offset, size, reason)
 
   if (fseek (file, offset, SEEK_SET))
     {
-      error (_("Unable to seek to %x for %s\n"), offset, reason);
+      error (_("Unable to seek to 0x%x for %s\n"), offset, reason);
       return NULL;
     }
 
@@ -477,7 +496,7 @@ get_data (var, file, offset, size, reason)
 
       if (mvar == NULL)
        {
-         error (_("Out of memory allocating %d bytes for %s\n"),
+         error (_("Out of memory allocating 0x%x bytes for %s\n"),
                 size, reason);
          return NULL;
        }
@@ -485,7 +504,7 @@ get_data (var, file, offset, size, reason)
 
   if (fread (mvar, size, 1, file) != 1)
     {
-      error (_("Unable to read in %d bytes of %s\n"), size, reason);
+      error (_("Unable to read in 0x%x bytes of %s\n"), size, reason);
       if (mvar != var)
        free (mvar);
       return NULL;
@@ -543,6 +562,60 @@ byte_get_little_endian (field, size)
     }
 }
 
+static bfd_vma
+byte_get_signed (field, size)
+     unsigned char *field;
+     int size;
+{
+  bfd_vma x = byte_get (field, size);
+
+  switch (size)
+    {
+    case 1:
+      return (x ^ 0x80) - 0x80;
+    case 2:
+      return (x ^ 0x8000) - 0x8000;
+    case 4:
+      return (x ^ 0x80000000) - 0x80000000;
+    case 8:
+    case -8:
+      return x;
+    default:
+      abort ();
+    }
+}
+
+static void
+byte_put_little_endian (field, value, size)
+     unsigned char * field;
+     bfd_vma        value;
+     int             size;
+{
+  switch (size)
+    {
+    case 8:
+      field[7] = (((value >> 24) >> 24) >> 8) & 0xff;
+      field[6] = ((value >> 24) >> 24) & 0xff;
+      field[5] = ((value >> 24) >> 16) & 0xff;
+      field[4] = ((value >> 24) >> 8) & 0xff;
+      /* Fall through.  */
+    case 4:
+      field[3] = (value >> 24) & 0xff;
+      field[2] = (value >> 16) & 0xff;
+      /* Fall through.  */
+    case 2:
+      field[1] = (value >> 8) & 0xff;
+      /* Fall through.  */
+    case 1:
+      field[0] = value & 0xff;
+      break;
+
+    default:
+      error (_("Unhandled data length: %d\n"), size);
+      abort ();
+    }
+}
+
 /* Print a VMA value.  */
 static void
 print_vma (vma, mode)
@@ -555,13 +628,34 @@ print_vma (vma, mode)
     {
       switch (mode)
        {
-       case FULL_HEX: printf ("0x"); /* drop through */
-       case LONG_HEX: printf ("%8.8lx", (unsigned long) vma); break;
-       case PREFIX_HEX: printf ("0x"); /* drop through */
-       case HEX: printf ("%lx", (unsigned long) vma); break;
-       case DEC: printf ("%ld", (unsigned long) vma); break;
-       case DEC_5: printf ("%5ld", (long) vma); break;
-       case UNSIGNED: printf ("%lu", (unsigned long) vma); break;
+       case FULL_HEX:
+         printf ("0x");
+         /* Drop through.  */
+       case LONG_HEX:
+         printf ("%8.8lx", (unsigned long) vma);
+         break;
+
+       case DEC_5:
+         if (vma <= 99999)
+           {
+             printf ("%5ld", (long) vma);
+             break;
+           }
+         /* Drop through.  */
+       case PREFIX_HEX:
+         printf ("0x");
+         /* Drop through.  */
+       case HEX:
+         printf ("%lx", (unsigned long) vma);
+         break;
+
+       case DEC:
+         printf ("%ld", (unsigned long) vma);
+         break;
+
+       case UNSIGNED:
+         printf ("%lu", (unsigned long) vma);
+         break;
        }
     }
 #ifdef BFD64
@@ -571,7 +665,7 @@ print_vma (vma, mode)
        {
        case FULL_HEX:
          printf ("0x");
-         /* drop through */
+         /* Drop through.  */
 
        case LONG_HEX:
          printf_vma (vma);
@@ -579,7 +673,7 @@ print_vma (vma, mode)
 
        case PREFIX_HEX:
          printf ("0x");
-         /* drop through */
+         /* Drop through.  */
 
        case HEX:
 #if BFD_HOST_64BIT_LONG
@@ -606,13 +700,18 @@ print_vma (vma, mode)
 
        case DEC_5:
 #if BFD_HOST_64BIT_LONG
-         printf ("%5ld", vma);
+         if (vma <= 99999)
+           printf ("%5ld", vma);
+         else
+           printf ("%#lx", vma);
 #else
          if (_bfd_int64_high (vma))
            /* ugg */
            printf ("++%ld", _bfd_int64_low (vma));
-         else
+         else if (vma <= 99999)
            printf ("%5ld", _bfd_int64_low (vma));
+         else
+           printf ("%#lx", _bfd_int64_low (vma));
 #endif
          break;
 
@@ -701,6 +800,41 @@ byte_get_big_endian (field, size)
     }
 }
 
+static void
+byte_put_big_endian (field, value, size)
+     unsigned char * field;
+     bfd_vma        value;
+     int             size;
+{
+  switch (size)
+    {
+    case 8:
+      field[7] = value & 0xff;
+      field[6] = (value >> 8) & 0xff;
+      field[5] = (value >> 16) & 0xff;
+      field[4] = (value >> 24) & 0xff;
+      value >>= 16;
+      value >>= 16;
+      /* Fall through.  */
+    case 4:
+      field[3] = value & 0xff;
+      field[2] = (value >> 8) & 0xff;
+      value >>= 16;
+      /* Fall through.  */
+    case 2:
+      field[1] = value & 0xff;
+      value >>= 8;
+      /* Fall through.  */
+    case 1:
+      field[0] = value & 0xff;
+      break;
+
+    default:
+      error (_("Unhandled data length: %d\n"), size);
+      abort ();
+    }
+}
+
 /* Guess the relocation size commonly used by the specific machines.  */
 
 static int
@@ -758,10 +892,15 @@ guess_is_rela (e_machine)
     case EM_S390:
     case EM_S390_OLD:
     case EM_MMIX:
+    case EM_MSP430:
+    case EM_MSP430_OLD:
     case EM_XSTORMY16:
     case EM_VAX:
     case EM_IP2K:
     case EM_IP2K_OLD:
+    case EM_IQ2000:
+    case EM_XTENSA:
+    case EM_XTENSA_OLD:
       return TRUE;
 
     case EM_MMA:
@@ -936,6 +1075,7 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
 }
 
 /* Display the contents of the relocation data found at the specified offset.  */
+
 static int
 dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
      FILE *file;
@@ -986,14 +1126,14 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
       if (is_rela)
        {
          if (do_wide)
-           printf (_("    Offset             Info            Type               Symbol's Value  Symbol's Name + Addend\n"));
+           printf (_("    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend\n"));
          else
            printf (_("  Offset          Info           Type           Sym. Value    Sym. Name + Addend\n"));
        }
       else
        {
          if (do_wide)
-           printf (_("    Offset             Info            Type               Symbol's Value  Symbol's Name\n"));
+           printf (_("    Offset             Info             Type               Symbol's Value  Symbol's Name\n"));
          else
            printf (_("  Offset          Info           Type           Sym. Value    Sym. Name\n"));
        }
@@ -1021,8 +1161,22 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        }
       else
        {
+         /* The #ifdef BFD64 below is to prevent a compile time warning.
+            We know that if we do not have a 64 bit data type that we
+            will never execute this code anyway.  */
+#ifdef BFD64
          if (elf_header.e_machine == EM_MIPS)
            {
+             /* In little-endian objects, r_info isn't really a 64-bit
+                little-endian value: it has a 32-bit little-endian
+                symbol index followed by four individual byte fields.
+                Reorder INFO accordingly.  */
+             if (elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+               info = (((info & 0xffffffff) << 32)
+                       | ((info >> 56) & 0xff)
+                       | ((info >> 40) & 0xff00)
+                       | ((info >> 24) & 0xff0000)
+                       | ((info >> 8) & 0xff000000));
              type  = ELF64_MIPS_R_TYPE (info);
              type2 = ELF64_MIPS_R_TYPE2 (info);
              type3 = ELF64_MIPS_R_TYPE3 (info);
@@ -1031,10 +1185,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
            type = ELF64_R_TYPE_ID (info);
          else
            type = ELF64_R_TYPE (info);
-         /* The #ifdef BFD64 below is to prevent a compile time warning.
-            We know that if we do not have a 64 bit data type that we
-            will never execute this code anyway.  */
-#ifdef BFD64
+
          symtab_index = ELF64_R_SYM  (info);
 #endif
        }
@@ -1156,11 +1307,19 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_mmix_reloc_type (type);
          break;
 
+       case EM_MSP430:
+       case EM_MSP430_OLD:
+         rtype = elf_msp430_reloc_type (type);
+         break;
+
        case EM_PPC:
-       case EM_PPC64:
          rtype = elf_ppc_reloc_type (type);
          break;
 
+       case EM_PPC64:
+         rtype = elf_ppc64_reloc_type (type);
+         break;
+
        case EM_MIPS:
        case EM_MIPS_RS3_LE:
          rtype = elf_mips_reloc_type (type);
@@ -1239,6 +1398,15 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        case EM_IP2K_OLD:
          rtype = elf_ip2k_reloc_type (type);
          break;
+
+       case EM_IQ2000:
+         rtype = elf_iq2000_reloc_type (type);
+         break;
+
+       case EM_XTENSA_OLD:
+       case EM_XTENSA:
+         rtype = elf_xtensa_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1248,7 +1416,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        printf (_("unrecognized: %-7lx"), type);
 #endif
       else
-       printf (do_wide ? "%-21.21s" : "%-17.17s", rtype);
+       printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
 
       if (symtab_index)
        {
@@ -1452,6 +1620,18 @@ get_parisc_dynamic_type (type)
     }
 }
 
+static const char *
+get_ia64_dynamic_type (type)
+     unsigned long type;
+{
+  switch (type)
+    {
+    case DT_IA_64_PLT_RESERVE: return "IA_64_PLT_RESERVE";
+    default:
+      return NULL;
+    }
+}
+
 static const char *
 get_dynamic_type (type)
      unsigned long type;
@@ -1549,6 +1729,9 @@ get_dynamic_type (type)
            case EM_PPC64:
              result = get_ppc64_dynamic_type (type);
              break;
+           case EM_IA_64:
+             result = get_ia64_dynamic_type (type);
+             break;
            default:
              result = NULL;
              break;
@@ -1642,14 +1825,14 @@ get_machine_name (e_machine)
     case EM_MCORE:             return "MCORE";
     case EM_ARM:               return "ARM";
     case EM_OLD_ALPHA:         return "Digital Alpha (old)";
-    case EM_SH:                        return "Hitachi SH";
+    case EM_SH:                        return "Renesas / SuperH SH";
     case EM_SPARCV9:           return "Sparc v9";
     case EM_TRICORE:           return "Siemens Tricore";
     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";
-    case EM_H8_500:            return "Hitachi H8/500";
+    case EM_H8_300:            return "Renesas H8/300";
+    case EM_H8_300H:           return "Renesas H8/300H";
+    case EM_H8S:               return "Renesas H8S";
+    case EM_H8_500:            return "Renesas H8/500";
     case EM_IA_64:             return "Intel IA-64";
     case EM_MIPS_X:            return "Stanford MIPS-X";
     case EM_COLDFIRE:          return "Motorola Coldfire";
@@ -1660,7 +1843,7 @@ get_machine_name (e_machine)
     case EM_CYGNUS_D30V:
     case EM_D30V:              return "d30v";
     case EM_CYGNUS_M32R:
-    case EM_M32R:              return "Mitsubishi M32r";
+    case EM_M32R:              return "Renesas M32R (formerly Mitsubishi M32r)";
     case EM_CYGNUS_V850:
     case EM_V850:              return "NEC v850";
     case EM_CYGNUS_MN10300:
@@ -1698,7 +1881,7 @@ get_machine_name (e_machine)
     case EM_ZSP:               return "LSI Logic's 16-bit DSP processor";
     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_PRISM:             return "Vitesse Prism";
     case EM_X86_64:            return "Advanced Micro Devices X86-64";
     case EM_S390_OLD:
     case EM_S390:              return "IBM S/390";
@@ -1708,6 +1891,9 @@ get_machine_name (e_machine)
     case EM_DLX:               return "OpenDLX";
     case EM_IP2K_OLD:
     case EM_IP2K:              return "Ubicom IP2xxx 8-bit microcontrollers";
+    case EM_IQ2000:            return "Vitesse IQ2000";
+    case EM_XTENSA_OLD:
+    case EM_XTENSA:            return "Tensilica Xtensa Processor";
     default:
       sprintf (buff, _("<unknown>: %x"), e_machine);
       return buff;
@@ -1845,6 +2031,10 @@ decode_ARM_machine_flags (e_flags, buf)
              strcat (buf, ", software FP");
              break;
 
+           case EF_ARM_MAVERICK_FLOAT:
+             strcat (buf, ", Maverick FP");
+             break;
+
            default:
              unknown = 1;
              break;
@@ -1988,6 +2178,7 @@ get_machine_flags (e_flags, e_machine)
            case E_MIPS_ARCH_4: strcat (buf, ", mips4"); break;
            case E_MIPS_ARCH_5: strcat (buf, ", mips5"); break;
            case E_MIPS_ARCH_32: strcat (buf, ", mips32"); break;
+           case E_MIPS_ARCH_32R2: strcat (buf, ", mips32r2"); break;
            case E_MIPS_ARCH_64: strcat (buf, ", mips64"); break;
            default: strcat (buf, ", unknown ISA"); break;
            }
@@ -2171,6 +2362,7 @@ get_segment_type (p_type)
 
     case PT_GNU_EH_FRAME:
                        return "GNU_EH_FRAME";
+    case PT_GNU_STACK: return "STACK";
 
     default:
       if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
@@ -2298,10 +2490,15 @@ static const char *
 get_ia64_section_type_name (sh_type)
      unsigned int sh_type;
 {
+  /* If the top 8 bits are 0x78 the next 8 are the os/abi ID. */
+  if ((sh_type & 0xFF000000) == SHT_IA_64_LOPSREG)
+    return get_osabi_name ((sh_type & 0x00FF0000) >> 16);
+      
   switch (sh_type)
     {
-    case SHT_IA_64_EXT:                return "IA_64_EXT";
-    case SHT_IA_64_UNWIND:     return "IA_64_UNWIND";
+    case SHT_IA_64_EXT:                  return "IA_64_EXT";
+    case SHT_IA_64_UNWIND:       return "IA_64_UNWIND";
+    case SHT_IA_64_PRIORITY_INIT: return "IA_64_PRIORITY_INIT";
     default:
       break;
     }
@@ -2496,7 +2693,7 @@ parse_args (argc, argv)
     usage ();
 
   while ((c = getopt_long
-         (argc, argv, "ersuahnldSDAIw::x:i:vVW", options, NULL)) != EOF)
+         (argc, argv, "ersuahnldSDAIw::x:i:vVWH", options, NULL)) != EOF)
     {
       char *cp;
       int section;
@@ -2812,6 +3009,9 @@ get_osabi_name (osabi)
     case ELFOSABI_TRU64:       return "UNIX - TRU64";
     case ELFOSABI_MODESTO:     return "Novell - Modesto";
     case ELFOSABI_OPENBSD:     return "UNIX - OpenBSD";
+    case ELFOSABI_OPENVMS:     return "VMS - OpenVMS";
+    case ELFOSABI_NSK:         return "HP - Non-Stop Kernel";
+    case ELFOSABI_AROS:                return "Amiga Research OS";
     case ELFOSABI_STANDALONE:  return _("Standalone App");
     case ELFOSABI_ARM:         return "ARM";
     default:
@@ -2821,6 +3021,7 @@ get_osabi_name (osabi)
 }
 
 /* Decode the data held in 'elf_header'.  */
+
 static int
 process_file_header ()
 {
@@ -2982,13 +3183,45 @@ get_64bit_program_headers (file, program_headers)
   return 1;
 }
 
+/* Returns 1 if the program headers were read into `program_headers'.  */
+
+static int
+get_program_headers (file)
+     FILE *file;
+{
+  Elf_Internal_Phdr *phdrs;
+
+  /* Check cache of prior read.  */
+  if (program_headers != NULL)
+    return 1;
+
+  phdrs = (Elf_Internal_Phdr *) malloc
+    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+
+  if (phdrs == NULL)
+    {
+      error (_("Out of memory\n"));
+      return 0;
+    }
+
+  if (is_32bit_elf
+      ? get_32bit_program_headers (file, phdrs)
+      : get_64bit_program_headers (file, phdrs))
+    {
+      program_headers = phdrs;
+      return 1;
+    }
+
+  free (phdrs);
+  return 0;
+}
+
 /* Returns 1 if the program headers were loaded.  */
 
 static int
 process_program_headers (file)
      FILE *file;
 {
-  Elf_Internal_Phdr *program_headers;
   Elf_Internal_Phdr *segment;
   unsigned int i;
 
@@ -3010,25 +3243,8 @@ process_program_headers (file)
       printf ("\n");
     }
 
-  program_headers = (Elf_Internal_Phdr *) malloc
-    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
-  if (program_headers == NULL)
-    {
-      error (_("Out of memory\n"));
+  if (! get_program_headers (file))
       return 0;
-    }
-
-  if (is_32bit_elf)
-    i = get_32bit_program_headers (file, program_headers);
-  else
-    i = get_64bit_program_headers (file, program_headers);
-
-  if (i == 0)
-    {
-      free (program_headers);
-      return 0;
-    }
 
   if (do_segments)
     {
@@ -3052,7 +3268,6 @@ process_program_headers (file)
        }
     }
 
-  loadaddr = -1;
   dynamic_addr = 0;
   dynamic_size = 0;
 
@@ -3140,12 +3355,6 @@ process_program_headers (file)
 
       switch (segment->p_type)
        {
-       case PT_LOAD:
-         if (loadaddr == -1)
-           loadaddr = (segment->p_vaddr & 0xfffff000)
-             - (segment->p_offset & 0xfffff000);
-         break;
-
        case PT_DYNAMIC:
          if (dynamic_addr)
            error (_("more than one dynamic segment\n"));
@@ -3173,12 +3382,6 @@ process_program_headers (file)
        putc ('\n', stdout);
     }
 
-  if (loadaddr == -1)
-    {
-      /* Very strange.  */
-      loadaddr = 0;
-    }
-
   if (do_segments && section_headers != NULL)
     {
       printf (_("\n Section to Segment mapping:\n"));
@@ -3215,12 +3418,44 @@ process_program_headers (file)
        }
     }
 
-  free (program_headers);
-
   return 1;
 }
 
 
+/* Find the file offset corresponding to VMA by using the program headers.  */
+
+static long
+offset_from_vma (file, vma, size)
+     FILE *file;
+     bfd_vma vma;
+     bfd_size_type size;
+{
+  Elf_Internal_Phdr *seg;
+
+  if (! get_program_headers (file))
+    {
+      warn (_("Cannot interpret virtual addresses without program headers.\n"));
+      return (long) vma;
+    }
+
+  for (seg = program_headers;
+       seg < program_headers + elf_header.e_phnum;
+       ++seg)
+    {
+      if (seg->p_type != PT_LOAD)
+       continue;
+
+      if (vma >= (seg->p_vaddr & -seg->p_align)
+         && vma + size <= seg->p_vaddr + seg->p_filesz)
+       return vma - seg->p_vaddr + seg->p_offset;
+    }
+
+  warn (_("Virtual address 0x%lx not located in any PT_LOAD segment.\n"),
+       (long) vma);
+  return (long) vma;
+}
+
+
 static int
 get_32bit_section_headers (file, num)
      FILE *file;
@@ -3532,6 +3767,9 @@ process_section_headers (file)
       string_table = (char *) get_data (NULL, file, section->sh_offset,
                                        section->sh_size, _("string table"));
 
+      if (string_table == NULL)
+       return 0;
+      
       string_table_length = section->sh_size;
     }
 
@@ -3730,6 +3968,19 @@ process_section_headers (file)
   return 1;
 }
 
+struct
+{
+  const char *name;
+  int reloc;
+  int size;
+  int rela;
+} dynamic_relocations [] =
+{
+    { "REL", DT_REL, DT_RELSZ, FALSE },
+    { "RELA", DT_RELA, DT_RELASZ, TRUE },
+    { "PLT", DT_JMPREL, DT_PLTRELSZ, UNKNOWN }
+};
+
 /* Process the reloc section.  */
 static int
 process_relocs (file)
@@ -3744,52 +3995,51 @@ process_relocs (file)
 
   if (do_using_dynamic)
     {
-      int is_rela = FALSE;
-
-      rel_size   = 0;
-      rel_offset = 0;
+      int is_rela;
+      const char *name;
+      int has_dynamic_reloc;
+      unsigned int i;
+      
+      has_dynamic_reloc = 0;
 
-      if (dynamic_info[DT_REL])
-       {
-         rel_offset = dynamic_info[DT_REL];
-         rel_size   = dynamic_info[DT_RELSZ];
-         is_rela    = FALSE;
-       }
-      else if (dynamic_info[DT_RELA])
+      for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++)
        {
-         rel_offset = dynamic_info[DT_RELA];
-         rel_size   = dynamic_info[DT_RELASZ];
-         is_rela    = TRUE;
-       }
-      else if (dynamic_info[DT_JMPREL])
-       {
-         rel_offset = dynamic_info[DT_JMPREL];
-         rel_size   = dynamic_info[DT_PLTRELSZ];
+         is_rela = dynamic_relocations [i].rela;
+         name = dynamic_relocations [i].name;
+         rel_size = dynamic_info [dynamic_relocations [i].size];
+         rel_offset = dynamic_info [dynamic_relocations [i].reloc];
+
+         has_dynamic_reloc |= rel_size;
 
-         switch (dynamic_info[DT_PLTREL])
+         if (is_rela == UNKNOWN)
            {
-           case DT_REL:
-             is_rela = FALSE;
-             break;
-           case DT_RELA:
-             is_rela = TRUE;
-             break;
-           default:
-             is_rela = UNKNOWN;
-             break;
+             if (dynamic_relocations [i].reloc == DT_JMPREL)
+               switch (dynamic_info[DT_PLTREL])
+                 {
+                 case DT_REL:
+                   is_rela = FALSE;
+                   break;
+                 case DT_RELA:
+                   is_rela = TRUE;
+                   break;
+                 }
            }
-       }
-
-      if (rel_size)
-       {
-         printf
-           (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"),
-            rel_offset, rel_size);
 
-         dump_relocations (file, rel_offset - loadaddr, rel_size,
-                           dynamic_symbols, num_dynamic_syms, dynamic_strings, is_rela);
+         if (rel_size)
+           {
+             printf
+               (_("\n'%s' relocation section at offset 0x%lx contains %ld bytes:\n"),
+                name, rel_offset, rel_size);
+
+             dump_relocations (file,
+                               offset_from_vma (file, rel_offset, rel_size),
+                               rel_size,
+                               dynamic_symbols, num_dynamic_syms,
+                               dynamic_strings, is_rela);
+           }
        }
-      else
+
+      if (! has_dynamic_reloc)
        printf (_("\nThere are no dynamic relocations in this file.\n"));
     }
   else
@@ -4009,14 +4259,13 @@ slurp_ia64_unwind_table (file, aux, sec)
      Elf_Internal_Shdr *sec;
 {
   unsigned long size, addr_size, nrelas, i;
-  Elf_Internal_Phdr *prog_hdrs, *seg;
+  Elf_Internal_Phdr *seg;
   struct unw_table_entry *tep;
   Elf_Internal_Shdr *relsec;
   Elf_Internal_Rela *rela, *rp;
   unsigned char *table, *tp;
   Elf_Internal_Sym *sym;
   const char *relname;
-  int result;
 
   addr_size = is_32bit_elf ? 4 : 8;
 
@@ -4025,21 +4274,12 @@ slurp_ia64_unwind_table (file, aux, sec)
 
   if (elf_header.e_phnum)
     {
-      prog_hdrs = (Elf_Internal_Phdr *)
-       xmalloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
-      if (is_32bit_elf)
-       result = get_32bit_program_headers (file, prog_hdrs);
-      else
-       result = get_64bit_program_headers (file, prog_hdrs);
-
-      if (!result)
-       {
-         free (prog_hdrs);
+      if (! get_program_headers (file))
          return 0;
-       }
 
-      for (seg = prog_hdrs; seg < prog_hdrs + elf_header.e_phnum; ++seg)
+      for (seg = program_headers;
+          seg < program_headers + elf_header.e_phnum;
+          ++seg)
        {
          if (seg->p_type != PT_LOAD)
            continue;
@@ -4051,8 +4291,6 @@ slurp_ia64_unwind_table (file, aux, sec)
              break;
            }
        }
-
-      free (prog_hdrs);
     }
 
   /* Second, build the unwind table from the contents of the unwind section:  */
@@ -4429,6 +4667,26 @@ dynamic_segment_parisc_val (entry)
   putchar ('\n');
 }
 
+static void
+dynamic_segment_ia64_val (entry)
+     Elf_Internal_Dyn *entry;
+{
+  switch (entry->d_tag)
+    {
+    case DT_IA_64_PLT_RESERVE: 
+      /* First 3 slots reserved.  */
+      print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+      printf (" -- ");
+      print_vma (entry->d_un.d_ptr + (3 * 8), PREFIX_HEX);
+      break;
+
+    default:
+      print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+      break;
+    }
+  putchar ('\n');
+}
+
 static int
 get_32bit_dynamic_segment (file)
      FILE *file;
@@ -4590,7 +4848,7 @@ process_dynamic_segment (file)
             we default to reading in the entire file (!) and
             processing that.  This is overkill, I know, but it
             should work.  */
-         section.sh_offset = entry->d_un.d_val - loadaddr;
+         section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0);
 
          if (fseek (file, 0, SEEK_END))
            error (_("Unable to seek to end of file!"));
@@ -4632,7 +4890,7 @@ process_dynamic_segment (file)
             processing that.  This is overkill, I know, but it
             should work.  */
 
-         offset = entry->d_un.d_val - loadaddr;
+         offset = offset_from_vma (file, entry->d_un.d_val, 0);
          if (fseek (file, 0, SEEK_END))
            error (_("Unable to seek to end of file\n"));
          str_tab_len = ftell (file) - offset;
@@ -4653,7 +4911,7 @@ process_dynamic_segment (file)
   /* And find the syminfo section if available.  */
   if (dynamic_syminfo == NULL)
     {
-      unsigned int syminsz = 0;
+      unsigned long syminsz = 0;
 
       for (i = 0, entry = dynamic_segment;
           i < dynamic_size;
@@ -4668,7 +4926,8 @@ process_dynamic_segment (file)
          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;
+           dynamic_syminfo_offset = offset_from_vma (file, entry->d_un.d_val,
+                                                     syminsz);
        }
 
       if (dynamic_syminfo_offset != 0 && syminsz != 0)
@@ -4703,7 +4962,7 @@ process_dynamic_segment (file)
     }
 
   if (do_dynamic && dynamic_addr)
-    printf (_("\nDynamic segment at offset 0x%x contains %ld entries:\n"),
+    printf (_("\nDynamic segment at offset 0x%lx contains %ld entries:\n"),
            dynamic_addr, (long) dynamic_size);
   if (do_dynamic)
     printf (_("  Tag        Type                         Name/Value\n"));
@@ -4917,6 +5176,7 @@ process_dynamic_segment (file)
          break;
 
        case DT_PLTREL:
+         dynamic_info[entry->d_tag] = entry->d_un.d_val;
          if (do_dynamic)
            puts (get_dynamic_type (entry->d_un.d_val));
          break;
@@ -4991,6 +5251,7 @@ process_dynamic_segment (file)
        case DT_RELAENT :
        case DT_SYMENT  :
        case DT_RELENT  :
+         dynamic_info[entry->d_tag] = entry->d_un.d_val;
        case DT_PLTPADSZ:
        case DT_MOVEENT :
        case DT_MOVESZ  :
@@ -5078,6 +5339,9 @@ process_dynamic_segment (file)
                case EM_PARISC:
                  dynamic_segment_parisc_val (entry);
                  break;
+               case EM_IA_64:
+                 dynamic_segment_ia64_val (entry);
+                 break;
                default:
                  print_vma (entry->d_un.d_val, PREFIX_HEX);
                  putchar ('\n');
@@ -5352,7 +5616,9 @@ process_version_sections (file)
            edata =
              ((unsigned char *)
               get_data (NULL, file,
-                        version_info[DT_VERSIONTAGIDX (DT_VERSYM)] - loadaddr,
+                        offset_from_vma
+                        (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
+                         total * sizeof (short)),
                         total * sizeof (short), _("version symbol data")));
            if (!edata)
              {
@@ -5408,8 +5674,9 @@ process_version_sections (file)
                          Elf_Internal_Verneed ivn;
                          unsigned long offset;
 
-                         offset = version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
-                           - loadaddr;
+                         offset = offset_from_vma
+                           (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
+                            sizeof (Elf_External_Verneed));
 
                          do
                            {
@@ -5464,8 +5731,9 @@ process_version_sections (file)
                          Elf_External_Verdef evd;
                          unsigned long offset;
 
-                         offset = (version_info[DT_VERSIONTAGIDX (DT_VERDEF)]
-                                   - loadaddr);
+                         offset = offset_from_vma
+                           (file, version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
+                            sizeof evd);
 
                          do
                            {
@@ -5692,7 +5960,9 @@ process_symbol_table (file)
   if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
                                || do_histogram))
     {
-      if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
+      if (fseek (file, offset_from_vma (file, dynamic_info[DT_HASH],
+                                       sizeof nb + sizeof nc),
+                SEEK_SET))
        {
          error (_("Unable to seek to start of dynamic information"));
          return 0;
@@ -5823,8 +6093,9 @@ process_symbol_table (file)
                  int is_nobits;
                  int check_def;
 
-                 offset = version_info[DT_VERSIONTAGIDX (DT_VERSYM)]
-                   - loadaddr;
+                 offset = offset_from_vma
+                   (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
+                    sizeof data + si * sizeof (vers_data));
 
                  get_data (&data, file, offset + si * sizeof (vers_data),
                            sizeof (data), _("version data"));
@@ -5846,8 +6117,9 @@ process_symbol_table (file)
                          Elf_Internal_Vernaux ivna;
 
                          /* We must test both.  */
-                         offset = (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
-                                   - loadaddr);
+                         offset = offset_from_vma
+                           (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
+                            sizeof evn);
 
                          do
                            {
@@ -5907,9 +6179,10 @@ process_symbol_table (file)
                              Elf_External_Verdaux evda;
                              unsigned long offset;
 
-                             offset
-                               = (version_info[DT_VERSIONTAGIDX (DT_VERDEF)]
-                                  - loadaddr);
+                             offset = offset_from_vma
+                               (file,
+                                version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
+                                sizeof (Elf_External_Verdef));
 
                              do
                                {
@@ -6335,31 +6608,42 @@ display_debug_lines (section, start, file)
      unsigned char * start;
      FILE *file ATTRIBUTE_UNUSED;
 {
-  DWARF2_External_LineInfo *external;
+  unsigned char *hdrptr;
   DWARF2_Internal_LineInfo info;
   unsigned char *standard_opcodes;
   unsigned char *data = start;
   unsigned char *end = start + section->sh_size;
   unsigned char *end_of_sequence;
   int i;
+  int offset_size;
+  int initial_length_size;
 
   printf (_("\nDump of debug contents of section %s:\n\n"),
          SECTION_NAME (section));
 
   while (data < end)
     {
-      external = (DWARF2_External_LineInfo *) data;
+      hdrptr = data;
 
       /* Check the length of the block.  */
-      info.li_length = BYTE_GET (external->li_length);
+      info.li_length = byte_get (hdrptr, 4);
+      hdrptr += 4;
 
       if (info.li_length == 0xffffffff)
        {
-         warn (_("64-bit DWARF line info is not supported yet.\n"));
-         break;
+         /* This section is 64-bit DWARF 3.  */
+         info.li_length = byte_get (hdrptr, 8);
+         hdrptr += 8;
+         offset_size = 8;
+         initial_length_size = 12;
+       }
+      else
+       {
+         offset_size = 4;
+         initial_length_size = 4;
        }
 
-      if (info.li_length + sizeof (external->li_length) > section->sh_size)
+      if (info.li_length + initial_length_size > section->sh_size)
        {
          warn
            (_("The line info appears to be corrupt - the section is too small\n"));
@@ -6367,19 +6651,26 @@ display_debug_lines (section, start, file)
        }
 
       /* Check its version number.  */
-      info.li_version = BYTE_GET (external->li_version);
-      if (info.li_version != 2)
+      info.li_version = byte_get (hdrptr, 2);
+      hdrptr += 2;
+      if (info.li_version != 2 && info.li_version != 3)
        {
-         warn (_("Only DWARF version 2 line info is currently supported.\n"));
+         warn (_("Only DWARF version 2 and 3 line info is currently supported.\n"));
          return 0;
        }
 
-      info.li_prologue_length = BYTE_GET (external->li_prologue_length);
-      info.li_min_insn_length = BYTE_GET (external->li_min_insn_length);
-      info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt);
-      info.li_line_base       = BYTE_GET (external->li_line_base);
-      info.li_line_range      = BYTE_GET (external->li_line_range);
-      info.li_opcode_base     = BYTE_GET (external->li_opcode_base);
+      info.li_prologue_length = byte_get (hdrptr, offset_size);
+      hdrptr += offset_size;
+      info.li_min_insn_length = byte_get (hdrptr, 1);
+      hdrptr++;
+      info.li_default_is_stmt = byte_get (hdrptr, 1);
+      hdrptr++;
+      info.li_line_base = byte_get (hdrptr, 1);
+      hdrptr++;
+      info.li_line_range = byte_get (hdrptr, 1);
+      hdrptr++;
+      info.li_opcode_base = byte_get (hdrptr, 1);
+      hdrptr++;
 
       /* Sign extend the line base field.  */
       info.li_line_base <<= 24;
@@ -6394,12 +6685,12 @@ display_debug_lines (section, start, file)
       printf (_("  Line Range:                  %d\n"), info.li_line_range);
       printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
 
-      end_of_sequence = data + info.li_length + sizeof (external->li_length);
+      end_of_sequence = data + info.li_length + initial_length_size;
 
       reset_state_machine (info.li_default_is_stmt);
 
       /* Display the contents of the Opcodes table.  */
-      standard_opcodes = data + sizeof (*external);
+      standard_opcodes = hdrptr;
 
       printf (_("\n Opcodes:\n"));
 
@@ -6592,7 +6883,6 @@ display_debug_pubnames (section, start, file)
      unsigned char *start;
      FILE *file ATTRIBUTE_UNUSED;
 {
-  DWARF2_External_PubNames *external;
   DWARF2_Internal_PubNames pubnames;
   unsigned char *end;
 
@@ -6604,30 +6894,41 @@ display_debug_pubnames (section, start, file)
     {
       unsigned char *data;
       unsigned long offset;
+      int offset_size, initial_length_size;
 
-      external = (DWARF2_External_PubNames *) start;
-
-      pubnames.pn_length  = BYTE_GET (external->pn_length);
-      pubnames.pn_version = BYTE_GET (external->pn_version);
-      pubnames.pn_offset  = BYTE_GET (external->pn_offset);
-      pubnames.pn_size    = BYTE_GET (external->pn_size);
-
-      data   = start + sizeof (*external);
-      start += pubnames.pn_length + sizeof (external->pn_length);
+      data = start;
 
+      pubnames.pn_length = byte_get (data, 4);
+      data += 4;
       if (pubnames.pn_length == 0xffffffff)
        {
-         warn (_("64-bit DWARF pubnames are not supported yet.\n"));
-         break;
+         pubnames.pn_length = byte_get (data, 8);
+         data += 8;
+         offset_size = 8;
+         initial_length_size = 12;
        }
+      else
+       {
+         offset_size = 4;
+         initial_length_size = 4;
+       }
+
+      pubnames.pn_version = byte_get (data, 2);
+      data += 2;
+      pubnames.pn_offset = byte_get (data, offset_size);
+      data += offset_size;
+      pubnames.pn_size = byte_get (data, offset_size);
+      data += offset_size;
+
+      start += pubnames.pn_length + initial_length_size;
 
-      if (pubnames.pn_version != 2)
+      if (pubnames.pn_version != 2 && pubnames.pn_version != 3)
        {
          static int warned = 0;
 
          if (! warned)
            {
-             warn (_("Only DWARF 2 pubnames are currently supported\n"));
+             warn (_("Only DWARF 2 and 3 pubnames are currently supported\n"));
              warned = 1;
            }
 
@@ -6647,11 +6948,11 @@ display_debug_pubnames (section, start, file)
 
       do
        {
-         offset = byte_get (data, 4);
+         offset = byte_get (data, offset_size);
 
          if (offset != 0)
            {
-             data += 4;
+             data += offset_size;
              printf ("    %ld\t\t%s\n", offset, data);
              data += strlen ((char *) data) + 1;
            }
@@ -6730,6 +7031,10 @@ get_TAG_name (tag)
     case DW_TAG_unspecified_type:      return "DW_TAG_unspecified_type";
     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";
     default:
       {
        static char buffer[100];
@@ -6842,6 +7147,8 @@ get_AT_name (attribute)
     case DW_AT_body_begin:             return "DW_AT_body_begin";
     case DW_AT_body_end:               return "DW_AT_body_end";
     case DW_AT_GNU_vector:             return "DW_AT_GNU_vector";
+      /* UPC extension.  */
+    case DW_AT_upc_threads_scaled:     return "DW_AT_upc_threads_scaled";
     default:
       {
        static char buffer[100];
@@ -7512,7 +7819,8 @@ decode_location_expression (data, pointer_size, length)
        }
 
       /* Separate the ops.  */
-      printf ("; ");
+      if (data < end)
+       printf ("; ");
     }
 }
 
@@ -7594,13 +7902,12 @@ display_debug_loc (section, start, file)
 
       while (1)
        {
-         /* Normally, the lists in  the debug_loc section are related to a
-            given compilation unit, and thus, we would use the
-            pointer size of that compilation unit.  However, since we are
-            displaying it seperately here, we either have to store
-            pointer sizes of all compilation units, or assume they don't
-            change.   We assume, like the debug_line display, that
-            it doesn't change.  */
+         /* Normally, the lists in the debug_loc section are related to a
+            given compilation unit, and thus, we would use the pointer size
+            of that compilation unit.  However, since we are displaying it
+            seperately here, we either have to store pointer sizes of all
+            compilation units, or assume they don't change.   We assume,
+            like the debug_line display, that it doesn't change.  */
          begin = byte_get (start, debug_line_pointer_size);
          start += debug_line_pointer_size;
          end = byte_get (start, debug_line_pointer_size);
@@ -7609,6 +7916,10 @@ display_debug_loc (section, start, file)
          if (begin == 0 && end == 0)
            break;
 
+         /* For now, skip any base address specifiers.  */
+         if (begin == 0xffffffff)
+           continue;
+
          begin += addr;
          end += addr;
 
@@ -7742,12 +8053,15 @@ display_debug_str (section, start, file)
 }
 
 static unsigned char *
-read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
+read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size,
+                             offset_size, dwarf_version)
      unsigned long attribute;
      unsigned long form;
      unsigned char *data;
      unsigned long cu_offset;
      unsigned long pointer_size;
+     unsigned long offset_size;
+     int dwarf_version;
 {
   unsigned long uvalue = 0;
   unsigned char *block_start = NULL;
@@ -7759,14 +8073,30 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
       break;
 
     case DW_FORM_ref_addr:
+      if (dwarf_version == 2)
+       {
+         uvalue = byte_get (data, pointer_size);
+         data += pointer_size;
+       }
+      else if (dwarf_version == 3)
+       {
+         uvalue = byte_get (data, offset_size);
+         data += offset_size;
+       }
+      else
+        {
+         error (_("Internal error: DWARF version is not 2 or 3.\n"));
+       }
+      break;
+
     case DW_FORM_addr:
       uvalue = byte_get (data, pointer_size);
       data += pointer_size;
       break;
 
     case DW_FORM_strp:
-      uvalue = byte_get (data, /* offset_size */ 4);
-      data += /* offset_size */ 4;
+      uvalue = byte_get (data, offset_size);
+      data += offset_size;
       break;
 
     case DW_FORM_ref1:
@@ -7803,7 +8133,8 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
       data += bytes_read;
       printf (" %s", get_FORM_name (form));
       return read_and_display_attr_value (attribute, form, data, cu_offset,
-                                         pointer_size);
+                                         pointer_size, offset_size,
+                                         dwarf_version);
     }
 
   switch (form)
@@ -7928,6 +8259,8 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
        case DW_LANG_Fortran95:         printf ("(Fortran 95)"); break;
          /* MIPS extension.  */
        case DW_LANG_Mips_Assembler:    printf ("(MIPS assembler)"); break;
+         /* UPC extension.  */
+       case DW_LANG_Upc:               printf ("(Unified Parallel C)"); break;
        default:
          printf ("(Unknown: %lx)", uvalue);
          break;
@@ -8041,7 +8374,7 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
          decode_location_expression (block_start, pointer_size, uvalue);
          printf (")");
        }
-      else if (form == DW_FORM_data4)
+      else if (form == DW_FORM_data4 || form == DW_FORM_data8)
        {
          printf ("(");
          printf ("location list");
@@ -8057,16 +8390,19 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
 }
 
 static unsigned char *
-read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
+read_and_display_attr (attribute, form, data, cu_offset, pointer_size,
+                       offset_size, dwarf_version)
      unsigned long attribute;
      unsigned long form;
      unsigned char *data;
      unsigned long cu_offset;
      unsigned long pointer_size;
+     unsigned long offset_size;
+     int dwarf_version;
 {
   printf ("     %-18s:", get_AT_name (attribute));
   data = read_and_display_attr_value (attribute, form, data, cu_offset,
-                                     pointer_size);
+                                     pointer_size, offset_size, dwarf_version);
   printf ("\n");
   return data;
 }
@@ -8087,29 +8423,39 @@ display_debug_info (section, start, file)
 
   while (start < end)
     {
-      DWARF2_External_CompUnit *external;
       DWARF2_Internal_CompUnit compunit;
       Elf_Internal_Shdr *relsec;
+      unsigned char *hdrptr;
+      unsigned char *cu_abbrev_offset_ptr;
       unsigned char *tags;
       unsigned int i;
       int level;
       unsigned long cu_offset;
+      int offset_size;
+      int initial_length_size;
 
-      external = (DWARF2_External_CompUnit *) start;
+      hdrptr = start;
 
-      compunit.cu_length        = BYTE_GET (external->cu_length);
-      compunit.cu_version       = BYTE_GET (external->cu_version);
-      compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset);
-      compunit.cu_pointer_size  = BYTE_GET (external->cu_pointer_size);
+      compunit.cu_length = byte_get (hdrptr, 4);
+      hdrptr += 4;
 
       if (compunit.cu_length == 0xffffffff)
        {
-         warn (_("64-bit DWARF debug info is not supported yet.\n"));
-         break;
+         compunit.cu_length = byte_get (hdrptr, 8);
+         hdrptr += 8;
+         offset_size = 8;
+         initial_length_size = 12;
+       }
+      else
+       {
+         offset_size = 4;
+         initial_length_size = 4;
        }
 
-      /* Check for RELA relocations in the
-        abbrev_offset address, and apply them.  */
+      compunit.cu_version = byte_get (hdrptr, 2);
+      hdrptr += 2;
+
+      /* Apply addends of RELA relocations.  */
       for (relsec = section_headers;
           relsec < section_headers + elf_header.e_shnum;
           ++relsec)
@@ -8134,9 +8480,13 @@ display_debug_info (section, start, file)
 
          for (rp = rela; rp < rela + nrelas; ++rp)
            {
-             if (rp->r_offset
-                 != (bfd_vma) ((unsigned char *) &external->cu_abbrev_offset
-                               - section_begin))
+             unsigned char *loc;
+
+             if (rp->r_offset >= (bfd_vma) (hdrptr - section_begin)
+                 && section->sh_size > (bfd_vma) offset_size
+                 && rp->r_offset <= section->sh_size - offset_size)
+               loc = section_begin + rp->r_offset;
+             else
                continue;
 
              if (is_32bit_elf)
@@ -8164,17 +8514,23 @@ display_debug_info (section, start, file)
                    }
                }
 
-             compunit.cu_abbrev_offset = rp->r_addend;
-             break;
+             byte_put (loc, rp->r_addend, offset_size);
            }
 
          free (rela);
          break;
        }
 
-      tags = start + sizeof (*external);
+      cu_abbrev_offset_ptr = hdrptr;
+      compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
+      hdrptr += offset_size;
+
+      compunit.cu_pointer_size = byte_get (hdrptr, 1);
+      hdrptr += 1;
+
+      tags = hdrptr;
       cu_offset = start - section_begin;
-      start += compunit.cu_length + sizeof (external->cu_length);
+      start += compunit.cu_length + initial_length_size;
 
       printf (_("  Compilation Unit @ %lx:\n"), cu_offset);
       printf (_("   Length:        %ld\n"), compunit.cu_length);
@@ -8182,9 +8538,9 @@ display_debug_info (section, start, file)
       printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
       printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
 
-      if (compunit.cu_version != 2)
+      if (compunit.cu_version != 2 && compunit.cu_version != 3)
        {
-         warn (_("Only version 2 DWARF debug information is currently supported.\n"));
+         warn (_("Only version 2 and 3 DWARF debug information is currently supported.\n"));
          continue;
        }
 
@@ -8262,7 +8618,9 @@ display_debug_info (section, start, file)
            tags = read_and_display_attr (attr->attribute,
                                          attr->form,
                                          tags, cu_offset,
-                                         compunit.cu_pointer_size);
+                                         compunit.cu_pointer_size,
+                                         offset_size,
+                                         compunit.cu_version);
 
          if (entry->children)
            ++level;
@@ -8289,30 +8647,48 @@ display_debug_aranges (section, start, file)
 
   while (start < end)
     {
-      DWARF2_External_ARange *external;
+      unsigned char *hdrptr;
       DWARF2_Internal_ARange arange;
       unsigned char *ranges;
       unsigned long length;
       unsigned long address;
       int excess;
+      int offset_size;
+      int initial_length_size;
 
-      external = (DWARF2_External_ARange *) start;
+      hdrptr = start;
 
-      arange.ar_length       = BYTE_GET (external->ar_length);
-      arange.ar_version      = BYTE_GET (external->ar_version);
-      arange.ar_info_offset  = BYTE_GET (external->ar_info_offset);
-      arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size);
-      arange.ar_segment_size = BYTE_GET (external->ar_segment_size);
+      arange.ar_length = byte_get (hdrptr, 4);
+      hdrptr += 4;
 
       if (arange.ar_length == 0xffffffff)
        {
-         warn (_("64-bit DWARF aranges are not supported yet.\n"));
-         break;
+         arange.ar_length = byte_get (hdrptr, 8);
+         hdrptr += 8;
+         offset_size = 8;
+         initial_length_size = 12;
+       }
+      else
+        {
+         offset_size = 4;
+         initial_length_size = 4;
        }
 
-      if (arange.ar_version != 2)
+      arange.ar_version = byte_get (hdrptr, 2);
+      hdrptr += 2;
+
+      arange.ar_info_offset = byte_get (hdrptr, offset_size);
+      hdrptr += offset_size;
+
+      arange.ar_pointer_size = byte_get (hdrptr, 1);
+      hdrptr += 1;
+
+      arange.ar_segment_size = byte_get (hdrptr, 1);
+      hdrptr += 1;
+
+      if (arange.ar_version != 2 && arange.ar_version != 3)
        {
-         warn (_("Only DWARF 2 aranges are currently supported.\n"));
+         warn (_("Only DWARF 2 and 3 aranges are currently supported.\n"));
          break;
        }
 
@@ -8324,10 +8700,10 @@ display_debug_aranges (section, start, file)
 
       printf (_("\n    Address  Length\n"));
 
-      ranges = start + sizeof (*external);
+      ranges = hdrptr;
 
       /* Must pad to an alignment boundary that is twice the pointer size.  */
-      excess = sizeof (*external) % (2 * arange.ar_pointer_size);
+      excess = (hdrptr - start) % (2 * arange.ar_pointer_size);
       if (excess)
        ranges += (2 * arange.ar_pointer_size) - excess;
 
@@ -8348,7 +8724,7 @@ display_debug_aranges (section, start, file)
          printf ("    %8.8lx %lu\n", address, length);
        }
 
-      start += arange.ar_length + sizeof (external->ar_length);
+      start += arange.ar_length + initial_length_size;
     }
 
   printf ("\n");
@@ -8373,6 +8749,7 @@ typedef struct Frame_Chunk
   int cfa_offset;
   int ra;
   unsigned char fde_encoding;
+  unsigned char cfa_exp;
 }
 Frame_Chunk;
 
@@ -8383,6 +8760,7 @@ Frame_Chunk;
 static void frame_need_space PARAMS ((Frame_Chunk *, int));
 static void frame_display_row PARAMS ((Frame_Chunk *, int *, int *));
 static int size_of_encoded_value PARAMS ((int));
+static bfd_vma get_encoded_value PARAMS ((unsigned char *, int));
 
 static void
 frame_need_space (fc, reg)
@@ -8439,7 +8817,10 @@ frame_display_row (fc, need_col_headers, max_regs)
     }
 
   printf ("%08lx ", fc->pc_begin);
-  sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
+  if (fc->cfa_exp)
+    strcpy (tmp, "exp");
+  else
+    sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
   printf ("%-8s ", tmp);
 
   for (r = 0; r < fc->ncols; r++)
@@ -8460,6 +8841,9 @@ frame_display_row (fc, need_col_headers, max_regs)
            case DW_CFA_register:
              sprintf (tmp, "r%d", fc->col_offset[r]);
              break;
+           case DW_CFA_expression:
+             strcpy (tmp, "exp");
+             break;
            default:
              strcpy (tmp, "n/a");
              break;
@@ -8484,6 +8868,18 @@ size_of_encoded_value (encoding)
     }
 }
 
+static bfd_vma
+get_encoded_value (data, encoding)
+     unsigned char *data;
+     int encoding;
+{
+  int size = size_of_encoded_value (encoding);
+  if (encoding & DW_EH_PE_signed)
+    return byte_get_signed (data, size);
+  else
+    return byte_get (data, size);
+}
+
 #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
@@ -8518,6 +8914,8 @@ display_debug_frames (section, start, file)
       unsigned char *augmentation_data = NULL;
       unsigned long augmentation_data_len = 0;
       int encoded_ptr_size = addr_size;
+      int offset_size;
+      int initial_length_size;
 
       saved_start = start;
       length = byte_get (start, 4); start += 4;
@@ -8531,12 +8929,19 @@ display_debug_frames (section, start, file)
 
       if (length == 0xffffffff)
        {
-         warn (_("64-bit DWARF format frames are not supported yet.\n"));
-         break;
+         length = byte_get (start, 8);
+         start += 8;
+         offset_size = 8;
+         initial_length_size = 12;
+       }
+      else
+       {
+         offset_size = 4;
+         initial_length_size = 4;
        }
 
-      block_end = saved_start + length + 4;
-      cie_id = byte_get (start, 4); start += 4;
+      block_end = saved_start + length + initial_length_size;
+      cie_id = byte_get (start, offset_size); start += offset_size;
 
       if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
        {
@@ -8680,7 +9085,7 @@ display_debug_frames (section, start, file)
          if (fc->fde_encoding)
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
-         fc->pc_begin = byte_get (start, encoded_ptr_size);
+         fc->pc_begin = get_encoded_value (start, fc->fde_encoding);
          if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
            fc->pc_begin += section->sh_addr + (start - section_start);
          start += encoded_ptr_size;
@@ -8711,8 +9116,12 @@ display_debug_frames (section, start, file)
 
       /* At this point, fc is the current chunk, cie (if any) is set, and we're
         about to interpret instructions for the chunk.  */
-
-      if (do_debug_frames_interp)
+      /* ??? At present we need to do this always, since this sizes the
+        fc->col_type and fc->col_offset arrays, which we write into always.
+        We should probably split the interpreted and non-interpreted bits
+        into two different routines, since there's so much that doesn't
+        really overlap between them.  */
+      if (1 || do_debug_frames_interp)
        {
          /* Start by making a pass over the chunk, allocating storage
             and taking note of what registers are used.  */
@@ -8721,7 +9130,7 @@ display_debug_frames (section, start, file)
          while (start < block_end)
            {
              unsigned op, opa;
-             unsigned long reg;
+             unsigned long reg, tmp;
 
              op = *start++;
              opa = op & 0x3f;
@@ -8789,6 +9198,17 @@ display_debug_frames (section, start, file)
                case DW_CFA_def_cfa_offset:
                  LEB ();
                  break;
+               case DW_CFA_def_cfa_expression:
+                 tmp = LEB ();
+                 start += tmp;
+                 break;
+               case DW_CFA_expression:
+                 reg = LEB ();
+                 tmp = LEB ();
+                 start += tmp;
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
+                 break;
                case DW_CFA_offset_extended_sf:
                  reg = LEB (); SLEB ();
                  frame_need_space (fc, reg);
@@ -8800,6 +9220,9 @@ display_debug_frames (section, start, file)
                case DW_CFA_def_cfa_offset_sf:
                  SLEB ();
                  break;
+               case DW_CFA_MIPS_advance_loc8:
+                 start += 8;
+                 break;
                case DW_CFA_GNU_args_size:
                  LEB ();
                  break;
@@ -8861,7 +9284,7 @@ display_debug_frames (section, start, file)
              break;
 
            case DW_CFA_set_loc:
-             vma = byte_get (start, encoded_ptr_size);
+             vma = get_encoded_value (start, fc->fde_encoding);
              if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
                vma += section->sh_addr + (start - section_start);
              start += encoded_ptr_size;
@@ -8943,7 +9366,7 @@ display_debug_frames (section, start, file)
              reg = LEB ();
              roffs = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_register: r%ld\n", reg);
+               printf ("  DW_CFA_register: r%ld in r%ld\n", reg, roffs);
              fc->col_type[reg] = DW_CFA_register;
              fc->col_offset[reg] = roffs;
              break;
@@ -8977,6 +9400,7 @@ display_debug_frames (section, start, file)
            case DW_CFA_def_cfa:
              fc->cfa_reg = LEB ();
              fc->cfa_offset = LEB ();
+             fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa: r%d ofs %d\n",
                        fc->cfa_reg, fc->cfa_offset);
@@ -8984,6 +9408,7 @@ display_debug_frames (section, start, file)
 
            case DW_CFA_def_cfa_register:
              fc->cfa_reg = LEB ();
+             fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
              break;
@@ -8999,6 +9424,31 @@ display_debug_frames (section, start, file)
                printf ("  DW_CFA_nop\n");
              break;
 
+           case DW_CFA_def_cfa_expression:
+             ul = LEB ();
+             if (! do_debug_frames_interp)
+               {
+                 printf ("  DW_CFA_def_cfa_expression (");
+                 decode_location_expression (start, addr_size, ul);
+                 printf (")\n");
+               }
+             fc->cfa_exp = 1;
+             start += ul;
+             break;
+
+           case DW_CFA_expression:
+             reg = LEB ();
+             ul = LEB ();
+             if (! do_debug_frames_interp)
+               {
+                 printf ("  DW_CFA_expression: r%ld (", reg);
+                 decode_location_expression (start, addr_size, ul);
+                 printf (")\n");
+               }
+             fc->col_type[reg] = DW_CFA_expression;
+             start += ul;
+             break;
+
            case DW_CFA_offset_extended_sf:
              reg = LEB ();
              l = SLEB ();
@@ -9013,6 +9463,7 @@ display_debug_frames (section, start, file)
            case DW_CFA_def_cfa_sf:
              fc->cfa_reg = LEB ();
              fc->cfa_offset = SLEB ();
+             fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_sf: r%d ofs %d\n",
                        fc->cfa_reg, fc->cfa_offset);
@@ -9024,6 +9475,17 @@ display_debug_frames (section, start, file)
                printf ("  DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
              break;
 
+           case DW_CFA_MIPS_advance_loc8:
+             ofs = byte_get (start, 8); start += 8;
+             if (do_debug_frames_interp)
+               frame_display_row (fc, &need_col_headers, &max_regs);
+             else
+               printf ("  DW_CFA_MIPS_advance_loc8: %ld to %08lx\n",
+                       ofs * fc->code_factor,
+                       fc->pc_begin + ofs * fc->code_factor);
+             fc->pc_begin += ofs * fc->code_factor;
+             break;
+
            case DW_CFA_GNU_window_save:
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_GNU_window_save\n");
@@ -9046,17 +9508,6 @@ 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;
@@ -9099,11 +9550,41 @@ prescan_debug_info (section, start, file)
      unsigned char *start;
      FILE *file ATTRIBUTE_UNUSED;
 {
-  DWARF2_External_CompUnit *external;
+  unsigned long length;
 
-  external = (DWARF2_External_CompUnit *) start;
+  /* Read the first 4 bytes.  For a 32-bit DWARF section, this will
+     be the length.  For a 64-bit DWARF section, it'll be the escape
+     code 0xffffffff followed by an 8 byte length.  For the purposes
+     of this prescan, we don't care about the actual length, but the
+     presence of the escape bytes does affect the location of the byte
+     which describes the address size.  */
+  length = byte_get (start, 4);
 
-  debug_line_pointer_size = BYTE_GET (external->cu_pointer_size);
+  if (length == 0xffffffff)
+    {
+      /* For 64-bit DWARF, the 1-byte address_size field is 22 bytes
+         from the start of the section.  This is computed as follows:
+
+           unit_length:         12 bytes
+           version:              2 bytes
+           debug_abbrev_offset:  8 bytes
+           -----------------------------
+           Total:               22 bytes  */
+
+      debug_line_pointer_size = byte_get (start + 22, 1);
+    }
+  else
+    {
+      /* For 32-bit DWARF, the 1-byte address_size field is 10 bytes from
+         the start of the section:
+           unit_length:          4 bytes
+           version:              2 bytes
+           debug_abbrev_offset:  4 bytes
+           -----------------------------
+           Total:               10 bytes  */
+
+      debug_line_pointer_size = byte_get (start + 10, 1);
+    }
   return 0;
 }
 
@@ -9292,16 +9773,20 @@ process_mips_specific (file)
     switch (entry->d_tag)
       {
       case DT_MIPS_LIBLIST:
-       liblist_offset = entry->d_un.d_val - loadaddr;
+       liblist_offset
+         = offset_from_vma (file, entry->d_un.d_val,
+                            liblistno * sizeof (Elf32_External_Lib));
        break;
       case DT_MIPS_LIBLISTNO:
        liblistno = entry->d_un.d_val;
        break;
       case DT_MIPS_OPTIONS:
-       options_offset = entry->d_un.d_val - loadaddr;
+       options_offset = offset_from_vma (file, entry->d_un.d_val, 0);
        break;
       case DT_MIPS_CONFLICT:
-       conflicts_offset = entry->d_un.d_val - loadaddr;
+       conflicts_offset
+         = offset_from_vma (file, entry->d_un.d_val,
+                            conflictsno * sizeof (Elf32_External_Conflict));
        break;
       case DT_MIPS_CONFLICTNO:
        conflictsno = entry->d_un.d_val;
@@ -9953,30 +10438,12 @@ static int
 process_corefile_note_segments (file)
      FILE *file;
 {
-  Elf_Internal_Phdr *program_headers;
   Elf_Internal_Phdr *segment;
   unsigned int i;
   int res = 1;
 
-  program_headers = (Elf_Internal_Phdr *) malloc
-    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
-  if (program_headers == NULL)
-    {
-      error (_("Out of memory\n"));
-      return 0;
-    }
-
-  if (is_32bit_elf)
-    i = get_32bit_program_headers (file, program_headers);
-  else
-    i = get_64bit_program_headers (file, program_headers);
-
-  if (i == 0)
-    {
-      free (program_headers);
+  if (! get_program_headers (file))
       return 0;
-    }
 
   for (i = 0, segment = program_headers;
        i < elf_header.e_phnum;
@@ -9988,8 +10455,6 @@ process_corefile_note_segments (file)
                                              (bfd_vma) segment->p_filesz);
     }
 
-  free (program_headers);
-
   return res;
 }
 
@@ -10047,8 +10512,14 @@ get_file_header (file)
     {
     default: /* fall through */
     case ELFDATANONE: /* fall through */
-    case ELFDATA2LSB: byte_get = byte_get_little_endian; break;
-    case ELFDATA2MSB: byte_get = byte_get_big_endian; break;
+    case ELFDATA2LSB:
+      byte_get = byte_get_little_endian;
+      byte_put = byte_put_little_endian;
+      break;
+    case ELFDATA2MSB:
+      byte_get = byte_get_big_endian;
+      byte_put = byte_put_big_endian;
+      break;
     }
 
   /* For now we only support 32 bit and 64 bit ELF files.  */
@@ -10200,6 +10671,12 @@ process_file (file_name)
 
   fclose (file);
 
+  if (program_headers)
+    {
+      free (program_headers);
+      program_headers = NULL;
+    }
+
   if (section_headers)
     {
       free (section_headers);
@@ -10262,6 +10739,8 @@ main (argc, argv)
      char **argv;
 {
   int err;
+  char *cmdline_dump_sects = NULL;
+  unsigned num_cmdline_dump_sects = 0;
 
 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
   setlocale (LC_MESSAGES, "");
@@ -10277,12 +10756,38 @@ main (argc, argv)
   if (optind < (argc - 1))
     show_name = 1;
 
+  /* When processing more than one file remember the dump requests
+     issued on command line to reset them after each file.  */
+  if (optind + 1 < argc && dump_sects != NULL)
+    {
+      cmdline_dump_sects = malloc (num_dump_sects);
+      if (cmdline_dump_sects == NULL)
+       error (_("Out of memory allocating dump request table."));
+      else
+       {
+         memcpy (cmdline_dump_sects, dump_sects, num_dump_sects);
+         num_cmdline_dump_sects = num_dump_sects;
+       }
+    }
+
   err = 0;
   while (optind < argc)
-    err |= process_file (argv[optind++]);
+    {
+      err |= process_file (argv[optind++]);
+
+      /* Reset dump requests.  */
+      if (optind < argc && dump_sects != NULL)
+       {
+         num_dump_sects = num_cmdline_dump_sects;
+         if (num_cmdline_dump_sects > 0)
+           memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects);
+       }
+    }
 
   if (dump_sects != NULL)
     free (dump_sects);
+  if (cmdline_dump_sects != NULL)
+    free (cmdline_dump_sects);
 
   return err;
 }