Support interworking for thumb-pe and arm-pe targets.
authorNick Clifton <nickc@redhat.com>
Wed, 25 Mar 1998 23:48:55 +0000 (23:48 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 25 Mar 1998 23:48:55 +0000 (23:48 +0000)
bfd/ChangeLog
bfd/coff-arm.c
bfd/coffcode.h
bfd/peicode.h

index 4677203d02d8a32cb01c60120346771018f3bf47..b454bd70edd8090da2e023635ed9a8bf21bbc138 100644 (file)
@@ -1,3 +1,14 @@
+Wed Mar 25 15:45:55 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * coffcode.h (coff_mkobject_hook): Set private falgs even for a PE
+       build.
+
+       * peicode.h: Call arm-coff private data functions after handling
+       pe private data.
+
+       * coff-arm.c: Turn statics into globals so that they can be shared
+       both pe and pei backends.
+
 Wed Mar 25 15:19:38 1998  Ian Lance Taylor  <ian@cygnus.com>
 
        * aoutf1.h (sunos_set_arch_mach): Use bfd_mach_m68* rather than
index 2c9318c6ab4a4e3bb49f93a359d8a39d999860b5..af129eb68230cd9f1745d648b56f858787be67a9 100644 (file)
@@ -725,11 +725,28 @@ arm_reloc_type_lookup(abfd,code)
 #define ARM 1                  /* Customize coffcode.h */
 
 /* The set of global variables that mark the total size of each kind
-   of glue required. */
-static long int global_thumb_glue_size = 0;
-static long int global_arm_glue_size = 0;
+   of glue required, plus a BFD to hang the glue sections onto.
+   Note:  These variable should not be made static, since in a *-pe
+   build there are two versions of this file compiled, one for pe
+   objects and one for pei objects, and they want to share these
+   variables.  */
+#if defined COFF_IMAGE_WITH_PE
+extern long int global_thumb_glue_size;
+#else
+long int global_thumb_glue_size = 0;
+#endif
 
-static bfd * bfd_of_glue_owner = NULL;
+#if defined COFF_IMAGE_WITH_PE
+extern long int global_arm_glue_size;
+#else
+long int global_arm_glue_size = 0;
+#endif
+
+#if defined COFF_IMAGE_WITH_PE 
+extern bfd * bfd_of_glue_owner;
+#else
+bfd * bfd_of_glue_owner = NULL;
+#endif
 
 /* some typedefs for holding instructions */
 typedef unsigned long int insn32;
@@ -1105,7 +1122,7 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
                                ("  first occurrence: %s: arm call to thumb",
                                 bfd_get_filename (input_bfd));
                            }
-                         
+
                          --my_offset;
                          myh->root.u.def.value = my_offset;
 
@@ -1182,6 +1199,7 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
                                ("  first occurrence: %s: thumb call to arm",
                                 bfd_get_filename (input_bfd));
                            }
+                         
                          -- my_offset;
                          myh->root.u.def.value = my_offset;
 
@@ -1658,6 +1676,8 @@ arm_process_before_allocation (abfd, info)
 
   _bfd_coff_get_external_symbols (abfd);
 
+  BFD_ASSERT (bfd_of_glue_owner != NULL);
+  
   /* Rummage around all the relocs and map the glue vectors.  */
   sec = abfd->sections;
 
@@ -1788,9 +1808,10 @@ coff_arm_bfd_merge_private_bfd_data (ibfd, obfd)
   /* If the two formats are different we cannot merge anything.
      This is not an error, since it is permissable to change the
      input and output formats.  */
-  if (ibfd->xvec != obfd->xvec)
+  if (   ibfd->xvec->flavour != bfd_target_coff_flavour
+      || obfd->xvec->flavour != bfd_target_coff_flavour)
     return true;
-  
+
   /* Verify that the APCS is the same for the two BFDs */
   if (APCS_SET (ibfd))
     {
@@ -1841,7 +1862,7 @@ coff_arm_bfd_merge_private_bfd_data (ibfd, obfd)
          bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
        }
     }
