* peicode.h (coff_swap_aux_in): Swap in extra PE x_scn fields.
[deliverable/binutils-gdb.git] / bfd / peicode.h
index ab244e10ec9e68f8a0871c34cfb4bb6c449910d7..3b8091e623a68d638a3f9496e4238bab1897bd56 100644 (file)
@@ -29,13 +29,14 @@ Most of this hacked by  Steve Chamberlain,
 #define coff_mkobject pe_mkobject
 #define coff_mkobject_hook pe_mkobject_hook
 
-
 #ifndef GET_FCN_LNNOPTR
-#define GET_FCN_LNNOPTR(abfd, ext)  bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#define GET_FCN_LNNOPTR(abfd, ext) \
+     bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
 #endif
 
 #ifndef GET_FCN_ENDNDX
-#define GET_FCN_ENDNDX(abfd, ext)  bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
+#define GET_FCN_ENDNDX(abfd, ext)  \
+       bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
 #endif
 
 #ifndef PUT_FCN_LNNOPTR
@@ -187,7 +188,6 @@ coff_swap_reloc_in (abfd, src, dst)
   reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET(abfd,
                                             (bfd_byte *) reloc_src->r_offset);
 #endif
-
 }
 
 
@@ -228,13 +228,30 @@ coff_swap_filehdr_in (abfd, src, dst)
   filehdr_dst->f_magic = bfd_h_get_16(abfd, (bfd_byte *) filehdr_src->f_magic);
   filehdr_dst->f_nscns = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_nscns);
   filehdr_dst->f_timdat = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_timdat);
-  filehdr_dst->f_symptr =
-    bfd_h_get_32 (abfd, (bfd_byte *) filehdr_src->f_symptr);
+
   filehdr_dst->f_nsyms = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_nsyms);
-  filehdr_dst->f_opthdr = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_opthdr);
   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 
+    {
+      filehdr_dst->f_symptr = 0;
+      filehdr_dst->f_nsyms = 0;
+      filehdr_dst->f_flags &= ~HAS_SYMS;
+    }
+
+  filehdr_dst->f_opthdr = bfd_h_get_16(abfd, 
+                                      (bfd_byte *)filehdr_src-> f_opthdr);
 }
 
+#ifdef COFF_IMAGE_WITH_PE
+
 static  unsigned int
 coff_swap_filehdr_out (abfd, in, out)
      bfd       *abfd;
@@ -309,7 +326,6 @@ coff_swap_filehdr_out (abfd, in, out)
   bfd_h_put_16(abfd, filehdr_in->f_opthdr, (bfd_byte *) filehdr_out->f_opthdr);
   bfd_h_put_16(abfd, filehdr_in->f_flags, (bfd_byte *) filehdr_out->f_flags);
 
-
   /* put in extra dos header stuff.  This data remains essentially
      constant, it just has to be tacked on to the beginning of all exes 
      for NT */
@@ -363,7 +379,30 @@ coff_swap_filehdr_out (abfd, in, out)
 
   return sizeof(FILHDR);
 }
+#else
 
+static  unsigned int
+coff_swap_filehdr_out (abfd, in, out)
+     bfd       *abfd;
+     PTR       in;
+     PTR       out;
+{
+  struct internal_filehdr *filehdr_in = (struct internal_filehdr *)in;
+  FILHDR *filehdr_out = (FILHDR *)out;
+
+  bfd_h_put_16(abfd, filehdr_in->f_magic, (bfd_byte *) filehdr_out->f_magic);
+  bfd_h_put_16(abfd, filehdr_in->f_nscns, (bfd_byte *) filehdr_out->f_nscns);
+  bfd_h_put_32(abfd, filehdr_in->f_timdat, (bfd_byte *) filehdr_out->f_timdat);
+  PUT_FILEHDR_SYMPTR (abfd, (bfd_vma) filehdr_in->f_symptr,
+                     (bfd_byte *) filehdr_out->f_symptr);
+  bfd_h_put_32(abfd, filehdr_in->f_nsyms, (bfd_byte *) filehdr_out->f_nsyms);
+  bfd_h_put_16(abfd, filehdr_in->f_opthdr, (bfd_byte *) filehdr_out->f_opthdr);
+  bfd_h_put_16(abfd, filehdr_in->f_flags, (bfd_byte *) filehdr_out->f_flags);
+
+  return sizeof(FILHDR);
+}
+
+#endif
 
 
 static void
@@ -386,6 +425,7 @@ coff_swap_sym_in (abfd, ext1, in1)
     memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN);
 #endif
   }
