*** empty log message ***
[deliverable/binutils-gdb.git] / bfd / peXXigen.c
index 70163055bc736d8b2d24a2e7364ad6026343c524..5fa874ea02266cb789f33d91220276bee5d1ecf7 100644 (file)
@@ -1,6 +1,6 @@
 /* Support for the generic parts of PE/PEI; the common executable parts.
    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005 Free Software Foundation, Inc.
+   2005, 2006 Free Software Foundation, Inc.
    Written by Cygnus Solutions.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -52,8 +52,8 @@
    on this code has a chance of getting something accomplished without
    wasting too much time.  */
 
-/* This expands into COFF_WITH_pe or COFF_WITH_pep depending on whether
-   we're compiling for straight PE or PE+.  */
+/* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64
+   depending on whether we're compiling for straight PE or PE+.  */
 #define COFF_WITH_XX
 
 #include "bfd.h"
@@ -67,7 +67,9 @@
    within PE/PEI, so we get them from there.  FIXME: The lack of
    variance is an assumption which may prove to be incorrect if new
    PE/PEI targets are created.  */
-#ifdef COFF_WITH_pep
+#if defined COFF_WITH_pex64
+# include "coff/x86_64.h"
+#elif defined COFF_WITH_pep
 # include "coff/ia64.h"
 #else
 # include "coff/i386.h"
@@ -77,7 +79,7 @@
 #include "libcoff.h"
 #include "libpei.h"
 
-#ifdef COFF_WITH_pep
+#if defined COFF_WITH_pep || defined COFF_WITH_pex64
 # undef AOUTSZ
 # define AOUTSZ                PEPAOUTSZ
 # define PEAOUTHDR     PEPAOUTHDR
@@ -147,6 +149,7 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1)
          int unused_section_number = 0;
          asection *sec;
          char *name;
+         flagword flags;
 
          for (sec = abfd->sections; sec; sec = sec->next)
            if (unused_section_number <= sec->target_index)
@@ -156,7 +159,8 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1)
          if (name == NULL)
            return;
          strcpy (name, in->n_name);
-         sec = bfd_make_section_anyway (abfd, name);
+         flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD;
+         sec = bfd_make_section_anyway_with_flags (abfd, name, flags);
 
          sec->vma = 0;
          sec->lma = 0;
@@ -169,7 +173,6 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1)
          sec->userdata = NULL;
          sec->next = NULL;
          sec->alignment_power = 2;
-         sec->flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD;
 
          sec->target_index = unused_section_number;
 
@@ -398,7 +401,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
   aouthdr_int->text_start =
     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   aouthdr_int->data_start =
     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
@@ -441,6 +444,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
         /* If data directory is empty, rva also should be 0.  */
        int size =
          H_GET_32 (abfd, src->DataDirectory[idx][1]);
+
        a->DataDirectory[idx].Size = size;
 
        if (size)
@@ -454,7 +458,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   if (aouthdr_int->entry)
     {
       aouthdr_int->entry += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->entry &= 0xffffffff;
 #endif
     }
@@ -462,12 +466,12 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   if (aouthdr_int->tsize)
     {
       aouthdr_int->text_start += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->text_start &= 0xffffffff;
 #endif
     }
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   if (aouthdr_int->dsize)
     {
@@ -547,7 +551,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->tsize)
     {
       aouthdr_in->text_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->text_start &= 0xffffffff;
 #endif
     }
@@ -555,7 +559,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->dsize)
     {
       aouthdr_in->data_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->data_start &= 0xffffffff;
 #endif
     }
@@ -563,7 +567,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->entry)
     {
       aouthdr_in->entry -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->entry &= 0xffffffff;
 #endif
     }
@@ -660,7 +664,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
                          aouthdr_out->standard.text_start);
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
                          aouthdr_out->standard.data_start);
@@ -1261,6 +1265,38 @@ pe_print_idata (bfd * abfd, void * vfile)
            }
 
          /* Print HintName vector entries.  */