-  
+
   /* Check the interworking support.  */
   if (INTERWORK_SET (ibfd))
     {
@@ -1871,7 +1892,7 @@ coff_arm_bfd_merge_private_bfd_data (ibfd, obfd)
 
 /* Display the flags field.  */
 
-static boolean
+boolean
 coff_arm_bfd_print_private_bfd_data (abfd, ptr)
      bfd *   abfd;
      PTR     ptr;
@@ -1890,8 +1911,10 @@ coff_arm_bfd_print_private_bfd_data (abfd, ptr)
             );
   
   if (INTERWORK_SET (abfd))
-    fprintf (file, ": [interworking %ssupported]",
+    fprintf (file, " [interworking %ssupported]",
             INTERWORK_FLAG (abfd) ? "" : "not " );
+  else
+    fprintf (file, " [interworking flag not initialised]");
   
   fputc ('\n', file);
   
@@ -1942,13 +1965,13 @@ coff_arm_bfd_set_private_flags (abfd, flags)
 /* Copy the important parts of the target specific data
    from one instance of a BFD to another.  */
 
-static boolean
+boolean
 coff_arm_bfd_copy_private_bfd_data (src, dest)
      bfd *  src;
      bfd *  dest;
 {
   BFD_ASSERT (src != NULL && dest != NULL);
-
   if (src == dest)
     return true;
 
@@ -1991,14 +2014,13 @@ coff_arm_bfd_copy_private_bfd_data (src, dest)
 
   return true;
 }
-#endif /* COFF_IMAGE_WITH_PE or not COFF_WITH_PE */
 
 /* Note:  the definitions here of LOCAL_LABEL_PREFIX and USER_LABEL_PREIFX
  *must* match the definitions on gcc/config/arm/semi.h.  */
 #define LOCAL_LABEL_PREFIX "."
 #define USER_LABEL_PREFIX "_"
 
-static boolean
+boolean
 coff_arm_is_local_label_name (abfd, name)
      bfd *        abfd;
      const char * name;
@@ -2030,6 +2052,7 @@ coff_arm_is_local_label_name (abfd, name)
     default:  return false;     /* Cannot make our minds up - default to false so that it will not be stripped by accident.  */ 
     }
 }
+#endif /* COFF_IMAGE_WITH_PE or not COFF_WITH_PE */
 
 #define coff_bfd_is_local_label_name           coff_arm_is_local_label_name
 #define coff_adjust_symndx                     coff_arm_adjust_symndx
@@ -2045,6 +2068,7 @@ extern boolean coff_arm_final_link_postscript ();
 extern boolean coff_arm_bfd_set_private_flags ();
 extern boolean coff_arm_bfd_merge_private_bfd_data ();
 extern boolean coff_arm_link_output_has_begun ();
+extern boolean coff_arm_is_local_label_name ();
 
 #if defined COFF_IMAGE_WITH_PE || ! defined COFF_WITH_PE
 /* This piece of machinery exists only to guarantee that the bfd that holds
index 753b662920338c5d0fbf4493d9191ec049026e40..5d99b0af8ed070ba0c85e717913cffdda3a593a6 100644 (file)
@@ -1327,7 +1327,7 @@ coff_mkobject_hook (abfd, filehdr, aouthdr)
     }
 #endif
 
-#if defined  ARM && ! defined COFF_WITH_PE
+#if defined ARM 
   /* Set the flags field from the COFF header read in */
   if (! coff_arm_bfd_set_private_flags (abfd, internal_f->f_flags))
     coff->flags = 0;
@@ -3461,7 +3461,7 @@ coff_slurp_symbol_table (abfd)
 #endif
 
            case C_EXT:
-#if defined ARM || defined COFF_WITH_PE
+#if defined ARM
             case C_THUMBEXT:
             case C_THUMBEXTFUNC:
 #endif
