Back to index

cell-binutils  2.17cvs20070401
peicode.h
Go to the documentation of this file.
00001 /* Support for the generic parts of PE/PEI, for BFD.
00002    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
00003    2005, 2006 Free Software Foundation, Inc.
00004    Written by Cygnus Solutions.
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 /* Most of this hacked by  Steve Chamberlain,
00023                      sac@cygnus.com
00024 
00025    PE/PEI rearrangement (and code added): Donn Terry
00026                                        Softway Systems, Inc.  */
00027 
00028 /* Hey look, some documentation [and in a place you expect to find it]!
00029 
00030    The main reference for the pei format is "Microsoft Portable Executable
00031    and Common Object File Format Specification 4.1".  Get it if you need to
00032    do some serious hacking on this code.
00033 
00034    Another reference:
00035    "Peering Inside the PE: A Tour of the Win32 Portable Executable
00036    File Format", MSJ 1994, Volume 9.
00037 
00038    The *sole* difference between the pe format and the pei format is that the
00039    latter has an MSDOS 2.0 .exe header on the front that prints the message
00040    "This app must be run under Windows." (or some such).
00041    (FIXME: Whether that statement is *really* true or not is unknown.
00042    Are there more subtle differences between pe and pei formats?
00043    For now assume there aren't.  If you find one, then for God sakes
00044    document it here!)
00045 
00046    The Microsoft docs use the word "image" instead of "executable" because
00047    the former can also refer to a DLL (shared library).  Confusion can arise
00048    because the `i' in `pei' also refers to "image".  The `pe' format can
00049    also create images (i.e. executables), it's just that to run on a win32
00050    system you need to use the pei format.
00051 
00052    FIXME: Please add more docs here so the next poor fool that has to hack
00053    on this code has a chance of getting something accomplished without
00054    wasting too much time.  */
00055 
00056 #include "libpei.h"
00057 
00058 static bfd_boolean (*pe_saved_coff_bfd_print_private_bfd_data) (bfd *, void *) =
00059 #ifndef coff_bfd_print_private_bfd_data
00060      NULL;
00061 #else
00062      coff_bfd_print_private_bfd_data;
00063 #undef coff_bfd_print_private_bfd_data
00064 #endif
00065 
00066 static bfd_boolean                      pe_print_private_bfd_data (bfd *, void *);
00067 #define coff_bfd_print_private_bfd_data pe_print_private_bfd_data
00068 
00069 static bfd_boolean (*pe_saved_coff_bfd_copy_private_bfd_data) (bfd *, bfd *) =
00070 #ifndef coff_bfd_copy_private_bfd_data
00071      NULL;
00072 #else
00073      coff_bfd_copy_private_bfd_data;
00074 #undef coff_bfd_copy_private_bfd_data
00075 #endif
00076 
00077 static bfd_boolean                     pe_bfd_copy_private_bfd_data (bfd *, bfd *);
00078 #define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data
00079 
00080 #define coff_mkobject      pe_mkobject
00081 #define coff_mkobject_hook pe_mkobject_hook
00082 
00083 #ifdef COFF_IMAGE_WITH_PE
00084 /* This structure contains static variables used by the ILF code.  */
00085 typedef asection * asection_ptr;
00086 
00087 typedef struct
00088 {
00089   bfd *                     abfd;
00090   bfd_byte *         data;
00091   struct bfd_in_memory * bim;
00092   unsigned short        magic;
00093 
00094   arelent *          reltab;
00095   unsigned int              relcount;
00096 
00097   coff_symbol_type *        sym_cache;
00098   coff_symbol_type *        sym_ptr;
00099   unsigned int              sym_index;
00100 
00101   unsigned int *     sym_table;
00102   unsigned int *     table_ptr;
00103 
00104   combined_entry_type * native_syms;
00105   combined_entry_type * native_ptr;
00106 
00107   coff_symbol_type **       sym_ptr_table;
00108   coff_symbol_type **       sym_ptr_ptr;
00109 
00110   unsigned int              sec_index;
00111 
00112   char *                string_table;
00113   char *                string_ptr;
00114   char *             end_string_ptr;
00115 
00116   SYMENT *              esym_table;
00117   SYMENT *              esym_ptr;
00118 
00119   struct internal_reloc * int_reltab;
00120 }
00121 pe_ILF_vars;
00122 #endif /* COFF_IMAGE_WITH_PE */
00123 
00124 #ifndef NO_COFF_RELOCS
00125 static void
00126 coff_swap_reloc_in (bfd * abfd, void * src, void * dst)
00127 {
00128   RELOC *reloc_src = (RELOC *) src;
00129   struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
00130 
00131   reloc_dst->r_vaddr  = H_GET_32 (abfd, reloc_src->r_vaddr);
00132   reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
00133   reloc_dst->r_type   = H_GET_16 (abfd, reloc_src->r_type);
00134 #ifdef SWAP_IN_RELOC_OFFSET
00135   reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET (abfd, reloc_src->r_offset);
00136 #endif
00137 }
00138 
00139 static unsigned int
00140 coff_swap_reloc_out (bfd * abfd, void * src, void * dst)
00141 {
00142   struct internal_reloc *reloc_src = (struct internal_reloc *) src;
00143   struct external_reloc *reloc_dst = (struct external_reloc *) dst;
00144 
00145   H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
00146   H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
00147   H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
00148 
00149 #ifdef SWAP_OUT_RELOC_OFFSET 
00150   SWAP_OUT_RELOC_OFFSET (abfd, reloc_src->r_offset, reloc_dst->r_offset);
00151 #endif
00152 #ifdef SWAP_OUT_RELOC_EXTRA
00153   SWAP_OUT_RELOC_EXTRA (abfd, reloc_src, reloc_dst);
00154 #endif
00155   return RELSZ;
00156 }
00157 #endif /* not NO_COFF_RELOCS */
00158 
00159 static void
00160 coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
00161 {
00162   FILHDR *filehdr_src = (FILHDR *) src;
00163   struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
00164 
00165   filehdr_dst->f_magic  = H_GET_16 (abfd, filehdr_src->f_magic);
00166   filehdr_dst->f_nscns  = H_GET_16 (abfd, filehdr_src->f_nscns);
00167   filehdr_dst->f_timdat = H_GET_32 (abfd, filehdr_src->f_timdat);
00168   filehdr_dst->f_nsyms  = H_GET_32 (abfd, filehdr_src->f_nsyms);
00169   filehdr_dst->f_flags  = H_GET_16 (abfd, filehdr_src->f_flags);
00170   filehdr_dst->f_symptr = H_GET_32 (abfd, filehdr_src->f_symptr);
00171 
00172   /* Other people's tools sometimes generate headers with an nsyms but
00173      a zero symptr.  */
00174   if (filehdr_dst->f_nsyms != 0 && filehdr_dst->f_symptr == 0)
00175     {
00176       filehdr_dst->f_nsyms = 0;
00177       filehdr_dst->f_flags |= F_LSYMS;
00178     }
00179 
00180   filehdr_dst->f_opthdr = H_GET_16 (abfd, filehdr_src-> f_opthdr);
00181 }
00182 
00183 #ifdef COFF_IMAGE_WITH_PE
00184 # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out
00185 #elif defined COFF_WITH_pex64
00186 # define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out
00187 #elif defined COFF_WITH_pep
00188 # define coff_swap_filehdr_out _bfd_pep_only_swap_filehdr_out
00189 #else
00190 # define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
00191 #endif
00192 
00193 static void
00194 coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
00195 {
00196   SCNHDR *scnhdr_ext = (SCNHDR *) ext;
00197   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
00198 
00199   memcpy (scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
00200 
00201   scnhdr_int->s_vaddr   = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
00202   scnhdr_int->s_paddr   = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
00203   scnhdr_int->s_size    = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
00204   scnhdr_int->s_scnptr  = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
00205   scnhdr_int->s_relptr  = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
00206   scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
00207   scnhdr_int->s_flags   = H_GET_32 (abfd, scnhdr_ext->s_flags);
00208 
00209   /* MS handles overflow of line numbers by carrying into the reloc
00210      field (it appears).  Since it's supposed to be zero for PE
00211      *IMAGE* format, that's safe.  This is still a bit iffy.  */
00212 #ifdef COFF_IMAGE_WITH_PE
00213   scnhdr_int->s_nlnno = (H_GET_16 (abfd, scnhdr_ext->s_nlnno)
00214                       + (H_GET_16 (abfd, scnhdr_ext->s_nreloc) << 16));
00215   scnhdr_int->s_nreloc = 0;
00216 #else
00217   scnhdr_int->s_nreloc = H_GET_16 (abfd, scnhdr_ext->s_nreloc);
00218   scnhdr_int->s_nlnno = H_GET_16 (abfd, scnhdr_ext->s_nlnno);
00219 #endif
00220 
00221   if (scnhdr_int->s_vaddr != 0)
00222     {
00223       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
00224       /* Do not cut upper 32-bits for 64-bit vma.  */
00225 #ifndef COFF_WITH_pex64
00226       scnhdr_int->s_vaddr &= 0xffffffff;
00227 #endif
00228     }
00229 
00230 #ifndef COFF_NO_HACK_SCNHDR_SIZE
00231   /* If this section holds uninitialized data and is from an object file
00232      or from an executable image that has not initialized the field,
00233      or if the image is an executable file and the physical size is padded,
00234      use the virtual size (stored in s_paddr) instead.  */
00235   if (scnhdr_int->s_paddr > 0
00236       && (((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0
00237           && (! bfd_pe_executable_p (abfd) || scnhdr_int->s_size == 0))
00238           || (bfd_pe_executable_p (abfd) && scnhdr_int->s_size > scnhdr_int->s_paddr)))
00239   /* This code used to set scnhdr_int->s_paddr to 0.  However,
00240      coff_set_alignment_hook stores s_paddr in virt_size, which
00241      only works if it correctly holds the virtual size of the
00242      section.  */
00243     scnhdr_int->s_size = scnhdr_int->s_paddr;
00244 #endif
00245 }
00246 
00247 static bfd_boolean
00248 pe_mkobject (bfd * abfd)
00249 {
00250   pe_data_type *pe;
00251   bfd_size_type amt = sizeof (pe_data_type);
00252 
00253   abfd->tdata.pe_obj_data = (struct pe_tdata *) bfd_zalloc (abfd, amt);
00254 
00255   if (abfd->tdata.pe_obj_data == 0)
00256     return FALSE;
00257 
00258   pe = pe_data (abfd);
00259 
00260   pe->coff.pe = 1;
00261 
00262   /* in_reloc_p is architecture dependent.  */
00263   pe->in_reloc_p = in_reloc_p;
00264 
00265 #ifdef PEI_FORCE_MINIMUM_ALIGNMENT
00266   pe->force_minimum_alignment = 1;
00267 #endif
00268 #ifdef PEI_TARGET_SUBSYSTEM
00269   pe->target_subsystem = PEI_TARGET_SUBSYSTEM;
00270 #endif
00271 
00272   return TRUE;
00273 }
00274 
00275 /* Create the COFF backend specific information.  */
00276 
00277 static void *
00278 pe_mkobject_hook (bfd * abfd,
00279                 void * filehdr,
00280                 void * aouthdr ATTRIBUTE_UNUSED)
00281 {
00282   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
00283   pe_data_type *pe;
00284 
00285   if (! pe_mkobject (abfd))
00286     return NULL;
00287 
00288   pe = pe_data (abfd);
00289   pe->coff.sym_filepos = internal_f->f_symptr;
00290   /* These members communicate important constants about the symbol
00291      table to GDB's symbol-reading code.  These `constants'
00292      unfortunately vary among coff implementations...  */
00293   pe->coff.local_n_btmask = N_BTMASK;
00294   pe->coff.local_n_btshft = N_BTSHFT;
00295   pe->coff.local_n_tmask = N_TMASK;
00296   pe->coff.local_n_tshift = N_TSHIFT;
00297   pe->coff.local_symesz = SYMESZ;
00298   pe->coff.local_auxesz = AUXESZ;
00299   pe->coff.local_linesz = LINESZ;
00300 
00301   pe->coff.timestamp = internal_f->f_timdat;
00302 
00303   obj_raw_syment_count (abfd) =
00304     obj_conv_table_size (abfd) =
00305       internal_f->f_nsyms;
00306 
00307   pe->real_flags = internal_f->f_flags;
00308 
00309   if ((internal_f->f_flags & F_DLL) != 0)
00310     pe->dll = 1;
00311 
00312   if ((internal_f->f_flags & IMAGE_FILE_DEBUG_STRIPPED) == 0)
00313     abfd->flags |= HAS_DEBUG;
00314 
00315 #ifdef COFF_IMAGE_WITH_PE
00316   if (aouthdr)
00317     pe->pe_opthdr = ((struct internal_aouthdr *) aouthdr)->pe;
00318 #endif
00319 
00320 #ifdef ARM
00321   if (! _bfd_coff_arm_set_private_flags (abfd, internal_f->f_flags))
00322     coff_data (abfd) ->flags = 0;
00323 #endif
00324 
00325   return (void *) pe;
00326 }
00327 
00328 static bfd_boolean
00329 pe_print_private_bfd_data (bfd *abfd, void * vfile)
00330 {
00331   FILE *file = (FILE *) vfile;
00332 
00333   if (!_bfd_XX_print_private_bfd_data_common (abfd, vfile))
00334     return FALSE;
00335 
00336   if (pe_saved_coff_bfd_print_private_bfd_data == NULL)
00337     return TRUE;
00338 
00339   fputc ('\n', file);
00340 
00341   return pe_saved_coff_bfd_print_private_bfd_data (abfd, vfile);
00342 }
00343 
00344 /* Copy any private info we understand from the input bfd
00345    to the output bfd.  */
00346 
00347 static bfd_boolean
00348 pe_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
00349 {
00350   /* PR binutils/716: Copy the large address aware flag.
00351      XXX: Should we be copying other flags or other fields in the pe_data()
00352      structure ?  */
00353   if (pe_data (obfd) != NULL
00354       && pe_data (ibfd) != NULL
00355       && pe_data (ibfd)->real_flags & IMAGE_FILE_LARGE_ADDRESS_AWARE)
00356     pe_data (obfd)->real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
00357       
00358   if (!_bfd_XX_bfd_copy_private_bfd_data_common (ibfd, obfd))
00359     return FALSE;
00360 
00361   if (pe_saved_coff_bfd_copy_private_bfd_data)
00362     return pe_saved_coff_bfd_copy_private_bfd_data (ibfd, obfd);
00363 
00364   return TRUE;
00365 }
00366 
00367 #define coff_bfd_copy_private_section_data \
00368   _bfd_XX_bfd_copy_private_section_data
00369 
00370 #define coff_get_symbol_info _bfd_XX_get_symbol_info
00371 
00372 #ifdef COFF_IMAGE_WITH_PE
00373 
00374 /* Code to handle Microsoft's Image Library Format.
00375    Also known as LINK6 format.
00376    Documentation about this format can be found at:
00377 
00378    http://msdn.microsoft.com/library/specs/pecoff_section8.htm  */
00379 
00380 /* The following constants specify the sizes of the various data
00381    structures that we have to create in order to build a bfd describing
00382    an ILF object file.  The final "+ 1" in the definitions of SIZEOF_IDATA6
00383    and SIZEOF_IDATA7 below is to allow for the possibility that we might
00384    need a padding byte in order to ensure 16 bit alignment for the section's
00385    contents.
00386 
00387    The value for SIZEOF_ILF_STRINGS is computed as follows:
00388 
00389       There will be NUM_ILF_SECTIONS section symbols.  Allow 9 characters
00390       per symbol for their names (longest section name is .idata$x).
00391 
00392       There will be two symbols for the imported value, one the symbol name
00393       and one with _imp__ prefixed.  Allowing for the terminating nul's this
00394       is strlen (symbol_name) * 2 + 8 + 21 + strlen (source_dll).
00395 
00396       The strings in the string table must start STRING__SIZE_SIZE bytes into
00397       the table in order to for the string lookup code in coffgen/coffcode to
00398       work.  */
00399 #define NUM_ILF_RELOCS             8
00400 #define NUM_ILF_SECTIONS        6
00401 #define NUM_ILF_SYMS               (2 + NUM_ILF_SECTIONS)
00402 
00403 #define SIZEOF_ILF_SYMS             (NUM_ILF_SYMS * sizeof (* vars.sym_cache))
00404 #define SIZEOF_ILF_SYM_TABLE        (NUM_ILF_SYMS * sizeof (* vars.sym_table))
00405 #define SIZEOF_ILF_NATIVE_SYMS      (NUM_ILF_SYMS * sizeof (* vars.native_syms))
00406 #define SIZEOF_ILF_SYM_PTR_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_ptr_table))
00407 #define SIZEOF_ILF_EXT_SYMS  (NUM_ILF_SYMS * sizeof (* vars.esym_table))
00408 #define SIZEOF_ILF_RELOCS    (NUM_ILF_RELOCS * sizeof (* vars.reltab))
00409 #define SIZEOF_ILF_INT_RELOCS       (NUM_ILF_RELOCS * sizeof (* vars.int_reltab))
00410 #define SIZEOF_ILF_STRINGS   (strlen (symbol_name) * 2 + 8 \
00411                                    + 21 + strlen (source_dll) \
00412                                    + NUM_ILF_SECTIONS * 9 \
00413                                    + STRING_SIZE_SIZE)
00414 #define SIZEOF_IDATA2              (5 * 4)
00415 
00416 /* For PEx64 idata4 & 5 have thumb size of 8 bytes.  */
00417 #ifdef COFF_WITH_pex64
00418 #define SIZEOF_IDATA4              (2 * 4)
00419 #define SIZEOF_IDATA5              (2 * 4)
00420 #else
00421 #define SIZEOF_IDATA4              (1 * 4)
00422 #define SIZEOF_IDATA5              (1 * 4)
00423 #endif
00424 
00425 #define SIZEOF_IDATA6              (2 + strlen (symbol_name) + 1 + 1)
00426 #define SIZEOF_IDATA7              (strlen (source_dll) + 1 + 1)
00427 #define SIZEOF_ILF_SECTIONS     (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
00428 
00429 #define ILF_DATA_SIZE                            \
00430       sizeof (* vars.bim)                 \
00431     + SIZEOF_ILF_SYMS                            \
00432     + SIZEOF_ILF_SYM_TABLE                \
00433     + SIZEOF_ILF_NATIVE_SYMS                     \
00434     + SIZEOF_ILF_SYM_PTR_TABLE                   \
00435     + SIZEOF_ILF_EXT_SYMS                 \
00436     + SIZEOF_ILF_RELOCS                          \
00437     + SIZEOF_ILF_INT_RELOCS               \
00438     + SIZEOF_ILF_STRINGS                  \
00439     + SIZEOF_IDATA2                       \
00440     + SIZEOF_IDATA4                       \
00441     + SIZEOF_IDATA5                       \
00442     + SIZEOF_IDATA6                       \
00443     + SIZEOF_IDATA7                       \
00444     + SIZEOF_ILF_SECTIONS                 \
00445     + MAX_TEXT_SECTION_SIZE
00446 
00447 /* Create an empty relocation against the given symbol.  */
00448 
00449 static void
00450 pe_ILF_make_a_symbol_reloc (pe_ILF_vars *               vars,
00451                          bfd_vma                     address,
00452                          bfd_reloc_code_real_type    reloc,
00453                          struct bfd_symbol **    sym,
00454                          unsigned int                sym_index)
00455 {
00456   arelent * entry;
00457   struct internal_reloc * internal;
00458 
00459   entry = vars->reltab + vars->relcount;
00460   internal = vars->int_reltab + vars->relcount;
00461 
00462   entry->address     = address;
00463   entry->addend      = 0;
00464   entry->howto       = bfd_reloc_type_lookup (vars->abfd, reloc);
00465   entry->sym_ptr_ptr = sym;
00466 
00467   internal->r_vaddr  = address;
00468   internal->r_symndx = sym_index;
00469   internal->r_type   = entry->howto->type;
00470 
00471   vars->relcount ++;
00472 
00473   BFD_ASSERT (vars->relcount <= NUM_ILF_RELOCS);
00474 }
00475 
00476 /* Create an empty relocation against the given section.  */
00477 
00478 static void
00479 pe_ILF_make_a_reloc (pe_ILF_vars *             vars,
00480                    bfd_vma                   address,
00481                    bfd_reloc_code_real_type  reloc,
00482                    asection_ptr              sec)
00483 {
00484   pe_ILF_make_a_symbol_reloc (vars, address, reloc, sec->symbol_ptr_ptr,
00485                            coff_section_data (vars->abfd, sec)->i);
00486 }
00487 
00488 /* Move the queued relocs into the given section.  */
00489 
00490 static void
00491 pe_ILF_save_relocs (pe_ILF_vars * vars,
00492                   asection_ptr  sec)
00493 {
00494   /* Make sure that there is somewhere to store the internal relocs.  */
00495   if (coff_section_data (vars->abfd, sec) == NULL)
00496     /* We should probably return an error indication here.  */
00497     abort ();
00498 
00499   coff_section_data (vars->abfd, sec)->relocs = vars->int_reltab;
00500   coff_section_data (vars->abfd, sec)->keep_relocs = TRUE;
00501 
00502   sec->relocation  = vars->reltab;
00503   sec->reloc_count = vars->relcount;
00504   sec->flags      |= SEC_RELOC;
00505 
00506   vars->reltab     += vars->relcount;
00507   vars->int_reltab += vars->relcount;
00508   vars->relcount   = 0;
00509 
00510   BFD_ASSERT ((bfd_byte *) vars->int_reltab < (bfd_byte *) vars->string_table);
00511 }
00512 
00513 /* Create a global symbol and add it to the relevant tables.  */
00514 
00515 static void
00516 pe_ILF_make_a_symbol (pe_ILF_vars *  vars,
00517                     const char *   prefix,
00518                     const char *   symbol_name,
00519                     asection_ptr   section,
00520                     flagword       extra_flags)
00521 {
00522   coff_symbol_type * sym;
00523   combined_entry_type * ent;
00524   SYMENT * esym;
00525   unsigned short sclass;
00526 
00527   if (extra_flags & BSF_LOCAL)
00528     sclass = C_STAT;
00529   else
00530     sclass = C_EXT;
00531 
00532 #ifdef THUMBPEMAGIC
00533   if (vars->magic == THUMBPEMAGIC)
00534     {
00535       if (extra_flags & BSF_FUNCTION)
00536        sclass = C_THUMBEXTFUNC;
00537       else if (extra_flags & BSF_LOCAL)
00538        sclass = C_THUMBSTAT;
00539       else
00540        sclass = C_THUMBEXT;
00541     }
00542 #endif
00543 
00544   BFD_ASSERT (vars->sym_index < NUM_ILF_SYMS);
00545 
00546   sym = vars->sym_ptr;
00547   ent = vars->native_ptr;
00548   esym = vars->esym_ptr;
00549 
00550   /* Copy the symbol's name into the string table.  */
00551   sprintf (vars->string_ptr, "%s%s", prefix, symbol_name);
00552 
00553   if (section == NULL)
00554     section = (asection_ptr) & bfd_und_section;
00555 
00556   /* Initialise the external symbol.  */
00557   H_PUT_32 (vars->abfd, vars->string_ptr - vars->string_table,
00558            esym->e.e.e_offset);
00559   H_PUT_16 (vars->abfd, section->target_index, esym->e_scnum);
00560   esym->e_sclass[0] = sclass;
00561 
00562   /* The following initialisations are unnecessary - the memory is
00563      zero initialised.  They are just kept here as reminders.  */
00564 
00565   /* Initialise the internal symbol structure.  */
00566   ent->u.syment.n_sclass          = sclass;
00567   ent->u.syment.n_scnum           = section->target_index;
00568   ent->u.syment._n._n_n._n_offset = (long) sym;
00569 
00570   sym->symbol.the_bfd = vars->abfd;
00571   sym->symbol.name    = vars->string_ptr;
00572   sym->symbol.flags   = BSF_EXPORT | BSF_GLOBAL | extra_flags;
00573   sym->symbol.section = section;
00574   sym->native         = ent;
00575 
00576   * vars->table_ptr = vars->sym_index;
00577   * vars->sym_ptr_ptr = sym;
00578 
00579   /* Adjust pointers for the next symbol.  */
00580   vars->sym_index ++;
00581   vars->sym_ptr ++;
00582   vars->sym_ptr_ptr ++;
00583   vars->table_ptr ++;
00584   vars->native_ptr ++;
00585   vars->esym_ptr ++;
00586   vars->string_ptr += strlen (symbol_name) + strlen (prefix) + 1;
00587 
00588   BFD_ASSERT (vars->string_ptr < vars->end_string_ptr);
00589 }
00590 
00591 /* Create a section.  */
00592 
00593 static asection_ptr
00594 pe_ILF_make_a_section (pe_ILF_vars * vars,
00595                      const char *  name,
00596                      unsigned int  size,
00597                      flagword      extra_flags)
00598 {
00599   asection_ptr sec;
00600   flagword     flags;
00601 
00602   sec = bfd_make_section_old_way (vars->abfd, name);
00603   if (sec == NULL)
00604     return NULL;
00605 
00606   flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_IN_MEMORY;
00607 
00608   bfd_set_section_flags (vars->abfd, sec, flags | extra_flags);
00609 
00610   bfd_set_section_alignment (vars->abfd, sec, 2);
00611 
00612   /* Check that we will not run out of space.  */
00613   BFD_ASSERT (vars->data + size < vars->bim->buffer + vars->bim->size);
00614 
00615   /* Set the section size and contents.  The actual
00616      contents are filled in by our parent.  */
00617   bfd_set_section_size (vars->abfd, sec, (bfd_size_type) size);
00618   sec->contents = vars->data;
00619   sec->target_index = vars->sec_index ++;
00620 
00621   /* Advance data pointer in the vars structure.  */
00622   vars->data += size;
00623 
00624   /* Skip the padding byte if it was not needed.
00625      The logic here is that if the string length is odd,
00626      then the entire string length, including the null byte,
00627      is even and so the extra, padding byte, is not needed.  */
00628   if (size & 1)
00629     vars->data --;
00630 
00631   /* Create a coff_section_tdata structure for our use.  */
00632   sec->used_by_bfd = (struct coff_section_tdata *) vars->data;
00633   vars->data += sizeof (struct coff_section_tdata);
00634 
00635   BFD_ASSERT (vars->data <= vars->bim->buffer + vars->bim->size);
00636 
00637   /* Create a symbol to refer to this section.  */
00638   pe_ILF_make_a_symbol (vars, "", name, sec, BSF_LOCAL);
00639 
00640   /* Cache the index to the symbol in the coff_section_data structure.  */
00641   coff_section_data (vars->abfd, sec)->i = vars->sym_index - 1;
00642 
00643   return sec;
00644 }
00645 
00646 /* This structure contains the code that goes into the .text section
00647    in order to perform a jump into the DLL lookup table.  The entries
00648    in the table are index by the magic number used to represent the
00649    machine type in the PE file.  The contents of the data[] arrays in
00650    these entries are stolen from the jtab[] arrays in ld/pe-dll.c.
00651    The SIZE field says how many bytes in the DATA array are actually
00652    used.  The OFFSET field says where in the data array the address
00653    of the .idata$5 section should be placed.  */
00654 #define MAX_TEXT_SECTION_SIZE 32
00655 
00656 typedef struct
00657 {
00658   unsigned short magic;
00659   unsigned char  data[MAX_TEXT_SECTION_SIZE];
00660   unsigned int   size;
00661   unsigned int   offset;
00662 }
00663 jump_table;
00664 
00665 static jump_table jtab[] =
00666 {
00667 #ifdef I386MAGIC
00668   { I386MAGIC,
00669     { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 },
00670     8, 2
00671   },
00672 #endif
00673 
00674 #ifdef AMD64MAGIC
00675   { AMD64MAGIC,
00676     { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 },
00677     8, 2
00678   },
00679 #endif
00680 
00681 #ifdef  MC68MAGIC
00682   { MC68MAGIC,
00683     { /* XXX fill me in */ },
00684     0, 0
00685   },
00686 #endif
00687 
00688 #ifdef  MIPS_ARCH_MAGIC_WINCE
00689   { MIPS_ARCH_MAGIC_WINCE,
00690     { 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d,
00691       0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 },
00692     16, 0
00693   },
00694 #endif
00695 
00696 #ifdef  SH_ARCH_MAGIC_WINCE
00697   { SH_ARCH_MAGIC_WINCE,
00698     { 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40,
00699       0x09, 0x00, 0x00, 0x00, 0x00, 0x00 },
00700     12, 8
00701   },
00702 #endif
00703 
00704 #ifdef  ARMPEMAGIC
00705   { ARMPEMAGIC,
00706     { 0x00, 0xc0, 0x9f, 0xe5, 0x00, 0xf0,
00707       0x9c, 0xe5, 0x00, 0x00, 0x00, 0x00},
00708     12, 8
00709   },
00710 #endif
00711 
00712 #ifdef  THUMBPEMAGIC
00713   { THUMBPEMAGIC,
00714     { 0x40, 0xb4, 0x02, 0x4e, 0x36, 0x68, 0xb4, 0x46,
00715       0x40, 0xbc, 0x60, 0x47, 0x00, 0x00, 0x00, 0x00 },
00716     16, 12
00717   },
00718 #endif
00719   { 0, { 0 }, 0, 0 }
00720 };
00721 
00722 #ifndef NUM_ENTRIES
00723 #define NUM_ENTRIES(a) (sizeof (a) / sizeof (a)[0])
00724 #endif
00725 
00726 /* Build a full BFD from the information supplied in a ILF object.  */
00727 
00728 static bfd_boolean
00729 pe_ILF_build_a_bfd (bfd *           abfd,
00730                   unsigned int    magic,
00731                   char *          symbol_name,
00732                   char *          source_dll,
00733                   unsigned int    ordinal,
00734                   unsigned int    types)
00735 {
00736   bfd_byte *               ptr;
00737   pe_ILF_vars              vars;
00738   struct internal_filehdr  internal_f;
00739   unsigned int             import_type;
00740   unsigned int             import_name_type;
00741   asection_ptr             id4, id5, id6 = NULL, text = NULL;
00742   coff_symbol_type **      imp_sym;
00743   unsigned int             imp_index;
00744 
00745   /* Decode and verify the types field of the ILF structure.  */
00746   import_type = types & 0x3;
00747   import_name_type = (types & 0x1c) >> 2;
00748 
00749   switch (import_type)
00750     {
00751     case IMPORT_CODE:
00752     case IMPORT_DATA:
00753       break;
00754 
00755     case IMPORT_CONST:
00756       /* XXX code yet to be written.  */
00757       _bfd_error_handler (_("%B: Unhandled import type; %x"),
00758                        abfd, import_type);
00759       return FALSE;
00760 
00761     default:
00762       _bfd_error_handler (_("%B: Unrecognised import type; %x"),
00763                        abfd, import_type);
00764       return FALSE;
00765     }
00766 
00767   switch (import_name_type)
00768     {
00769     case IMPORT_ORDINAL:
00770     case IMPORT_NAME:
00771     case IMPORT_NAME_NOPREFIX:
00772     case IMPORT_NAME_UNDECORATE:
00773       break;
00774 
00775     default:
00776       _bfd_error_handler (_("%B: Unrecognised import name type; %x"),
00777                        abfd, import_name_type);
00778       return FALSE;
00779     }
00780 
00781   /* Initialise local variables.
00782 
00783      Note these are kept in a structure rather than being
00784      declared as statics since bfd frowns on global variables.
00785 
00786      We are going to construct the contents of the BFD in memory,
00787      so allocate all the space that we will need right now.  */
00788   ptr = bfd_zalloc (abfd, (bfd_size_type) ILF_DATA_SIZE);
00789   if (ptr == NULL)
00790     return FALSE;
00791 
00792   /* Create a bfd_in_memory structure.  */
00793   vars.bim = (struct bfd_in_memory *) ptr;
00794   vars.bim->buffer = ptr;
00795   vars.bim->size   = ILF_DATA_SIZE;
00796   ptr += sizeof (* vars.bim);
00797 
00798   /* Initialise the pointers to regions of the memory and the
00799      other contents of the pe_ILF_vars structure as well.  */
00800   vars.sym_cache = (coff_symbol_type *) ptr;
00801   vars.sym_ptr   = (coff_symbol_type *) ptr;
00802   vars.sym_index = 0;
00803   ptr += SIZEOF_ILF_SYMS;
00804 
00805   vars.sym_table = (unsigned int *) ptr;
00806   vars.table_ptr = (unsigned int *) ptr;
00807   ptr += SIZEOF_ILF_SYM_TABLE;
00808 
00809   vars.native_syms = (combined_entry_type *) ptr;
00810   vars.native_ptr  = (combined_entry_type *) ptr;
00811   ptr += SIZEOF_ILF_NATIVE_SYMS;
00812 
00813   vars.sym_ptr_table = (coff_symbol_type **) ptr;
00814   vars.sym_ptr_ptr   = (coff_symbol_type **) ptr;
00815   ptr += SIZEOF_ILF_SYM_PTR_TABLE;
00816 
00817   vars.esym_table = (SYMENT *) ptr;
00818   vars.esym_ptr   = (SYMENT *) ptr;
00819   ptr += SIZEOF_ILF_EXT_SYMS;
00820 
00821   vars.reltab   = (arelent *) ptr;
00822   vars.relcount = 0;
00823   ptr += SIZEOF_ILF_RELOCS;
00824 
00825   vars.int_reltab  = (struct internal_reloc *) ptr;
00826   ptr += SIZEOF_ILF_INT_RELOCS;
00827 
00828   vars.string_table = (char *) ptr;
00829   vars.string_ptr   = (char *) ptr + STRING_SIZE_SIZE;
00830   ptr += SIZEOF_ILF_STRINGS;
00831   vars.end_string_ptr = (char *) ptr;
00832 
00833   /* The remaining space in bim->buffer is used
00834      by the pe_ILF_make_a_section() function.  */
00835   vars.data = ptr;
00836   vars.abfd = abfd;
00837   vars.sec_index = 0;
00838   vars.magic = magic;
00839 
00840   /* Create the initial .idata$<n> sections:
00841      [.idata$2:  Import Directory Table -- not needed]
00842      .idata$4:  Import Lookup Table
00843      .idata$5:  Import Address Table
00844 
00845      Note we do not create a .idata$3 section as this is
00846      created for us by the linker script.  */
00847   id4 = pe_ILF_make_a_section (& vars, ".idata$4", SIZEOF_IDATA4, 0);
00848   id5 = pe_ILF_make_a_section (& vars, ".idata$5", SIZEOF_IDATA5, 0);
00849   if (id4 == NULL || id5 == NULL)
00850     return FALSE;
00851 
00852   /* Fill in the contents of these sections.  */
00853   if (import_name_type == IMPORT_ORDINAL)
00854     {
00855       if (ordinal == 0)
00856        /* XXX - treat as IMPORT_NAME ??? */
00857        abort ();
00858 
00859 #ifdef COFF_WITH_pex64
00860       ((unsigned int *) id4->contents)[0] = ordinal;
00861       ((unsigned int *) id4->contents)[1] = 0x80000000;
00862       ((unsigned int *) id5->contents)[0] = ordinal;
00863       ((unsigned int *) id5->contents)[1] = 0x80000000;
00864 #else
00865       * (unsigned int *) id4->contents = ordinal | 0x80000000;
00866       * (unsigned int *) id5->contents = ordinal | 0x80000000;
00867 #endif
00868     }
00869   else
00870     {
00871       char * symbol;
00872       unsigned int len;
00873 
00874       /* Create .idata$6 - the Hint Name Table.  */
00875       id6 = pe_ILF_make_a_section (& vars, ".idata$6", SIZEOF_IDATA6, 0);
00876       if (id6 == NULL)
00877        return FALSE;
00878 
00879       /* If necessary, trim the import symbol name.  */
00880       symbol = symbol_name;
00881 
00882       /* As used by MS compiler, '_', '@', and '?' are alternative
00883         forms of USER_LABEL_PREFIX, with '?' for c++ mangled names,
00884         '@' used for fastcall (in C),  '_' everywhere else.  Only one
00885         of these is used for a symbol.  We strip this leading char for
00886         IMPORT_NAME_NOPREFIX and IMPORT_NAME_UNDECORATE as per the
00887         PE COFF 6.0 spec (section 8.3, Import Name Type).  */
00888 
00889       if (import_name_type != IMPORT_NAME)
00890        {
00891          char c = symbol[0];
00892          if (c == '_' || c == '@' || c == '?')
00893            symbol++;
00894        }
00895       
00896       len = strlen (symbol);
00897       if (import_name_type == IMPORT_NAME_UNDECORATE)
00898        {
00899          /* Truncate at the first '@'.  */
00900          char *at = strchr (symbol, '@');
00901 
00902          if (at != NULL)
00903            len = at - symbol;
00904        }
00905 
00906       id6->contents[0] = ordinal & 0xff;
00907       id6->contents[1] = ordinal >> 8;
00908 
00909       memcpy ((char *) id6->contents + 2, symbol, len);
00910       id6->contents[len + 2] = '\0';
00911     }
00912 
00913   if (import_name_type != IMPORT_ORDINAL)
00914     {
00915       pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_RVA, id6);
00916       pe_ILF_save_relocs (&vars, id4);
00917 
00918       pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_RVA, id6);
00919       pe_ILF_save_relocs (&vars, id5);
00920     }
00921 
00922   /* Create extra sections depending upon the type of import we are dealing with.  */
00923   switch (import_type)
00924     {
00925       int i;
00926 
00927     case IMPORT_CODE:
00928       /* Create a .text section.
00929         First we need to look up its contents in the jump table.  */
00930       for (i = NUM_ENTRIES (jtab); i--;)
00931        {
00932          if (jtab[i].size == 0)
00933            continue;
00934          if (jtab[i].magic == magic)
00935            break;
00936        }
00937       /* If we did not find a matching entry something is wrong.  */
00938       if (i < 0)
00939        abort ();
00940 
00941       /* Create the .text section.  */
00942       text = pe_ILF_make_a_section (& vars, ".text", jtab[i].size, SEC_CODE);
00943       if (text == NULL)
00944        return FALSE;
00945 
00946       /* Copy in the jump code.  */
00947       memcpy (text->contents, jtab[i].data, jtab[i].size);
00948 
00949       /* Create an import symbol.  */
00950       pe_ILF_make_a_symbol (& vars, "__imp_", symbol_name, id5, 0);
00951       imp_sym   = vars.sym_ptr_ptr - 1;
00952       imp_index = vars.sym_index - 1;
00953 
00954       /* Create a reloc for the data in the text section.  */
00955 #ifdef MIPS_ARCH_MAGIC_WINCE
00956       if (magic == MIPS_ARCH_MAGIC_WINCE)
00957        {
00958          pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) 0, BFD_RELOC_HI16_S,
00959                                   (struct bfd_symbol **) imp_sym,
00960                                   imp_index);
00961          pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_LO16, text);
00962          pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) 4, BFD_RELOC_LO16,
00963                                   (struct bfd_symbol **) imp_sym,
00964                                   imp_index);
00965        }
00966       else
00967 #endif
00968        pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
00969                                 BFD_RELOC_32, (asymbol **) imp_sym,
00970                                 imp_index);
00971 
00972       pe_ILF_save_relocs (& vars, text);
00973       break;
00974 
00975     case IMPORT_DATA:
00976       break;
00977 
00978     default:
00979       /* XXX code not yet written.  */
00980       abort ();
00981     }
00982 
00983   /* Initialise the bfd.  */
00984   memset (& internal_f, 0, sizeof (internal_f));
00985 
00986   internal_f.f_magic  = magic;
00987   internal_f.f_symptr = 0;
00988   internal_f.f_nsyms  = 0;
00989   internal_f.f_flags  = F_AR32WR | F_LNNO; /* XXX is this correct ?  */
00990 
00991   if (   ! bfd_set_start_address (abfd, (bfd_vma) 0)
00992       || ! bfd_coff_set_arch_mach_hook (abfd, & internal_f))
00993     return FALSE;
00994 
00995   if (bfd_coff_mkobject_hook (abfd, (void *) & internal_f, NULL) == NULL)
00996     return FALSE;
00997 
00998   coff_data (abfd)->pe = 1;
00999 #ifdef THUMBPEMAGIC
01000   if (vars.magic == THUMBPEMAGIC)
01001     /* Stop some linker warnings about thumb code not supporting interworking.  */
01002     coff_data (abfd)->flags |= F_INTERWORK | F_INTERWORK_SET;
01003 #endif
01004 
01005   /* Switch from file contents to memory contents.  */
01006   bfd_cache_close (abfd);
01007 
01008   abfd->iostream = (void *) vars.bim;
01009   abfd->flags |= BFD_IN_MEMORY /* | HAS_LOCALS */;
01010   abfd->where = 0;
01011   obj_sym_filepos (abfd) = 0;
01012 
01013   /* Now create a symbol describing the imported value.  */
01014   switch (import_type)
01015     {
01016     case IMPORT_CODE:
01017       pe_ILF_make_a_symbol (& vars, "", symbol_name, text,
01018                          BSF_NOT_AT_END | BSF_FUNCTION);
01019 
01020       /* Create an import symbol for the DLL, without the
01021        .dll suffix.  */
01022       ptr = (bfd_byte *) strrchr (source_dll, '.');
01023       if (ptr)
01024        * ptr = 0;
01025       pe_ILF_make_a_symbol (& vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0);
01026       if (ptr)
01027        * ptr = '.';
01028       break;
01029 
01030     case IMPORT_DATA:
01031       /* Nothing to do here.  */
01032       break;
01033 
01034     default:
01035       /* XXX code not yet written.  */
01036       abort ();
01037     }
01038 
01039   /* Point the bfd at the symbol table.  */
01040   obj_symbols (abfd) = vars.sym_cache;
01041   bfd_get_symcount (abfd) = vars.sym_index;
01042 
01043   obj_raw_syments (abfd) = vars.native_syms;
01044   obj_raw_syment_count (abfd) = vars.sym_index;
01045 
01046   obj_coff_external_syms (abfd) = (void *) vars.esym_table;
01047   obj_coff_keep_syms (abfd) = TRUE;
01048 
01049   obj_convert (abfd) = vars.sym_table;
01050   obj_conv_table_size (abfd) = vars.sym_index;
01051 
01052   obj_coff_strings (abfd) = vars.string_table;
01053   obj_coff_keep_strings (abfd) = TRUE;
01054 
01055   abfd->flags |= HAS_SYMS;
01056 
01057   return TRUE;
01058 }
01059 
01060 /* We have detected a Image Library Format archive element.
01061    Decode the element and return the appropriate target.  */
01062 
01063 static const bfd_target *
01064 pe_ILF_object_p (bfd * abfd)
01065 {
01066   bfd_byte        buffer[16];
01067   bfd_byte *      ptr;
01068   char *          symbol_name;
01069   char *          source_dll;
01070   unsigned int    machine;
01071   bfd_size_type   size;
01072   unsigned int    ordinal;
01073   unsigned int    types;
01074   unsigned int    magic;
01075 
01076   /* Upon entry the first four buyes of the ILF header have
01077       already been read.  Now read the rest of the header.  */
01078   if (bfd_bread (buffer, (bfd_size_type) 16, abfd) != 16)
01079     return NULL;
01080 
01081   ptr = buffer;
01082 
01083   /*  We do not bother to check the version number.
01084       version = H_GET_16 (abfd, ptr);  */
01085   ptr += 2;
01086 
01087   machine = H_GET_16 (abfd, ptr);
01088   ptr += 2;
01089 
01090   /* Check that the machine type is recognised.  */
01091   magic = 0;
01092 
01093   switch (machine)
01094     {
01095     case IMAGE_FILE_MACHINE_UNKNOWN:
01096     case IMAGE_FILE_MACHINE_ALPHA:
01097     case IMAGE_FILE_MACHINE_ALPHA64:
01098     case IMAGE_FILE_MACHINE_IA64:
01099       break;
01100 
01101     case IMAGE_FILE_MACHINE_I386:
01102 #ifdef I386MAGIC
01103       magic = I386MAGIC;
01104 #endif
01105       break;
01106 
01107     case IMAGE_FILE_MACHINE_AMD64:
01108 #ifdef AMD64MAGIC
01109       magic = AMD64MAGIC;
01110 #endif
01111       break;
01112 
01113     case IMAGE_FILE_MACHINE_M68K:
01114 #ifdef MC68AGIC
01115       magic = MC68MAGIC;
01116 #endif
01117       break;
01118 
01119     case IMAGE_FILE_MACHINE_R3000:
01120     case IMAGE_FILE_MACHINE_R4000:
01121     case IMAGE_FILE_MACHINE_R10000:
01122 
01123     case IMAGE_FILE_MACHINE_MIPS16:
01124     case IMAGE_FILE_MACHINE_MIPSFPU:
01125     case IMAGE_FILE_MACHINE_MIPSFPU16:
01126 #ifdef MIPS_ARCH_MAGIC_WINCE
01127       magic = MIPS_ARCH_MAGIC_WINCE;
01128 #endif
01129       break;
01130 
01131     case IMAGE_FILE_MACHINE_SH3:
01132     case IMAGE_FILE_MACHINE_SH4:
01133 #ifdef SH_ARCH_MAGIC_WINCE
01134       magic = SH_ARCH_MAGIC_WINCE;
01135 #endif
01136       break;
01137 
01138     case IMAGE_FILE_MACHINE_ARM:
01139 #ifdef ARMPEMAGIC
01140       magic = ARMPEMAGIC;
01141 #endif
01142       break;
01143 
01144     case IMAGE_FILE_MACHINE_THUMB:
01145 #ifdef THUMBPEMAGIC
01146       {
01147        extern const bfd_target TARGET_LITTLE_SYM;
01148 
01149        if (abfd->xvec == & TARGET_LITTLE_SYM)
01150          magic = THUMBPEMAGIC;
01151       }
01152 #endif
01153       break;
01154 
01155     case IMAGE_FILE_MACHINE_POWERPC:
01156       /* We no longer support PowerPC.  */
01157     default:
01158       _bfd_error_handler
01159        (_("%B: Unrecognised machine type (0x%x)"
01160           " in Import Library Format archive"),
01161         abfd, machine);
01162       bfd_set_error (bfd_error_malformed_archive);
01163 
01164       return NULL;
01165       break;
01166     }
01167 
01168   if (magic == 0)
01169     {
01170       _bfd_error_handler
01171        (_("%B: Recognised but unhandled machine type (0x%x)"
01172           " in Import Library Format archive"),
01173         abfd, machine);
01174       bfd_set_error (bfd_error_wrong_format);
01175 
01176       return NULL;
01177     }
01178 
01179   /* We do not bother to check the date.
01180      date = H_GET_32 (abfd, ptr);  */
01181   ptr += 4;
01182 
01183   size = H_GET_32 (abfd, ptr);
01184   ptr += 4;
01185 
01186   if (size == 0)
01187     {
01188       _bfd_error_handler
01189        (_("%B: size field is zero in Import Library Format header"), abfd);
01190       bfd_set_error (bfd_error_malformed_archive);
01191 
01192       return NULL;
01193     }
01194 
01195   ordinal = H_GET_16 (abfd, ptr);
01196   ptr += 2;
01197 
01198   types = H_GET_16 (abfd, ptr);
01199   /* ptr += 2; */
01200 
01201   /* Now read in the two strings that follow.  */
01202   ptr = bfd_alloc (abfd, size);
01203   if (ptr == NULL)
01204     return NULL;
01205 
01206   if (bfd_bread (ptr, size, abfd) != size)
01207     {
01208       bfd_release (abfd, ptr);
01209       return NULL;
01210     }
01211 
01212   symbol_name = (char *) ptr;
01213   source_dll  = symbol_name + strlen (symbol_name) + 1;
01214 
01215   /* Verify that the strings are null terminated.  */
01216   if (ptr[size - 1] != 0
01217       || (bfd_size_type) ((bfd_byte *) source_dll - ptr) >= size)
01218     {
01219       _bfd_error_handler
01220        (_("%B: string not null terminated in ILF object file."), abfd);
01221       bfd_set_error (bfd_error_malformed_archive);
01222       bfd_release (abfd, ptr);
01223       return NULL;
01224     }
01225 
01226   /* Now construct the bfd.  */
01227   if (! pe_ILF_build_a_bfd (abfd, magic, symbol_name,
01228                          source_dll, ordinal, types))
01229     {
01230       bfd_release (abfd, ptr);
01231       return NULL;
01232     }
01233 
01234   return abfd->xvec;
01235 }
01236 
01237 static const bfd_target *
01238 pe_bfd_object_p (bfd * abfd)
01239 {
01240   bfd_byte buffer[4];
01241   struct external_PEI_DOS_hdr dos_hdr;
01242   struct external_PEI_IMAGE_hdr image_hdr;
01243   file_ptr offset;
01244 
01245   /* Detect if this a Microsoft Import Library Format element.  */
01246   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
01247       || bfd_bread (buffer, (bfd_size_type) 4, abfd) != 4)
01248     {
01249       if (bfd_get_error () != bfd_error_system_call)
01250        bfd_set_error (bfd_error_wrong_format);
01251       return NULL;
01252     }
01253 
01254   if (H_GET_32 (abfd, buffer) == 0xffff0000)
01255     return pe_ILF_object_p (abfd);
01256 
01257   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
01258       || bfd_bread (&dos_hdr, (bfd_size_type) sizeof (dos_hdr), abfd)
01259         != sizeof (dos_hdr))
01260     {
01261       if (bfd_get_error () != bfd_error_system_call)
01262        bfd_set_error (bfd_error_wrong_format);
01263       return NULL;
01264     }
01265 
01266   /* There are really two magic numbers involved; the magic number
01267      that says this is a NT executable (PEI) and the magic number that
01268      determines the architecture.  The former is DOSMAGIC, stored in
01269      the e_magic field.  The latter is stored in the f_magic field.
01270      If the NT magic number isn't valid, the architecture magic number
01271      could be mimicked by some other field (specifically, the number
01272      of relocs in section 3).  Since this routine can only be called
01273      correctly for a PEI file, check the e_magic number here, and, if
01274      it doesn't match, clobber the f_magic number so that we don't get
01275      a false match.  */
01276   if (H_GET_16 (abfd, dos_hdr.e_magic) != DOSMAGIC)
01277     {
01278       bfd_set_error (bfd_error_wrong_format);
01279       return NULL;
01280     }
01281 
01282   offset = H_GET_32 (abfd, dos_hdr.e_lfanew);
01283   if (bfd_seek (abfd, offset, SEEK_SET) != 0
01284       || (bfd_bread (&image_hdr, (bfd_size_type) sizeof (image_hdr), abfd)
01285          != sizeof (image_hdr)))
01286     {
01287       if (bfd_get_error () != bfd_error_system_call)
01288        bfd_set_error (bfd_error_wrong_format);
01289       return NULL;
01290     }
01291 
01292   if (H_GET_32 (abfd, image_hdr.nt_signature) != 0x4550)
01293     {
01294       bfd_set_error (bfd_error_wrong_format);
01295       return NULL;
01296     }
01297 
01298   /* Here is the hack.  coff_object_p wants to read filhsz bytes to
01299      pick up the COFF header for PE, see "struct external_PEI_filehdr"
01300      in include/coff/pe.h.  We adjust so that that will work. */
01301   if (bfd_seek (abfd, (file_ptr) (offset - sizeof (dos_hdr)), SEEK_SET) != 0)
01302     {
01303       if (bfd_get_error () != bfd_error_system_call)
01304        bfd_set_error (bfd_error_wrong_format);
01305       return NULL;
01306     }
01307 
01308   return coff_object_p (abfd);
01309 }
01310 
01311 #define coff_object_p pe_bfd_object_p
01312 #endif /* COFF_IMAGE_WITH_PE */