+
   in->n_value = bfd_h_get_32(abfd, (bfd_byte *) ext->e_value); 
   in->n_scnum = bfd_h_get_16(abfd, (bfd_byte *) ext->e_scnum);
   if (sizeof(ext->e_type) == 2){
@@ -415,6 +455,10 @@ coff_swap_sym_in (abfd, ext1, in1)
     /*    else */
     /*      in->n_scnum = 2; */
   }
+
+#ifdef coff_swap_sym_in_hook
+  coff_swap_sym_in_hook(abfd, ext1, in1);
+#endif
 }
 
 static unsigned int
@@ -436,6 +480,7 @@ coff_swap_sym_out (abfd, inp, extp)
     memcpy(ext->e.e_name, in->_n._n_name, SYMNMLEN);
 #endif
   }
+
   bfd_h_put_32(abfd,  in->n_value , (bfd_byte *) ext->e_value);
   bfd_h_put_16(abfd,  in->n_scnum , (bfd_byte *) ext->e_scnum);
   if (sizeof(ext->e_type) == 2)
@@ -448,6 +493,7 @@ coff_swap_sym_out (abfd, inp, extp)
     }
   bfd_h_put_8(abfd,  in->n_sclass , ext->e_sclass);
   bfd_h_put_8(abfd,  in->n_numaux , ext->e_numaux);
+
   return sizeof(SYMENT);
 }
 
@@ -489,6 +535,12 @@ coff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
       in->x_scn.x_scnlen = GET_SCN_SCNLEN(abfd, ext);
       in->x_scn.x_nreloc = GET_SCN_NRELOC(abfd, ext);
       in->x_scn.x_nlinno = GET_SCN_NLINNO(abfd, ext);
+      in->x_scn.x_checksum = bfd_h_get_32 (abfd,
+                                          (bfd_byte *) ext->x_scn.x_checksum);
+      in->x_scn.x_associated =
+       bfd_h_get_16 (abfd, (bfd_byte *) ext->x_scn.x_associated);
+      in->x_scn.x_comdat = bfd_h_get_8 (abfd,
+                                       (bfd_byte *) ext->x_scn.x_comdat);
       return;
     }
     break;
@@ -569,6 +621,12 @@ coff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
       PUT_SCN_SCNLEN(abfd, in->x_scn.x_scnlen, ext);
       PUT_SCN_NRELOC(abfd, in->x_scn.x_nreloc, ext);
       PUT_SCN_NLINNO(abfd, in->x_scn.x_nlinno, ext);
+      bfd_h_put_32 (abfd, in->x_scn.x_checksum,
+                   (bfd_byte *) ext->x_scn.x_checksum);
+      bfd_h_put_16 (abfd, in->x_scn.x_associated,
+                   (bfd_byte *) ext->x_scn.x_associated);
+      bfd_h_put_8 (abfd, in->x_scn.x_comdat,
+                  (bfd_byte *) ext->x_scn.x_comdat);
       return sizeof (AUXENT);
     }
     break;
@@ -725,13 +783,12 @@ static void add_data_entry (abfd, aout, idx, name, base)
   /* add import directory information if it exists */
   if (sec != NULL)
     {
-      aout->DataDirectory[idx].VirtualAddress = sec->lma - base;
-      aout->DataDirectory[idx].Size = sec->_raw_size;
+      aout->DataDirectory[idx].VirtualAddress = sec->vma - base;
+      aout->DataDirectory[idx].Size = sec->_cooked_size;
       sec->flags |= SEC_DATA;
     }
 }
 
-
 static unsigned int
 coff_swap_aouthdr_out (abfd, in, out)
      bfd       *abfd;
@@ -769,15 +826,46 @@ coff_swap_aouthdr_out (abfd, in, out)
   add_data_entry (abfd, extra, 0, ".edata", ib);
   add_data_entry (abfd, extra, 1, ".idata", ib);
   add_data_entry (abfd, extra, 2, ".rsrc" ,ib);
+
+#ifdef POWERPC_LE_PE
+  /* FIXME: do other PE platforms use this? */
+  add_data_entry (abfd, extra, 3, ".pdata" ,ib);
+#endif
+
   add_data_entry (abfd, extra, 5, ".reloc", ib);