@@ -3497,7 +3497,7 @@ coff_slurp_symbol_table (abfd)
 
                  dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
 
-#if defined (COFF_WITH_PE) || defined (COFF_IMAGE_WITH_PE)
+#if defined COFF_WITH_PE
                  /* PE sets the symbol to a value relative to the
                      start of the section.  */
                  dst->symbol.value = src->u.syment.n_value;
@@ -3534,7 +3534,7 @@ coff_slurp_symbol_table (abfd)
 #ifdef I960
            case C_LEAFSTAT:    /* static leaf procedure        */
 #endif
-#if defined ARM || defined COFF_WITH_PE
+#if defined ARM 
             case C_THUMBSTAT:   /* Thumb static                  */
             case C_THUMBLABEL:  /* Thumb label                   */
             case C_THUMBSTATFUNC:/* Thumb static function        */
@@ -3549,7 +3549,7 @@ coff_slurp_symbol_table (abfd)
                 section, if there is one.  */
              if (dst->symbol.section)
                {
-#if defined (COFF_WITH_PE) || defined (COFF_IMAGE_WITH_PE)
+#if defined COFF_WITH_PE
                  /* PE sets the symbol to a value relative to the
                      start of the section.  */
                  dst->symbol.value = src->u.syment.n_value;
@@ -3659,7 +3659,7 @@ coff_slurp_symbol_table (abfd)
            case C_FCN:         /* ".bf" or ".ef"                */
            case C_EFCN:        /* physical end of function      */
              dst->symbol.flags = BSF_LOCAL;
-#if defined (COFF_WITH_PE) || defined (COFF_IMAGE_WITH_PE)
+#if defined COFF_WITH_PE
              /* PE sets the symbol to a value relative to the start
                 of the section.  */
              dst->symbol.value = src->u.syment.n_value;
index 1a45ad2ea51b2fb1139dc85ffa81fcc56c9be61d..90260668eac5c906d50934c252fedd8951c7f163 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for the generic parts of most COFF variants, for BFD.
-   Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -285,16 +285,12 @@ coff_swap_filehdr_in (abfd, src, dst)
   filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags);
   filehdr_dst->f_symptr = bfd_h_get_32 (abfd, (bfd_byte *) filehdr_src->f_symptr);
 