+#ifdef COFF_WITH_pex64
+         for (j = 0; j < datasize; j += 8)
+           {
+             unsigned long member = bfd_get_32 (abfd, data + idx + j);
+             unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4);
+
+             if (!member && !member_high)
+               break;
+
+             if (member_high & 0x80000000)
+               fprintf (file, "\t%lx%08lx\t %4lx%08lx  <none>",
+                        member_high,member, member_high & 0x7fffffff, member);
+             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",
+                        (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
+             fprintf (file, "\n");
+           }
+#else
          for (j = 0; j < datasize; j += 4)
            {
              unsigned long member = bfd_get_32 (abfd, data + idx + j);
@@ -1293,7 +1329,7 @@ pe_print_idata (bfd * abfd, void * vfile)
 
              fprintf (file, "\n");
            }
-
+#endif
          if (ft_allocated)
            free (ft_data);
        }
@@ -1533,10 +1569,10 @@ pe_print_edata (bfd * abfd, void * vfile)
 static bfd_boolean
 pe_print_pdata (bfd * abfd, void * vfile)
 {
-#ifdef COFF_WITH_pep
-# define PDATA_ROW_SIZE        (3*8)
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
+# define PDATA_ROW_SIZE        (3 * 8)
 #else
-# define PDATA_ROW_SIZE        (5*4)
+# define PDATA_ROW_SIZE        (5 * 4)
 #endif
   FILE *file = (FILE *) vfile;
   bfd_byte *data = 0;
@@ -1559,7 +1595,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
 
   fprintf (file,
           _("\nThe Function Table (interpreted .pdata section contents)\n"));
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   fprintf (file,
           _(" vma:\t\t\tBegin Address    End Address      Unwind Info\n"));
 #else
@@ -1613,7 +1649,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
       fprintf_vma (file, begin_addr); fputc (' ', file);
       fprintf_vma (file, end_addr); fputc (' ', file);
       fprintf_vma (file, eh_handler);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
       fputc (' ', file);
       fprintf_vma (file, eh_data); fputc (' ', file);
       fprintf_vma (file, prolog_end_addr);
@@ -1949,6 +1985,7 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
 {
   struct coff_link_hash_entry *h1;
   struct bfd_link_info *info = pfinfo->info;
+  bfd_boolean result = TRUE;
 
   /* There are a few fields that need to be filled in now while we
      have symbol table access.
@@ -1962,49 +1999,103 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
                              ".idata$2", FALSE, FALSE, TRUE);
   if (h1 != NULL)
     {
-      pe_data (abfd)->pe_opthdr.DataDirectory[1].VirtualAddress =
-       (h1->root.u.def.value
-        + h1->root.u.def.section->output_section->vma
-        + h1->root.u.def.section->output_offset);
+      /* PR ld/2729: We cannot rely upon all the output sections having been 
+        created properly, so check before referencing them.  Issue a warning
+        message for any sections tht could not be found.  */
+      if (h1->root.u.def.section != NULL
+         && h1->root.u.def.section->output_section != NULL)
+       pe_data (abfd)->pe_opthdr.DataDirectory[1].VirtualAddress =
+         (h1->root.u.def.value
+          + h1->root.u.def.section->output_section->vma
+          + h1->root.u.def.section->output_offset);
+      else
+       {
+         _bfd_error_handler
+           (_("%B: unable to fill in DataDictionary[1] because .idata$2 is missing"), 
+            abfd);
+         result = FALSE;
+       }
+
       h1 = coff_link_hash_lookup (coff_hash_table (info),
                                  ".idata$4", FALSE, FALSE, TRUE);
-      pe_data (abfd)->pe_opthdr.DataDirectory[1].Size =
-       ((h1->root.u.def.value
-         + h1->root.u.def.section->output_section->vma
-         + h1->root.u.def.section->output_offset)
-        - pe_data (abfd)->pe_opthdr.DataDirectory[1].VirtualAddress);
+      if (h1 != NULL
+         && h1->root.u.def.section != NULL
+         && h1->root.u.def.section->output_section != NULL)
+       pe_data (abfd)->pe_opthdr.DataDirectory[1].Size =
+         ((h1->root.u.def.value
+           + h1->root.u.def.section->output_section->vma
+           + h1->root.u.def.section->output_offset)
+          - pe_data (abfd)->pe_opthdr.DataDirectory[1].VirtualAddress);
+      else
+       {
+         _bfd_error_handler
+           (_("%B: unable to fill in DataDictionary[1] because .idata$4 is missing"), 
+            abfd);
+         result = FALSE;
+       }
 
       /* The import address table.  This is the size/address of
          .idata$5.  */
       h1 = coff_link_hash_lookup (coff_hash_table (info),
                                  ".idata$5", FALSE, FALSE, TRUE);
-      pe_data (abfd)->pe_opthdr.DataDirectory[12].VirtualAddress =
-       (h1->root.u.def.value
-        + h1->root.u.def.section->output_section->vma
-        + h1->root.u.def.section->output_offset);
+      if (h1 != NULL
+         && h1->root.u.def.section != NULL
+         && h1->root.u.def.section->output_section != NULL)
+       pe_data (abfd)->pe_opthdr.DataDirectory[12].VirtualAddress =
+         (h1->root.u.def.value
+          + h1->root.u.def.section->output_section->vma
+          + h1->root.u.def.section->output_offset);
+      else
+       {
+         _bfd_error_handler
+           (_("%B: unable to fill in DataDictionary[12] because .idata$5 is missing"), 
+            abfd);
+         result = FALSE;
+       }
+
       h1 = coff_link_hash_lookup (coff_hash_table (info),
                                  ".idata$6", FALSE, FALSE, TRUE);
-      pe_data (abfd)->pe_opthdr.DataDirectory[12].Size =
-       ((h1->root.u.def.value
-         + h1->root.u.def.section->output_section->vma
-         + h1->root.u.def.section->output_offset)
-        - pe_data (abfd)->pe_opthdr.DataDirectory[12].VirtualAddress);      
+      if (h1 != NULL
+         && h1->root.u.def.section != NULL
+         && h1->root.u.def.section->output_section != NULL)
+       pe_data (abfd)->pe_opthdr.DataDirectory[12].Size =
+         ((h1->root.u.def.value
+           + h1->root.u.def.section->output_section->vma
+           + h1->root.u.def.section->output_offset)
+          - pe_data (abfd)->pe_opthdr.DataDirectory[12].VirtualAddress);      
+      else
+       {
+         _bfd_error_handler
+           (_("%B: unable to fill in DataDictionary[12] because .idata$6 is missing"), 
+            abfd);
+         result = FALSE;
+       }
     }
 
   h1 = coff_link_hash_lookup (coff_hash_table (info),
                              "__tls_used", FALSE, FALSE, TRUE);
   if (h1 != NULL)
     {
-      pe_data (abfd)->pe_opthdr.DataDirectory[9].VirtualAddress =
-       (h1->root.u.def.value
-        + h1->root.u.def.section->output_section->vma
-        + h1->root.u.def.section->output_offset
-        - pe_data (abfd)->pe_opthdr.ImageBase);
+      if (h1->root.u.def.section != NULL
+         && h1->root.u.def.section->output_section != NULL)
+       pe_data (abfd)->pe_opthdr.DataDirectory[9].VirtualAddress =
+         (h1->root.u.def.value
+          + h1->root.u.def.section->output_section->vma
+          + h1->root.u.def.section->output_offset
+          - pe_data (abfd)->pe_opthdr.ImageBase);
+      else
+       {
+         _bfd_error_handler
+           (_("%B: unable to fill in DataDictionary[9] because __tls_used is missing"), 
+            abfd);
+         result = FALSE;
+       }
+
       pe_data (abfd)->pe_opthdr.DataDirectory[9].Size = 0x18;
     }
 
   /* If we couldn't find idata$2, we either have an excessively
      trivial program or are in DEEP trouble; we have to assume trivial
      program....  */
-  return TRUE;
+  return result;
 }
This page took 0.030437 seconds and 4 git commands to generate.