+
+#ifdef POWERPC_LE_PE
+  /* On the PPC NT system, this field is set up as follows. It is
+     not an "officially" reserved field, so it currently has no title.
+     first_thunk_address is idata$5, and the thunk_size is the size
+     of the idata$5 chunk of the idata section.
+  */
+  extra->DataDirectory[12].VirtualAddress = first_thunk_address;
+  extra->DataDirectory[12].Size = thunk_size;
+
+  /* On the PPC NT system, the size of the directory entry is not the
+     size of the entire section. It's actually offset to the end of 
+     the idata$3 component of the idata section. This is the size of
+     the entire import table. (also known as the start of idata$4)
+  */
+  extra->DataDirectory[1].Size = import_table_size;
+#endif
+
   {
     asection *sec;
     bfd_vma dsize= 0;
     bfd_vma isize = SA(abfd->sections->filepos);
     bfd_vma tsize= 0;
+
     for (sec = abfd->sections; sec; sec = sec->next)
       {
        int rounded = FA(sec->_raw_size);
+
+       if (strcmp(sec->name,".junk") == 0)
+         {
+           continue;
+         }
+
        if (sec->flags & SEC_DATA) 
          dsize += rounded;
        if (sec->flags & SEC_CODE)
@@ -792,13 +880,22 @@ coff_swap_aouthdr_out (abfd, in, out)
 
   extra->SizeOfHeaders = abfd->sections->filepos;
   bfd_h_put_16(abfd, aouthdr_in->magic, (bfd_byte *) aouthdr_out->standard.magic);
-  bfd_h_put_16(abfd, aouthdr_in->vstamp, (bfd_byte *) aouthdr_out->standard.vstamp);
+
+#ifdef POWERPC_LE_PE
+  /* this little piece of magic sets the "linker version" field to 2.60 */
+  bfd_h_put_16(abfd, 2  + 60 * 256, (bfd_byte *) aouthdr_out->standard.vstamp);
+#else
+  /* this little piece of magic sets the "linker version" field to 2.55 */
+  bfd_h_put_16(abfd, 2  + 55 * 256, (bfd_byte *) aouthdr_out->standard.vstamp);
+#endif
+
   PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, (bfd_byte *) aouthdr_out->standard.tsize);
   PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, (bfd_byte *) aouthdr_out->standard.dsize);
   PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, (bfd_byte *) aouthdr_out->standard.bsize);
   PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, (bfd_byte *) aouthdr_out->standard.entry);
   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
                          (bfd_byte *) aouthdr_out->standard.text_start);
+
   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
                          (bfd_byte *) aouthdr_out->standard.data_start);
 
@@ -856,7 +953,6 @@ coff_swap_aouthdr_out (abfd, in, out)
       }
   }
 
-
   return sizeof(AOUTHDR);
 }
 
@@ -891,6 +987,11 @@ static void
     {
       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
     }
+  if (strcmp (scnhdr_int->s_name, _BSS) == 0) 
+    {
+      scnhdr_int->s_size = scnhdr_int->s_paddr;
+      scnhdr_int->s_paddr = 0;
+    }
 }
 
 static unsigned int
@@ -907,7 +1008,6 @@ coff_swap_scnhdr_out (abfd, in, out)
 
   memcpy(scnhdr_ext->s_name, scnhdr_int->s_name, sizeof(scnhdr_int->s_name));
 
-
   PUT_SCNHDR_VADDR (abfd, 
                    (scnhdr_int->s_vaddr 
                     - pe_data(abfd)->pe_opthdr.ImageBase),
@@ -950,6 +1050,11 @@ coff_swap_scnhdr_out (abfd, in, out)
      section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE
      (0x02000000).  Also, the resource data should also be read and
      writable.  */
+
+  /* FIXME: alignment is also encoded in this field, at least on ppc (krk) */
+  /* FIXME: even worse, I don't see how to get the original alignment field*/
+  /*        back...                                                        */
+
   {
     int flags = scnhdr_int->s_flags;
     if (strcmp (scnhdr_int->s_name, ".data")  == 0 ||
@@ -966,6 +1071,31 @@ coff_swap_scnhdr_out (abfd, in, out)
     else if (strcmp (scnhdr_int->s_name, ".rdata") == 0
             || strcmp (scnhdr_int->s_name, ".edata") == 0)
       flags =  IMAGE_SCN_MEM_READ | SEC_DATA;     
+    /* ppc-nt additions */
+    else if (strcmp (scnhdr_int->s_name, ".pdata") == 0)
+      flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES |
+                         IMAGE_SCN_MEM_READ ;
+    /* Remember this field is a max of 8 chars, so the null is _not_ there
+       for an 8 character name like ".reldata". (yep. Stupid bug) */
+    else if (strncmp (scnhdr_int->s_name, ".reldata", strlen(".reldata")) == 0)
+      flags =  IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES |
+              IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ;
+    else if (strcmp (scnhdr_int->s_name, ".ydata") == 0)
+      flags =  IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES |
+              IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ;
+    else if (strcmp (scnhdr_int->s_name, ".drectve") == 0)
+      flags =  IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE ;
+    /* end of ppc-nt additions */
+#ifdef POWERPC_LE_PE
+    else if (strncmp (scnhdr_int->s_name, ".stabstr", strlen(".stabstr")) == 0)
+      {
+       flags =  IMAGE_SCN_LNK_INFO;
+      }
+    else if (strcmp (scnhdr_int->s_name, ".stab") == 0)
+      {
+       flags =  IMAGE_SCN_LNK_INFO;
+      }
+#endif
 
     bfd_h_put_32(abfd, flags, (bfd_byte *) scnhdr_ext->s_flags);
   }
@@ -994,23 +1124,641 @@ coff_swap_scnhdr_out (abfd, in, out)
     }
   return ret;
 }