-  /* Other people's tools sometimes generate headers
-     with an nsyms but a zero symptr. */
-  if (filehdr_dst->f_nsyms && filehdr_dst->f_symptr)
-    {
-      filehdr_dst->f_flags |= HAS_SYMS;
-    }
-  else 
+  /* Other people's tools sometimes generate headers with an nsyms but
+     a zero symptr.  */
+  if (filehdr_dst->f_nsyms != 0 && filehdr_dst->f_symptr == 0)
     {
       filehdr_dst->f_nsyms = 0;
-      filehdr_dst->f_flags &= ~HAS_SYMS;
+      filehdr_dst->f_flags |= F_LSYMS;
     }
 
   filehdr_dst->f_opthdr = bfd_h_get_16(abfd, 
@@ -778,38 +774,38 @@ coff_swap_aouthdr_in (abfd, aouthdr_ext1, aouthdr_int1)
     GET_AOUTHDR_DATA_START (abfd, (bfd_byte *) aouthdr_ext->data_start);
 
   a = &aouthdr_int->pe;
-  a->ImageBase = bfd_h_get_32 (abfd, src->ImageBase);
-  a->SectionAlignment = bfd_h_get_32 (abfd, src->SectionAlignment);
-  a->FileAlignment = bfd_h_get_32 (abfd, src->FileAlignment);
+  a->ImageBase = bfd_h_get_32 (abfd, (bfd_byte *) src->ImageBase);
+  a->SectionAlignment = bfd_h_get_32 (abfd, (bfd_byte *) src->SectionAlignment);
+  a->FileAlignment = bfd_h_get_32 (abfd, (bfd_byte *) src->FileAlignment);
   a->MajorOperatingSystemVersion = 
-    bfd_h_get_16 (abfd, src->MajorOperatingSystemVersion);
+    bfd_h_get_16 (abfd, (bfd_byte *) src->MajorOperatingSystemVersion);
   a->MinorOperatingSystemVersion = 
-    bfd_h_get_16 (abfd, src->MinorOperatingSystemVersion);
-  a->MajorImageVersion = bfd_h_get_16 (abfd, src->MajorImageVersion);
-  a->MinorImageVersion = bfd_h_get_16 (abfd, src->MinorImageVersion);
-  a->MajorSubsystemVersion = bfd_h_get_16 (abfd, src->MajorSubsystemVersion);
-  a->MinorSubsystemVersion = bfd_h_get_16 (abfd, src->MinorSubsystemVersion);
-  a->Reserved1 = bfd_h_get_32 (abfd, src->Reserved1);
-  a->SizeOfImage = bfd_h_get_32 (abfd, src->SizeOfImage);
-  a->SizeOfHeaders = bfd_h_get_32 (abfd, src->SizeOfHeaders);
-  a->CheckSum = bfd_h_get_32 (abfd, src->CheckSum);
-  a->Subsystem = bfd_h_get_16 (abfd, src->Subsystem);
-  a->DllCharacteristics = bfd_h_get_16 (abfd, src->DllCharacteristics);
-  a->SizeOfStackReserve = bfd_h_get_32 (abfd, src->SizeOfStackReserve);
-  a->SizeOfStackCommit = bfd_h_get_32 (abfd, src->SizeOfStackCommit);
-  a->SizeOfHeapReserve = bfd_h_get_32 (abfd, src->SizeOfHeapReserve);
-  a->SizeOfHeapCommit = bfd_h_get_32 (abfd, src->SizeOfHeapCommit);
-  a->LoaderFlags = bfd_h_get_32 (abfd, src->LoaderFlags);
-  a->NumberOfRvaAndSizes = bfd_h_get_32 (abfd, src->NumberOfRvaAndSizes);
+    bfd_h_get_16 (abfd, (bfd_byte *) src->MinorOperatingSystemVersion);
+  a->MajorImageVersion = bfd_h_get_16 (abfd, (bfd_byte *) src->MajorImageVersion);
+  a->MinorImageVersion = bfd_h_get_16 (abfd, (bfd_byte *) src->MinorImageVersion);
+  a->MajorSubsystemVersion = bfd_h_get_16 (abfd, (bfd_byte *) src->MajorSubsystemVersion);
+  a->MinorSubsystemVersion = bfd_h_get_16 (abfd, (bfd_byte *) src->MinorSubsystemVersion);
+  a->Reserved1 = bfd_h_get_32 (abfd, (bfd_byte *) src->Reserved1);
+  a->SizeOfImage = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfImage);
+  a->SizeOfHeaders = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfHeaders);
+  a->CheckSum = bfd_h_get_32 (abfd, (bfd_byte *) src->CheckSum);
+  a->Subsystem = bfd_h_get_16 (abfd, (bfd_byte *) src->Subsystem);
+  a->DllCharacteristics = bfd_h_get_16 (abfd, (bfd_byte *) src->DllCharacteristics);
+  a->SizeOfStackReserve = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfStackReserve);
+  a->SizeOfStackCommit = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfStackCommit);
+  a->SizeOfHeapReserve = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfHeapReserve);
+  a->SizeOfHeapCommit = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfHeapCommit);
+  a->LoaderFlags = bfd_h_get_32 (abfd, (bfd_byte *) src->LoaderFlags);
+  a->NumberOfRvaAndSizes = bfd_h_get_32 (abfd, (bfd_byte *) src->NumberOfRvaAndSizes);
 
   {
     int idx;
     for (idx=0; idx < 16; idx++)
       {
        a->DataDirectory[idx].VirtualAddress =
-         bfd_h_get_32 (abfd, src->DataDirectory[idx][0]);
+         bfd_h_get_32 (abfd, (bfd_byte *) src->DataDirectory[idx][0]);
        a->DataDirectory[idx].Size =
-         bfd_h_get_32 (abfd, src->DataDirectory[idx][1]);
+         bfd_h_get_32 (abfd, (bfd_byte *) src->DataDirectory[idx][1]);
       }
   }
 
@@ -1138,13 +1134,13 @@ coff_swap_scnhdr_out (abfd, in, out)
     int flags = scnhdr_int->s_flags;
     if (strcmp (scnhdr_int->s_name, ".data")  == 0 ||
        strcmp (scnhdr_int->s_name, ".CRT")   == 0 ||
-       strcmp (scnhdr_int->s_name, ".rsrc")  == 0 ||
        strcmp (scnhdr_int->s_name, ".bss")   == 0)
       flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
     else if (strcmp (scnhdr_int->s_name, ".text") == 0)
       flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
     else if (strcmp (scnhdr_int->s_name, ".reloc") == 0)
-      flags = SEC_DATA| IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE;
+      flags = (SEC_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
+              | IMAGE_SCN_MEM_SHARED);
     else if (strcmp (scnhdr_int->s_name, ".idata") == 0)
       flags = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | SEC_DATA;     
     else if (strcmp (scnhdr_int->s_name, ".rdata") == 0
@@ -1164,9 +1160,12 @@ coff_swap_scnhdr_out (abfd, in, out)
     else if (strncmp (scnhdr_int->s_name, ".drectve", 8) == 0)
       flags =  IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE ;
     else if (strncmp (scnhdr_int->s_name, ".stab", 5) == 0)
-      flags |= IMAGE_SCN_LNK_INFO | IMAGE_SCN_MEM_DISCARDABLE;
+      flags |= (IMAGE_SCN_LNK_INFO | IMAGE_SCN_MEM_DISCARDABLE
+               | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ);
+    else if (strcmp (scnhdr_int->s_name, ".rsrc")  == 0)
+      flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED;
     else
-      flags = IMAGE_SCN_MEM_READ;
+      flags |= IMAGE_SCN_MEM_READ;
 
     bfd_h_put_32(abfd, flags, (bfd_byte *) scnhdr_ext->s_flags);
   }
@@ -1225,12 +1224,15 @@ pe_print_idata(abfd, vfile)
   FILE *file = (FILE *) vfile;
   bfd_byte *data = 0;
   asection *section = bfd_get_section_by_name (abfd, ".idata");
+  unsigned long adj;
 
 #ifdef POWERPC_LE_PE
   asection *rel_section = bfd_get_section_by_name (abfd, ".reldata");
 #endif
 
-  bfd_size_type datasize = 0;
+  bfd_size_type datasize;
+  bfd_size_type dataoff;
+  bfd_size_type secsize;
   bfd_size_type i;
   bfd_size_type start, stop;
   int onaline = 20;
@@ -1238,8 +1240,41 @@ pe_print_idata(abfd, vfile)
   pe_data_type *pe = pe_data (abfd);
   struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
 
-  if (section == 0)
-    return true;
+  if (section != NULL)
+    {
+      datasize = bfd_section_size (abfd, section);
+      dataoff = 0;
+
+      if (datasize == 0)
+       return true;
+    }
+  else
+    {
+      bfd_vma addr, size;
+
+      addr = extra->DataDirectory[1].VirtualAddress;
+      size = extra->DataDirectory[1].Size;
+
+      if (addr == 0 || size == 0)
+       return true;
+
+      for (section = abfd->sections; section != NULL; section = section->next)
+       {
+         if (section->vma - extra->ImageBase <= addr
+             && ((section->vma - extra->ImageBase
+                  + bfd_section_size (abfd, section))
+                 >= addr + size))
+           break;
+       }
+      if (section == NULL)
+       return true;
+
+      /* For some reason the import table size is not reliable.  The
+         import data will extend past the indicated size, and before
+         the indicated address.  */
+      dataoff = addr - (section->vma - extra->ImageBase);
+      datasize = size;
+    }
 
 #ifdef POWERPC_LE_PE
   if (rel_section != 0 && bfd_section_size (abfd, rel_section) != 0)