+
+static char * dir_names[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = 
+{
+  "Export Directory [.edata]",
+  "Import Directory [parts of .idata]",
+  "Resource Directory [.rsrc]",
+  "Exception Directory [.pdata]",
+  "Security Directory",
+  "Base Relocation Directory [.reloc]",
+  "Debug Directory",
+  "Description Directory",
+  "Special Directory",
+  "Thread Storage Directory [.tls]",
+  "Load Configuration Directory",
+  "Bound Import Directory",
+  "Import Address Table Directory",
+  "Reserved",
+  "Reserved",
+  "Reserved"
+};
+
 /**********************************************************************/
 static boolean
-pe_print_private_bfd_data (abfd, vfile)
+pe_print_idata(abfd, vfile)
+     bfd*abfd;
+     void *vfile;
+{
+  FILE *file = vfile;
+  bfd_byte *data = 0;
+  asection *section = bfd_get_section_by_name (abfd, ".idata");
+
+#ifdef POWERPC_LE_PE
+  asection *rel_section = bfd_get_section_by_name (abfd, ".reldata");
+#endif
+
+  bfd_size_type datasize = 0;
+  bfd_size_type i;
+  bfd_size_type start, stop;
+  int onaline = 20;
+
+  pe_data_type *pe = pe_data (abfd);
+  struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
+
+  if (section == 0)
+    return true;
+
+#ifdef POWERPC_LE_PE
+  if (rel_section != 0 && bfd_section_size (abfd, rel_section) != 0)
+    {
+      /* The toc address can be found by taking the starting address,
+        which on the PPC locates a function descriptor. The descriptor
+        consists of the function code starting address followed by the
+        address of the toc. The starting address we get from the bfd,
+        and the descriptor is supposed to be in the .reldata section. 
+      */
+
+      bfd_vma loadable_toc_address;
+      bfd_vma toc_address;
+      bfd_vma start_address;
+      bfd_byte *data = 0;
+      int offset;
+      data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, 
+                                                                rel_section));
+      if (data == NULL && bfd_section_size (abfd, rel_section) != 0)
+       return false;
+
+      datasize = bfd_section_size (abfd, rel_section);
+  
+      bfd_get_section_contents (abfd, 
+                               rel_section, 
+                               (PTR) data, 0, 
+                               bfd_section_size (abfd, rel_section));
+
+      offset = abfd->start_address - rel_section->vma;
+
+      start_address = bfd_get_32(abfd, data+offset);
+      loadable_toc_address = bfd_get_32(abfd, data+offset+4);
+      toc_address = loadable_toc_address - 32768;
+
+      fprintf(file,
+             "\nFunction descriptor located at the start address: %04lx\n",
+             (unsigned long int) (abfd->start_address));
+      fprintf (file,
+              "\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n", 
+              start_address, loadable_toc_address, toc_address);
+    }
+#endif
+
+  fprintf(file,
+         "\nThe Import Tables (interpreted .idata section contents)\n");
+  fprintf(file,
+         " vma:    Hint    Time      Forward  DLL       First\n");
+  fprintf(file,
+         "         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)
+    return false;
+
+  bfd_get_section_contents (abfd, 
+                           section, 
+                           (PTR) data, 0, 
+                           bfd_section_size (abfd, section));
+
+  start = 0;
+
+  stop = bfd_section_size (abfd, section);
+
+  for (i = start; i < stop; i += onaline)
+    {
+      bfd_vma hint_addr;
+      bfd_vma time_stamp;
+      bfd_vma forward_chain;
+      bfd_vma dll_name;
+      bfd_vma first_thunk;
+      int idx;
+      int j;
+      char *dll;
+      int adj = extra->ImageBase - section->vma;
+
+      fprintf (file,
+              " %04lx\t", 
+              (unsigned long int) (i + section->vma));
+      
+      if (i+20 > stop)
+       {
+         /* check stuff */
+         ;
+       }
+      
+      hint_addr = bfd_get_32(abfd, data+i);
+      time_stamp = bfd_get_32(abfd, data+i+4);
+      forward_chain = bfd_get_32(abfd, data+i+8);
+      dll_name = bfd_get_32(abfd, data+i+12);
+      first_thunk = bfd_get_32(abfd, data+i+16);
+      
+      fprintf(file, "%08lx %08lx %08lx %08lx %08lx\n",
+             hint_addr,
+             time_stamp,
+             forward_chain,
+             dll_name,
+             first_thunk);
+
+      if (hint_addr ==0)
+       {
+         break;
+       }
+
+      /* the image base is present in the section->vma */
+      dll = 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)
+       {
+         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 = data + member + adj + 2;
+         fprintf(file, "\t%04lx\t %4d  %s\n",
+                 member, ordinal, member_name);
+       }
+
+      if (hint_addr != first_thunk) 
+       {
+         int differ = 0;
+         int idx2;
+
+         idx2 = first_thunk + adj;
+
+         for (j=0;j<stop;j+=4)
+           {
+             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)
+               {
+                 if (differ == 0)
+                   {
+                     fprintf(file, 
+                             "\tThe Import Address Table (difference found)\n");
+                     fprintf(file, "\tvma:  Ordinal  Member-Name\n");
+                     differ = 1;
+                   }
+                 if (iat_member == 0)
+                   {
+                     fprintf(file,
+                             "\t>>> Ran out of IAT members!\n");
+                   }
+                 else 
+                   {
+                     ordinal = bfd_get_16(abfd,
+                                          data + iat_member + adj);
+                     member_name = data + iat_member + adj + 2;
+                     fprintf(file, "\t%04lx\t %4d  %s\n",
+                             iat_member, ordinal, member_name);
+                   }
+                 break;
+               }
+             if (hint_member == 0)
+               break;
+           }
+         if (differ == 0)
+           {
+             fprintf(file,
+                     "\tThe Import Address Table is identical\n");
+           }
+       }
+
+      fprintf(file, "\n");
+
+    }
+
+  free (data);
+
+  return true;
+}
+
+static boolean
+pe_print_edata(abfd, vfile)
+     bfd*abfd;
+     void *vfile;
+{
+  FILE *file = vfile;
+  bfd_byte *data = 0;
+  asection *section = bfd_get_section_by_name (abfd, ".edata");
+
+  bfd_size_type datasize = 0;
+  bfd_size_type i;
+
+  int adj;
+  struct EDT_type 
+    {
+      long export_flags;             /* reserved - should be zero */
+      long time_stamp;
+      short major_ver;
+      short minor_ver;
+      bfd_vma name;                  /* rva - relative to image base */
+      long base;                     /* ordinal base */
+      long num_functions;        /* Number in the export address table */
+      long num_names;            /* Number in the name pointer table */
+      bfd_vma eat_addr;    /* rva to the export address table */
+      bfd_vma npt_addr;        /* rva to the Export Name Pointer Table */
+      bfd_vma ot_addr; /* rva to the Ordinal Table */
+    } edt;
+
+  pe_data_type *pe = pe_data (abfd);
+  struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
+
+  if (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)
+    return false;
+
+  bfd_get_section_contents (abfd, 
+                           section, 
+                           (PTR) data, 0, 
+                           bfd_section_size (abfd, section));
+
+  /* Go get Export Directory Table */
+  edt.export_flags   = bfd_get_32(abfd, data+0); 
+  edt.time_stamp     = bfd_get_32(abfd, data+4);
+  edt.major_ver      = bfd_get_16(abfd, data+8);
+  edt.minor_ver      = bfd_get_16(abfd, data+10);
+  edt.name           = bfd_get_32(abfd, data+12);
+  edt.base           = bfd_get_32(abfd, data+16);
+  edt.num_functions  = bfd_get_32(abfd, data+20); 
+  edt.num_names      = bfd_get_32(abfd, data+24); 
+  edt.eat_addr       = bfd_get_32(abfd, data+28);
+  edt.npt_addr       = bfd_get_32(abfd, data+32); 
+  edt.ot_addr        = bfd_get_32(abfd, data+36);
+
+  adj = extra->ImageBase - section->vma;
+
+
+  /* Dump the EDT first first */
+  fprintf(file,
+         "\nThe Export Tables (interpreted .edata section contents)\n\n");
+
+  fprintf(file,
+         "Export Flags \t\t\t%lx\n", (unsigned long) edt.export_flags);
+
+  fprintf(file,
+         "Time/Date stamp \t\t%lx\n", (unsigned long) edt.time_stamp);
+
+  fprintf(file,
+         "Major/Minor \t\t\t%d/%d\n", edt.major_ver, edt.minor_ver);
+
+  fprintf (file,
+          "Name \t\t\t\t");
+  fprintf_vma (file, edt.name);
+  fprintf (file,
+          "%s\n", data + edt.name + adj);
+
+  fprintf(file,
+         "Ordinal Base \t\t\t%ld\n", edt.base);
+
+  fprintf(file,
+         "Number in:\n");
+
+  fprintf(file,
+         "\tExport Address Table \t\t%lx\n",
+         (unsigned long) edt.num_functions);
+
+  fprintf(file,
+         "\t[Name Pointer/Ordinal] Table\t%ld\n", edt.num_names);
+
+  fprintf(file,
+         "Table Addresses\n");
+
+  fprintf (file,
+          "\tExport Address Table \t\t");
+  fprintf_vma (file, edt.eat_addr);
+  fprintf (file, "\n");
+
+  fprintf (file,
+         "\tName Pointer Table \t\t");
+  fprintf_vma (file, edt.npt_addr);
+  fprintf (file, "\n");
+
+  fprintf (file,
+          "\tOrdinal Table \t\t\t");
+  fprintf_vma (file, edt.ot_addr);
+  fprintf (file, "\n");
+
+  
+  /* The next table to find si the Export Address Table. It's basically
+     a list of pointers that either locate a function in this dll, or
+     forward the call to another dll. Something like:
+      typedef union 
+      {
+        long export_rva;
+        long forwarder_rva;
+      } export_address_table_entry;
+  */
+
+  fprintf(file,
+         "\nExport Address Table -- Ordinal Base %ld\n",
+         edt.base);
+
+  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_actual = extra->ImageBase + eat_member;
+      bfd_vma edata_start = bfd_get_section_vma(abfd,section);
+      bfd_vma edata_end = edata_start + bfd_section_size (abfd, section);
+
+
+      if (eat_member == 0)
+       continue;
+
+      if (edata_start < eat_actual && eat_actual < edata_end) 
+       {
+         /* this rva is to a name (forwarding function) in our section */
+         /* Should locate a function descriptor */
+         fprintf(file,
+                 "\t[%4ld] +base[%4ld] %04lx %s -- %s\n", 
+                 (long) i, (long) (i + edt.base), eat_member,
+                 "Forwarder RVA", data + eat_member + adj);
+       }
+      else
+       {
+         /* Should locate a function descriptor in the reldata section */
+         fprintf(file,
+                 "\t[%4ld] +base[%4ld] %04lx %s\n", 
+                 (long) i, (long) (i + edt.base), eat_member, "Export RVA");
+       }
+    }
+
+  /* The Export Name Pointer Table is paired with the Export Ordinal Table */
+  /* Dump them in parallel for clarity */
+  fprintf(file,
+         "\n[Ordinal/Name Pointer] Table\n");
+
+  for (i = 0; i < edt.num_names; ++i)
+    {
+      bfd_vma name_ptr = bfd_get_32(abfd, 
+                                   data + 
+                                   edt.npt_addr
+                                   + (i*4) + adj);
+      
+      char *name = data + name_ptr + adj;
+
+      bfd_vma ord = bfd_get_16(abfd, 
+                                   data + 
+                                   edt.ot_addr
+                                   + (i*2) + adj);
+      fprintf(file,
+             "\t[%4ld] %s\n", (long) ord, name);
+
+    }
+
+  free (data);
+
+  return true;
+}
+
+static boolean
+pe_print_pdata(abfd, vfile)
+     bfd*abfd;
+     void *vfile;
+{
+  FILE *file = vfile;
+  bfd_byte *data = 0;
+  asection *section = bfd_get_section_by_name (abfd, ".pdata");
+  bfd_size_type datasize = 0;
+  bfd_size_type i;
+  bfd_size_type start, stop;
+  int onaline = 20;
+
+  if (section == 0)
+    return true;
+
+  stop = bfd_section_size (abfd, section);
+  if ((stop % onaline) != 0)
+    fprintf (file, "Warning, .pdata section size (%ld) is not a multiple of %d\n",
+            (long)stop, onaline);
+
+  fprintf(file,
+         "\nThe Function Table (interpreted .pdata section contents)\n");
+  fprintf(file,
+         " vma:\t\tBegin    End      EH       EH       PrologEnd\n");
+  fprintf(file,
+         "     \t\tAddress  Address  Handler  Data     Address\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)
+    return false;
+
+  bfd_get_section_contents (abfd, 
+                           section, 
+                           (PTR) data, 0, 
+                           bfd_section_size (abfd, section));
+
+  start = 0;
+
+  for (i = start; i < stop; i += onaline)
+    {
+      bfd_vma begin_addr;
+      bfd_vma end_addr;
+      bfd_vma eh_handler;
+      bfd_vma eh_data;
+      bfd_vma prolog_end_addr;
+
+      if (i+20 > stop)
+         break;
+      
+      begin_addr = bfd_get_32(abfd, data+i);
+      end_addr = bfd_get_32(abfd, data+i+4);
+      eh_handler = bfd_get_32(abfd, data+i+8);
+      eh_data = bfd_get_32(abfd, data+i+12);
+      prolog_end_addr = bfd_get_32(abfd, data+i+16);
+      
+      if (begin_addr == 0 && end_addr == 0 && eh_handler == 0
+         && eh_data == 0 && prolog_end_addr == 0)
+       {
+         /* We are probably into the padding of the
+            section now */
+         break;
+       }
+
+      fprintf (file,
+              " %08lx\t", 
+              (unsigned long int) (i + section->vma));
+
+      fprintf(file, "%08lx %08lx %08lx %08lx %08lx",
+             begin_addr,
+             end_addr,
+             eh_handler,
+             eh_data,
+             prolog_end_addr);
+
+#ifdef POWERPC_LE_PE
+      if (eh_handler == 0 && eh_data != 0)
+       {
+         /* Special bits here, although the meaning may */
+         /* be a little mysterious. The only one I know */
+         /* for sure is 0x03.                           */
+         /* Code Significance                           */
+         /* 0x00 None                                   */
+         /* 0x01 Register Save Millicode                */
+         /* 0x02 Register Restore Millicode             */
+         /* 0x03 Glue Code Sequence                     */
+         switch (eh_data)
+           {
+           case 0x01:
+             fprintf(file, " Register save millicode");
+             break;
+           case 0x02:
+             fprintf(file, " Register restore millicode");
+             break;
+           case 0x03:
+             fprintf(file, " Glue code sequence");
+             break;
+           default:
+             break;
+           }
+       }
+#endif    
+      fprintf(file, "\n");
+    }
+
+  free (data);
+
+  return true;
+}
+
+static const char *tbl[6] =
+{
+"ABSOLUTE",
+"HIGH",
+"LOW",
+"HIGHLOW",
+"HIGHADJ",
+"unknown"
+};
+
+static boolean
+pe_print_reloc(abfd, vfile)
      bfd*abfd;
      void *vfile;
 {
   FILE *file = vfile;
+  bfd_byte *data = 0;
+  asection *section = bfd_get_section_by_name (abfd, ".reloc");
+  bfd_size_type datasize = 0;
+  bfd_size_type i;
+  bfd_size_type start, stop;
+
+  if (section == 0)
+    return true;
+
+  if (bfd_section_size (abfd, section) == 0)
+    return true;
+
+  fprintf(file,
+         "\n\nPE File Base Relocations (interpreted .reloc"
+         " section contents)\n");
+
+  data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
+  datasize = bfd_section_size (abfd, section);
+  if (data == NULL && datasize != 0)
+    return false;
+
+  bfd_get_section_contents (abfd, 
+                           section, 
+                           (PTR) data, 0, 
+                           bfd_section_size (abfd, section));
+
+  start = 0;
+
+  stop = bfd_section_size (abfd, section);
+
+  for (i = start; i < stop;)
+    {
+      int j;
+      bfd_vma virtual_address;
+      long number, size;
+
+      /* The .reloc section is a sequence of blocks, with a header consisting
+        of two 32 bit quantities, followed by a number of 16 bit entries */
+
+      virtual_address = bfd_get_32(abfd, data+i);
+      size = bfd_get_32(abfd, data+i+4);
+      number = (size - 8) / 2;
+
+      if (size == 0) 
+       {
+         break;
+       }
+
+      fprintf (file,
+              "\nVirtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n",
+              virtual_address, size, size, number);
+
+      for (j = 0; j < number; ++j)
+       {
+         unsigned short e = bfd_get_16(abfd, data + i + 8 + j*2);
+         int t =   (e & 0xF000) >> 12;
+         int off = e & 0x0FFF;
+
+         if (t > 5) 
+           abort();
+
+         fprintf(file,
+                 "\treloc %4d offset %4x [%4lx] %s\n", 
+                 j, off, (long) (off + virtual_address), tbl[t]);
+         
+       }
+      i += size;
+    }
+
+  free (data);
+
+  return true;
+}
+
+static boolean
+pe_print_private_bfd_data (abfd, vfile)
+     bfd *abfd;
+     PTR vfile;
+{
+  FILE *file = (FILE *) vfile;
   int j;
   pe_data_type *pe = pe_data (abfd);
   struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr;
-  fprintf (file,"ImageBase\t\t");
+
+  fprintf (file,"\nImageBase\t\t");
   fprintf_vma (file, i->ImageBase);
-  fprintf (file,"SectionAlignment\t");
+  fprintf (file,"\nSectionAlignment\t");
   fprintf_vma (file, i->SectionAlignment);
-  fprintf (file,"FileAlignment\t\t");
+  fprintf (file,"\nFileAlignment\t\t");
   fprintf_vma (file, i->FileAlignment);
-  fprintf (file,"MajorOSystemVersion\t%d\n", i->MajorOperatingSystemVersion);
+  fprintf (file,"\nMajorOSystemVersion\t%d\n", i->MajorOperatingSystemVersion);
   fprintf (file,"MinorOSystemVersion\t%d\n", i->MinorOperatingSystemVersion);
   fprintf (file,"MajorImageVersion\t%d\n", i->MajorImageVersion);
   fprintf (file,"MinorImageVersion\t%d\n", i->MinorImageVersion);
@@ -1024,22 +1772,29 @@ pe_print_private_bfd_data (abfd, vfile)
   fprintf (file,"DllCharacteristics\t%08x\n", i->DllCharacteristics);
   fprintf (file,"SizeOfStackReserve\t");
   fprintf_vma (file, i->SizeOfStackReserve);
-  fprintf (file,"SizeOfStackCommit\t");
+  fprintf (file,"\nSizeOfStackCommit\t");
   fprintf_vma (file, i->SizeOfStackCommit);
-  fprintf (file,"SizeOfHeapReserve\t");
+  fprintf (file,"\nSizeOfHeapReserve\t");
   fprintf_vma (file, i->SizeOfHeapReserve);
-  fprintf (file,"SizeOfHeapCommit\t");
+  fprintf (file,"\nSizeOfHeapCommit\t");
   fprintf_vma (file, i->SizeOfHeapCommit);
-  fprintf (file,"LoaderFlags\t\t%08lx\n", i->LoaderFlags);
+  fprintf (file,"\nLoaderFlags\t\t%08lx\n", i->LoaderFlags);
   fprintf (file,"NumberOfRvaAndSizes\t%08lx\n", i->NumberOfRvaAndSizes);
 
+  fprintf (file,"\nThe Data Directory\n");
   for (j = 0; j < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; j++) 
     {
-      fprintf (file, "Entry %2d ", j);
+      fprintf (file, "Entry %1x ", j);
       fprintf_vma (file, i->DataDirectory[j].VirtualAddress);
-      fprintf (file, " %08lx\n", i->DataDirectory[j].Size);
+      fprintf (file, " %08lx ", i->DataDirectory[j].Size);
+      fprintf (file, "%s\n", dir_names[j]);
     }
 
+  pe_print_idata(abfd, vfile);
+  pe_print_edata(abfd, vfile);
+  pe_print_pdata(abfd, vfile);
+  pe_print_reloc(abfd, vfile);
+
   return true;
 }
 
@@ -1048,16 +1803,16 @@ pe_mkobject (abfd)
      bfd * abfd;
 {
   pe_data_type *pe;
-
   abfd->tdata.pe_obj_data = 
     (struct pe_tdata *) bfd_zalloc (abfd, sizeof (pe_data_type));
+
   if (abfd->tdata.pe_obj_data == 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
-  pe =pe_data (abfd);
+    return false;
+
+  pe = pe_data (abfd);
+
   pe->coff.pe = 1;
+  pe->in_reloc_p = in_reloc_p;
   return true;
 }
 
@@ -1075,9 +1830,7 @@ pe_mkobject_hook (abfd, filehdr, aouthdr)
     return NULL;
 
   pe = pe_data (abfd);
-
   pe->coff.sym_filepos = internal_f->f_symptr;
-
   /* These members communicate important constants about the symbol
      table to GDB's symbol-reading code.  These `constants'
      unfortunately vary among coff implementations...  */
@@ -1093,10 +1846,35 @@ pe_mkobject_hook (abfd, filehdr, aouthdr)
     obj_conv_table_size (abfd) =
       internal_f->f_nsyms;
 
-  pe->pe_opthdr = ((struct internal_aouthdr *)aouthdr)->pe;
+  pe->real_flags = internal_f->f_flags;
+
+#ifdef COFF_IMAGE_WITH_PE
+  if (aouthdr) 
+    {
+      pe->pe_opthdr = ((struct internal_aouthdr *)aouthdr)->pe;
+    }
+#endif
+
   return (PTR) pe;
 }
 
 
 
+/* Copy any private info we understand from the input bfd
+   to the output bfd.  */
+
+#define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data
 
+static boolean
+pe_bfd_copy_private_bfd_data (ibfd, obfd)
+     bfd *ibfd, *obfd;
+{
+  /* One day we may try to grok other private data.  */
+  if (ibfd->xvec->flavour != bfd_target_coff_flavour
+      || obfd->xvec->flavour != bfd_target_coff_flavour)
+    return true;
+
+  pe_data(obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr;
+
+  return true;
+}
This page took 0.0351 seconds and 4 git commands to generate.