@@ -1291,27 +1326,22 @@ pe_print_idata(abfd, vfile)
   fprintf(file,
          "\nThe Import Tables (interpreted .idata section contents)\n");
   fprintf(file,
-         " vma:    Hint    Time      Forward  DLL       First\n");
+         " vma:            Hint    Time      Forward  DLL       First\n");
   fprintf(file,
-         "         Table   Stamp     Chain    Name      Thunk\n");
+         "                 Table   Stamp     Chain    Name      Thunk\n");
 
-  if (bfd_section_size (abfd, section) == 0)
-    return true;
-
-  data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
-  datasize = bfd_section_size (abfd, section);
-  if (data == NULL && datasize != 0)
+  secsize = bfd_section_size (abfd, section);
+  data = (bfd_byte *) bfd_malloc (secsize);
+  if (data == NULL && secsize != 0)
     return false;
 
-  bfd_get_section_contents (abfd, 
-                           section, 
-                           (PTR) data, 0, 
-                           bfd_section_size (abfd, section));
-
-  start = 0;
+  if (! bfd_get_section_contents (abfd, section, (PTR) data, 0, secsize))
+    return false;
 
-  stop = bfd_section_size (abfd, section);
+  adj = (extra->ImageBase - section->vma) & 0xffffffff;
 
+  start = dataoff;
+  stop = dataoff + datasize;
   for (i = start; i < stop; i += onaline)
     {
       bfd_vma hint_addr;
@@ -1322,11 +1352,10 @@ pe_print_idata(abfd, vfile)
       int idx;
       int j;
       char *dll;
-      int adj = (extra->ImageBase - section->vma) & 0xffffffff;
 
       fprintf (file,
-              " %04lx\t", 
-              (unsigned long int) (i + section->vma));
+              " %08lx\t", 
+              (unsigned long int) (i + section->vma + dataoff));
       
       if (i+20 > stop)
        {
@@ -1347,33 +1376,52 @@ pe_print_idata(abfd, vfile)
              dll_name,
              first_thunk);
 
-      if (hint_addr ==0)
-       {
-         break;
-       }
+      if (hint_addr == 0 && first_thunk == 0)
+       break;
 
       /* the image base is present in the section->vma */
       dll = (char *) data + dll_name + adj;
       fprintf(file, "\n\tDLL Name: %s\n", dll);
-      fprintf(file, "\tvma:  Ordinal  Member-Name\n");
 
-      idx = hint_addr + adj;
-
-      for (j=0;j<stop;j+=4)
+      if (hint_addr != 0)
        {
-         int ordinal;
-         char *member_name;
-         bfd_vma member = bfd_get_32(abfd, data + idx + j);
-         if (member == 0)
-           break;
-         ordinal = bfd_get_16(abfd,
-                              data + member + adj);
-         member_name = (char *) data + member + adj + 2;
-         fprintf(file, "\t%04lx\t %4d  %s\n",
-                 member, ordinal, member_name);
+         fprintf (file, "\tvma:  Hint/Ord Member-Name\n");
+
+         idx = hint_addr + adj;
+
+         for (j = 0; j < stop; j += 4)
+           {
+             unsigned long member = bfd_get_32 (abfd, data + idx + j);
+
+             if (member == 0)
+               break;
+             if (member & 0x80000000)
+               fprintf (file, "\t%04lx\t %4lu", member,
+                        member & 0x7fffffff);
+             else
+               {
+                 int ordinal;
+                 char *member_name;
+
+                 ordinal = bfd_get_16 (abfd, data + member + adj);
+                 member_name = (char *) data + member + adj + 2;
+                 fprintf (file, "\t%04lx\t %4d  %s",
+                          member, ordinal, member_name);
+               }
+
+             /* If the time stamp is not zero, the import address
+                 table holds actual addresses.  */
+             if (time_stamp != 0
+                 && first_thunk != 0
+                 && first_thunk != hint_addr)
+               fprintf (file, "\t%04lx",
+                        bfd_get_32 (abfd, data + first_thunk + adj + j));
+
+             fprintf (file, "\n");
+           }
        }
 
-      if (hint_addr != first_thunk
+      if (hint_addr != first_thunk && time_stamp == 0)
        {
          int differ = 0;
          int idx2;
@@ -1384,15 +1432,27 @@ pe_print_idata(abfd, vfile)
            {
              int ordinal;
              char *member_name;
-             bfd_vma hint_member = bfd_get_32(abfd, data + idx + j);
-             bfd_vma iat_member = bfd_get_32(abfd, data + idx2 + j);
-             if (hint_member != iat_member)
+             bfd_vma hint_member;
+             bfd_vma iat_member;
+
+             if (time_stamp != 0)
+               {
+               }
+
+             if (hint_addr != 0)
+               hint_member = bfd_get_32 (abfd, data + idx + j);
+             iat_member = bfd_get_32 (abfd, data + idx2 + j);
+
+             if (hint_addr == 0 && iat_member == 0)
+               break;
+
+             if (hint_addr == 0 || hint_member != iat_member)
                {
                  if (differ == 0)
                    {
-                     fprintf(file, 
-                             "\tThe Import Address Table (difference found)\n");
-                     fprintf(file, "\tvma:  Ordinal  Member-Name\n");
+                     fprintf (file, 
+                              "\tThe Import Address Table (difference found)\n");
+                     fprintf(file, "\tvma:  Hint/Ord Member-Name\n");
                      differ = 1;
                    }
                  if (iat_member == 0)
@@ -1408,9 +1468,9 @@ pe_print_idata(abfd, vfile)
                      fprintf(file, "\t%04lx\t %4d  %s\n",
                              iat_member, ordinal, member_name);
                    }
-                 break;
                }
-             if (hint_member == 0)
+
+             if (hint_addr != 0 && hint_member == 0)
                break;
            }
          if (differ == 0)
@@ -1438,7 +1498,8 @@ pe_print_edata (abfd, vfile)
   bfd_byte *data = 0;
   asection *section = bfd_get_section_by_name (abfd, ".edata");
 
-  bfd_size_type datasize = 0;
+  bfd_size_type datasize;
+  bfd_size_type dataoff;
   bfd_size_type i;
 
   int adj;
@@ -1460,20 +1521,43 @@ pe_print_edata (abfd, vfile)
   pe_data_type *pe = pe_data (abfd);
   struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
 
-  if (section == 0)
-    return true;
+  if (section != NULL)
+    {
+      datasize = bfd_section_size (abfd, section);
+      dataoff = 0;
+    }
+  else
+    {
+      bfd_vma addr, size;
 
-  data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, 
-                                                            section));
-  datasize = bfd_section_size (abfd, section);
+      addr = extra->DataDirectory[0].VirtualAddress;
+      size = extra->DataDirectory[0].Size;
 
+      if (addr == 0 || size == 0)
+       return true;
+
+      for (section = abfd->sections; section != NULL; section = section->next)
+       {
+         if (section->vma - extra->ImageBase <= addr
+             && ((section->vma - extra->ImageBase
+                  + bfd_section_size (abfd, section))
+                 >= addr + size))
+           break;
+       }
+      if (section == NULL)
+       return true;
+
+      datasize = size;
+      dataoff = addr - (section->vma - extra->ImageBase);
+    }
+
+  data = (bfd_byte *) bfd_malloc (datasize);
   if (data == NULL && datasize != 0)
     return false;
 
-  bfd_get_section_contents (abfd, 
-                           section, 
-                           (PTR) data, 0, 
-                           bfd_section_size (abfd, section));
+  if (! bfd_get_section_contents (abfd, section, (PTR) data, dataoff,
+                                 datasize))
+    return false;
 
   /* Go get Export Directory Table */
   edt.export_flags   = bfd_get_32(abfd, data+0); 
@@ -1488,7 +1572,7 @@ pe_print_edata (abfd, vfile)
   edt.npt_addr       = bfd_get_32(abfd, data+32); 
   edt.ot_addr        = bfd_get_32(abfd, data+36);
 
-  adj = (extra->ImageBase - section->vma) & 0xffffffff;
+  adj = (extra->ImageBase - (section->vma + dataoff)) & 0xffffffff;
 
 
   /* Dump the EDT first first */
@@ -1558,12 +1642,11 @@ pe_print_edata (abfd, vfile)
 
   for (i = 0; i < edt.num_functions; ++i)
     {
-      bfd_vma eat_member = bfd_get_32(abfd, 
-                                     data + edt.eat_addr + (i*4) + adj);
+      bfd_vma eat_member = bfd_get_32 (abfd, 
+                                      data + edt.eat_addr + (i * 4) + adj);
       bfd_vma eat_actual = (extra->ImageBase + eat_member) & 0xffffffff;
-      bfd_vma edata_start = bfd_get_section_vma(abfd,section);
-      bfd_vma edata_end = edata_start + bfd_section_size (abfd, section);
-
+      bfd_vma edata_start = bfd_get_section_vma (abfd,section) + dataoff;
+      bfd_vma edata_end = edata_start + datasize;
 
       if (eat_member == 0)
        continue;
@@ -1827,6 +1910,24 @@ pe_print_private_bfd_data (abfd, vfile)
   pe_data_type *pe = pe_data (abfd);
   struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr;
 
+  /* The MS dumpbin program reportedly ands with 0xff0f before
+     printing the characteristics field.  Not sure why.  No reason to
+     emulate it here.  */
+  fprintf (file, "\nCharacteristics 0x%x\n", pe->real_flags);
+#undef PF
+#define PF(x, y)    if (pe->real_flags & x) { fprintf (file, "\t%s\n", y); }
+  PF (F_RELFLG, "relocations stripped");
+  PF (F_EXEC, "executable");
+  PF (F_LNNO, "line numbers stripped");
+  PF (F_LSYMS, "symbols stripped");
+  PF (0x80, "little endian");
+  PF (F_AR32WR, "32 bit words");
+  PF (0x200, "debugging information removed");
+  PF (0x1000, "system file");
+  PF (F_DLL, "DLL");
+  PF (0x8000, "big endian");
+#undef PF
+
   fprintf (file,"\nImageBase\t\t");
   fprintf_vma (file, i->ImageBase);
   fprintf (file,"\nSectionAlignment\t");
@@ -1870,7 +1971,8 @@ pe_print_private_bfd_data (abfd, vfile)
   pe_print_pdata(abfd, vfile);
   pe_print_reloc(abfd, vfile);
 
-  return true;
+  fputc ('\n', file);
+  return coff_arm_bfd_print_private_bfd_data (abfd, vfile);
 }
 
 static boolean
@@ -1933,6 +2035,9 @@ pe_mkobject_hook (abfd, filehdr, aouthdr)
     }
 #endif
 
+  if (! coff_arm_bfd_set_private_flags (abfd, internal_f->f_flags))
+    coff_data (abfd) ->flags = 0;
+  
   return (PTR) pe;
 }
 
@@ -1956,7 +2061,7 @@ pe_bfd_copy_private_bfd_data (ibfd, obfd)
   pe_data (obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr;
   pe_data (obfd)->dll = pe_data (ibfd)->dll;
 
-  return true;
+  return coff_arm_bfd_copy_private_bfd_data (ibfd, obfd);
 }
 
 #ifdef COFF_IMAGE_WITH_PE