13d8817e4Smiod /* Support for the generic parts of PE/PEI, for BFD.
23d8817e4Smiod Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
33d8817e4Smiod 2005 Free Software Foundation, Inc.
43d8817e4Smiod Written by Cygnus Solutions.
53d8817e4Smiod
63d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
73d8817e4Smiod
83d8817e4Smiod This program is free software; you can redistribute it and/or modify
93d8817e4Smiod it under the terms of the GNU General Public License as published by
103d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
113d8817e4Smiod (at your option) any later version.
123d8817e4Smiod
133d8817e4Smiod This program is distributed in the hope that it will be useful,
143d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
153d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163d8817e4Smiod GNU General Public License for more details.
173d8817e4Smiod
183d8817e4Smiod You should have received a copy of the GNU General Public License
193d8817e4Smiod along with this program; if not, write to the Free Software
203d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
213d8817e4Smiod
223d8817e4Smiod /* Most of this hacked by Steve Chamberlain,
233d8817e4Smiod sac@cygnus.com
243d8817e4Smiod
253d8817e4Smiod PE/PEI rearrangement (and code added): Donn Terry
263d8817e4Smiod Softway Systems, Inc. */
273d8817e4Smiod
283d8817e4Smiod /* Hey look, some documentation [and in a place you expect to find it]!
293d8817e4Smiod
303d8817e4Smiod The main reference for the pei format is "Microsoft Portable Executable
313d8817e4Smiod and Common Object File Format Specification 4.1". Get it if you need to
323d8817e4Smiod do some serious hacking on this code.
333d8817e4Smiod
343d8817e4Smiod Another reference:
353d8817e4Smiod "Peering Inside the PE: A Tour of the Win32 Portable Executable
363d8817e4Smiod File Format", MSJ 1994, Volume 9.
373d8817e4Smiod
383d8817e4Smiod The *sole* difference between the pe format and the pei format is that the
393d8817e4Smiod latter has an MSDOS 2.0 .exe header on the front that prints the message
403d8817e4Smiod "This app must be run under Windows." (or some such).
413d8817e4Smiod (FIXME: Whether that statement is *really* true or not is unknown.
423d8817e4Smiod Are there more subtle differences between pe and pei formats?
433d8817e4Smiod For now assume there aren't. If you find one, then for God sakes
443d8817e4Smiod document it here!)
453d8817e4Smiod
463d8817e4Smiod The Microsoft docs use the word "image" instead of "executable" because
473d8817e4Smiod the former can also refer to a DLL (shared library). Confusion can arise
483d8817e4Smiod because the `i' in `pei' also refers to "image". The `pe' format can
493d8817e4Smiod also create images (i.e. executables), it's just that to run on a win32
503d8817e4Smiod system you need to use the pei format.
513d8817e4Smiod
523d8817e4Smiod FIXME: Please add more docs here so the next poor fool that has to hack
533d8817e4Smiod on this code has a chance of getting something accomplished without
543d8817e4Smiod wasting too much time. */
553d8817e4Smiod
563d8817e4Smiod #include "libpei.h"
573d8817e4Smiod
583d8817e4Smiod static bfd_boolean (*pe_saved_coff_bfd_print_private_bfd_data) (bfd *, void *) =
593d8817e4Smiod #ifndef coff_bfd_print_private_bfd_data
603d8817e4Smiod NULL;
613d8817e4Smiod #else
623d8817e4Smiod coff_bfd_print_private_bfd_data;
633d8817e4Smiod #undef coff_bfd_print_private_bfd_data
643d8817e4Smiod #endif
653d8817e4Smiod
663d8817e4Smiod static bfd_boolean pe_print_private_bfd_data (bfd *, void *);
673d8817e4Smiod #define coff_bfd_print_private_bfd_data pe_print_private_bfd_data
683d8817e4Smiod
693d8817e4Smiod static bfd_boolean (*pe_saved_coff_bfd_copy_private_bfd_data) (bfd *, bfd *) =
703d8817e4Smiod #ifndef coff_bfd_copy_private_bfd_data
713d8817e4Smiod NULL;
723d8817e4Smiod #else
733d8817e4Smiod coff_bfd_copy_private_bfd_data;
743d8817e4Smiod #undef coff_bfd_copy_private_bfd_data
753d8817e4Smiod #endif
763d8817e4Smiod
773d8817e4Smiod static bfd_boolean pe_bfd_copy_private_bfd_data (bfd *, bfd *);
783d8817e4Smiod #define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data
793d8817e4Smiod
803d8817e4Smiod #define coff_mkobject pe_mkobject
813d8817e4Smiod #define coff_mkobject_hook pe_mkobject_hook
823d8817e4Smiod
833d8817e4Smiod #ifdef COFF_IMAGE_WITH_PE
843d8817e4Smiod /* This structure contains static variables used by the ILF code. */
853d8817e4Smiod typedef asection * asection_ptr;
863d8817e4Smiod
873d8817e4Smiod typedef struct
883d8817e4Smiod {
893d8817e4Smiod bfd * abfd;
903d8817e4Smiod bfd_byte * data;
913d8817e4Smiod struct bfd_in_memory * bim;
923d8817e4Smiod unsigned short magic;
933d8817e4Smiod
943d8817e4Smiod arelent * reltab;
953d8817e4Smiod unsigned int relcount;
963d8817e4Smiod
973d8817e4Smiod coff_symbol_type * sym_cache;
983d8817e4Smiod coff_symbol_type * sym_ptr;
993d8817e4Smiod unsigned int sym_index;
1003d8817e4Smiod
1013d8817e4Smiod unsigned int * sym_table;
1023d8817e4Smiod unsigned int * table_ptr;
1033d8817e4Smiod
1043d8817e4Smiod combined_entry_type * native_syms;
1053d8817e4Smiod combined_entry_type * native_ptr;
1063d8817e4Smiod
1073d8817e4Smiod coff_symbol_type ** sym_ptr_table;
1083d8817e4Smiod coff_symbol_type ** sym_ptr_ptr;
1093d8817e4Smiod
1103d8817e4Smiod unsigned int sec_index;
1113d8817e4Smiod
1123d8817e4Smiod char * string_table;
1133d8817e4Smiod char * string_ptr;
1143d8817e4Smiod char * end_string_ptr;
1153d8817e4Smiod
1163d8817e4Smiod SYMENT * esym_table;
1173d8817e4Smiod SYMENT * esym_ptr;
1183d8817e4Smiod
1193d8817e4Smiod struct internal_reloc * int_reltab;
1203d8817e4Smiod }
1213d8817e4Smiod pe_ILF_vars;
1223d8817e4Smiod #endif /* COFF_IMAGE_WITH_PE */
1233d8817e4Smiod
1243d8817e4Smiod #ifndef NO_COFF_RELOCS
1253d8817e4Smiod static void
coff_swap_reloc_in(bfd * abfd,void * src,void * dst)1263d8817e4Smiod coff_swap_reloc_in (bfd * abfd, void * src, void * dst)
1273d8817e4Smiod {
1283d8817e4Smiod RELOC *reloc_src = (RELOC *) src;
1293d8817e4Smiod struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
1303d8817e4Smiod
1313d8817e4Smiod reloc_dst->r_vaddr = H_GET_32 (abfd, reloc_src->r_vaddr);
1323d8817e4Smiod reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
1333d8817e4Smiod reloc_dst->r_type = H_GET_16 (abfd, reloc_src->r_type);
1343d8817e4Smiod #ifdef SWAP_IN_RELOC_OFFSET
1353d8817e4Smiod reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET (abfd, reloc_src->r_offset);
1363d8817e4Smiod #endif
1373d8817e4Smiod }
1383d8817e4Smiod
1393d8817e4Smiod static unsigned int
coff_swap_reloc_out(bfd * abfd,void * src,void * dst)1403d8817e4Smiod coff_swap_reloc_out (bfd * abfd, void * src, void * dst)
1413d8817e4Smiod {
1423d8817e4Smiod struct internal_reloc *reloc_src = (struct internal_reloc *) src;
1433d8817e4Smiod struct external_reloc *reloc_dst = (struct external_reloc *) dst;
1443d8817e4Smiod
1453d8817e4Smiod H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
1463d8817e4Smiod H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
1473d8817e4Smiod H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
1483d8817e4Smiod
1493d8817e4Smiod #ifdef SWAP_OUT_RELOC_OFFSET
1503d8817e4Smiod SWAP_OUT_RELOC_OFFSET (abfd, reloc_src->r_offset, reloc_dst->r_offset);
1513d8817e4Smiod #endif
1523d8817e4Smiod #ifdef SWAP_OUT_RELOC_EXTRA
1533d8817e4Smiod SWAP_OUT_RELOC_EXTRA (abfd, reloc_src, reloc_dst);
1543d8817e4Smiod #endif
1553d8817e4Smiod return RELSZ;
1563d8817e4Smiod }
1573d8817e4Smiod #endif /* not NO_COFF_RELOCS */
1583d8817e4Smiod
1593d8817e4Smiod static void
coff_swap_filehdr_in(bfd * abfd,void * src,void * dst)1603d8817e4Smiod coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
1613d8817e4Smiod {
1623d8817e4Smiod FILHDR *filehdr_src = (FILHDR *) src;
1633d8817e4Smiod struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
1643d8817e4Smiod
1653d8817e4Smiod filehdr_dst->f_magic = H_GET_16 (abfd, filehdr_src->f_magic);
1663d8817e4Smiod filehdr_dst->f_nscns = H_GET_16 (abfd, filehdr_src->f_nscns);
1673d8817e4Smiod filehdr_dst->f_timdat = H_GET_32 (abfd, filehdr_src->f_timdat);
1683d8817e4Smiod filehdr_dst->f_nsyms = H_GET_32 (abfd, filehdr_src->f_nsyms);
1693d8817e4Smiod filehdr_dst->f_flags = H_GET_16 (abfd, filehdr_src->f_flags);
1703d8817e4Smiod filehdr_dst->f_symptr = H_GET_32 (abfd, filehdr_src->f_symptr);
1713d8817e4Smiod
1723d8817e4Smiod /* Other people's tools sometimes generate headers with an nsyms but
1733d8817e4Smiod a zero symptr. */
1743d8817e4Smiod if (filehdr_dst->f_nsyms != 0 && filehdr_dst->f_symptr == 0)
1753d8817e4Smiod {
1763d8817e4Smiod filehdr_dst->f_nsyms = 0;
1773d8817e4Smiod filehdr_dst->f_flags |= F_LSYMS;
1783d8817e4Smiod }
1793d8817e4Smiod
1803d8817e4Smiod filehdr_dst->f_opthdr = H_GET_16 (abfd, filehdr_src-> f_opthdr);
1813d8817e4Smiod }
1823d8817e4Smiod
1833d8817e4Smiod #ifdef COFF_IMAGE_WITH_PE
1843d8817e4Smiod # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out
1853d8817e4Smiod #else
1863d8817e4Smiod # define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
1873d8817e4Smiod #endif
1883d8817e4Smiod
1893d8817e4Smiod static void
coff_swap_scnhdr_in(bfd * abfd,void * ext,void * in)1903d8817e4Smiod coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
1913d8817e4Smiod {
1923d8817e4Smiod SCNHDR *scnhdr_ext = (SCNHDR *) ext;
1933d8817e4Smiod struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
1943d8817e4Smiod
1953d8817e4Smiod memcpy (scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
1963d8817e4Smiod
1973d8817e4Smiod scnhdr_int->s_vaddr = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
1983d8817e4Smiod scnhdr_int->s_paddr = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
1993d8817e4Smiod scnhdr_int->s_size = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
2003d8817e4Smiod scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
2013d8817e4Smiod scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
2023d8817e4Smiod scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
2033d8817e4Smiod scnhdr_int->s_flags = H_GET_32 (abfd, scnhdr_ext->s_flags);
2043d8817e4Smiod
2053d8817e4Smiod /* MS handles overflow of line numbers by carrying into the reloc
2063d8817e4Smiod field (it appears). Since it's supposed to be zero for PE
2073d8817e4Smiod *IMAGE* format, that's safe. This is still a bit iffy. */
2083d8817e4Smiod #ifdef COFF_IMAGE_WITH_PE
2093d8817e4Smiod scnhdr_int->s_nlnno = (H_GET_16 (abfd, scnhdr_ext->s_nlnno)
2103d8817e4Smiod + (H_GET_16 (abfd, scnhdr_ext->s_nreloc) << 16));
2113d8817e4Smiod scnhdr_int->s_nreloc = 0;
2123d8817e4Smiod #else
2133d8817e4Smiod scnhdr_int->s_nreloc = H_GET_16 (abfd, scnhdr_ext->s_nreloc);
2143d8817e4Smiod scnhdr_int->s_nlnno = H_GET_16 (abfd, scnhdr_ext->s_nlnno);
2153d8817e4Smiod #endif
2163d8817e4Smiod
2173d8817e4Smiod if (scnhdr_int->s_vaddr != 0)
2183d8817e4Smiod {
2193d8817e4Smiod scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
2203d8817e4Smiod scnhdr_int->s_vaddr &= 0xffffffff;
2213d8817e4Smiod }
2223d8817e4Smiod
2233d8817e4Smiod #ifndef COFF_NO_HACK_SCNHDR_SIZE
2243d8817e4Smiod /* If this section holds uninitialized data and is from an object file
2253d8817e4Smiod or from an executable image that has not initialized the field,
2263d8817e4Smiod or if the image is an executable file and the physical size is padded,
2273d8817e4Smiod use the virtual size (stored in s_paddr) instead. */
2283d8817e4Smiod if (scnhdr_int->s_paddr > 0
2293d8817e4Smiod && (((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0
2303d8817e4Smiod && (! bfd_pe_executable_p (abfd) || scnhdr_int->s_size == 0))
2313d8817e4Smiod || (bfd_pe_executable_p (abfd) && scnhdr_int->s_size > scnhdr_int->s_paddr)))
2323d8817e4Smiod /* This code used to set scnhdr_int->s_paddr to 0. However,
2333d8817e4Smiod coff_set_alignment_hook stores s_paddr in virt_size, which
2343d8817e4Smiod only works if it correctly holds the virtual size of the
2353d8817e4Smiod section. */
2363d8817e4Smiod scnhdr_int->s_size = scnhdr_int->s_paddr;
2373d8817e4Smiod #endif
2383d8817e4Smiod }
2393d8817e4Smiod
2403d8817e4Smiod static bfd_boolean
pe_mkobject(bfd * abfd)2413d8817e4Smiod pe_mkobject (bfd * abfd)
2423d8817e4Smiod {
2433d8817e4Smiod pe_data_type *pe;
2443d8817e4Smiod bfd_size_type amt = sizeof (pe_data_type);
2453d8817e4Smiod
2463d8817e4Smiod abfd->tdata.pe_obj_data = (struct pe_tdata *) bfd_zalloc (abfd, amt);
2473d8817e4Smiod
2483d8817e4Smiod if (abfd->tdata.pe_obj_data == 0)
2493d8817e4Smiod return FALSE;
2503d8817e4Smiod
2513d8817e4Smiod pe = pe_data (abfd);
2523d8817e4Smiod
2533d8817e4Smiod pe->coff.pe = 1;
2543d8817e4Smiod
2553d8817e4Smiod /* in_reloc_p is architecture dependent. */
2563d8817e4Smiod pe->in_reloc_p = in_reloc_p;
2573d8817e4Smiod
2583d8817e4Smiod #ifdef PEI_FORCE_MINIMUM_ALIGNMENT
2593d8817e4Smiod pe->force_minimum_alignment = 1;
2603d8817e4Smiod #endif
2613d8817e4Smiod #ifdef PEI_TARGET_SUBSYSTEM
2623d8817e4Smiod pe->target_subsystem = PEI_TARGET_SUBSYSTEM;
2633d8817e4Smiod #endif
2643d8817e4Smiod
2653d8817e4Smiod return TRUE;
2663d8817e4Smiod }
2673d8817e4Smiod
2683d8817e4Smiod /* Create the COFF backend specific information. */
2693d8817e4Smiod
2703d8817e4Smiod static void *
pe_mkobject_hook(bfd * abfd,void * filehdr,void * aouthdr ATTRIBUTE_UNUSED)2713d8817e4Smiod pe_mkobject_hook (bfd * abfd,
2723d8817e4Smiod void * filehdr,
2733d8817e4Smiod void * aouthdr ATTRIBUTE_UNUSED)
2743d8817e4Smiod {
2753d8817e4Smiod struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
2763d8817e4Smiod pe_data_type *pe;
2773d8817e4Smiod
2783d8817e4Smiod if (! pe_mkobject (abfd))
2793d8817e4Smiod return NULL;
2803d8817e4Smiod
2813d8817e4Smiod pe = pe_data (abfd);
2823d8817e4Smiod pe->coff.sym_filepos = internal_f->f_symptr;
2833d8817e4Smiod /* These members communicate important constants about the symbol
2843d8817e4Smiod table to GDB's symbol-reading code. These `constants'
2853d8817e4Smiod unfortunately vary among coff implementations... */
2863d8817e4Smiod pe->coff.local_n_btmask = N_BTMASK;
2873d8817e4Smiod pe->coff.local_n_btshft = N_BTSHFT;
2883d8817e4Smiod pe->coff.local_n_tmask = N_TMASK;
2893d8817e4Smiod pe->coff.local_n_tshift = N_TSHIFT;
2903d8817e4Smiod pe->coff.local_symesz = SYMESZ;
2913d8817e4Smiod pe->coff.local_auxesz = AUXESZ;
2923d8817e4Smiod pe->coff.local_linesz = LINESZ;
2933d8817e4Smiod
2943d8817e4Smiod pe->coff.timestamp = internal_f->f_timdat;
2953d8817e4Smiod
2963d8817e4Smiod obj_raw_syment_count (abfd) =
2973d8817e4Smiod obj_conv_table_size (abfd) =
2983d8817e4Smiod internal_f->f_nsyms;
2993d8817e4Smiod
3003d8817e4Smiod pe->real_flags = internal_f->f_flags;
3013d8817e4Smiod
3023d8817e4Smiod if ((internal_f->f_flags & F_DLL) != 0)
3033d8817e4Smiod pe->dll = 1;
3043d8817e4Smiod
3053d8817e4Smiod if ((internal_f->f_flags & IMAGE_FILE_DEBUG_STRIPPED) == 0)
3063d8817e4Smiod abfd->flags |= HAS_DEBUG;
3073d8817e4Smiod
3083d8817e4Smiod #ifdef COFF_IMAGE_WITH_PE
3093d8817e4Smiod if (aouthdr)
3103d8817e4Smiod pe->pe_opthdr = ((struct internal_aouthdr *) aouthdr)->pe;
3113d8817e4Smiod #endif
3123d8817e4Smiod
3133d8817e4Smiod #ifdef ARM
3143d8817e4Smiod if (! _bfd_coff_arm_set_private_flags (abfd, internal_f->f_flags))
3153d8817e4Smiod coff_data (abfd) ->flags = 0;
3163d8817e4Smiod #endif
3173d8817e4Smiod
3183d8817e4Smiod return (void *) pe;
3193d8817e4Smiod }
3203d8817e4Smiod
3213d8817e4Smiod static bfd_boolean
pe_print_private_bfd_data(bfd * abfd,void * vfile)3223d8817e4Smiod pe_print_private_bfd_data (bfd *abfd, void * vfile)
3233d8817e4Smiod {
3243d8817e4Smiod FILE *file = (FILE *) vfile;
3253d8817e4Smiod
3263d8817e4Smiod if (!_bfd_XX_print_private_bfd_data_common (abfd, vfile))
3273d8817e4Smiod return FALSE;
3283d8817e4Smiod
3293d8817e4Smiod if (pe_saved_coff_bfd_print_private_bfd_data == NULL)
3303d8817e4Smiod return TRUE;
3313d8817e4Smiod
3323d8817e4Smiod fputc ('\n', file);
3333d8817e4Smiod
3343d8817e4Smiod return pe_saved_coff_bfd_print_private_bfd_data (abfd, vfile);
3353d8817e4Smiod }
3363d8817e4Smiod
3373d8817e4Smiod /* Copy any private info we understand from the input bfd
3383d8817e4Smiod to the output bfd. */
3393d8817e4Smiod
3403d8817e4Smiod static bfd_boolean
pe_bfd_copy_private_bfd_data(bfd * ibfd,bfd * obfd)3413d8817e4Smiod pe_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
3423d8817e4Smiod {
3433d8817e4Smiod /* PR binutils/716: Copy the large address aware flag.
3443d8817e4Smiod XXX: Should we be copying other flags or other fields in the pe_data()
3453d8817e4Smiod structure ? */
3463d8817e4Smiod if (pe_data (obfd) != NULL
3473d8817e4Smiod && pe_data (ibfd) != NULL
3483d8817e4Smiod && pe_data (ibfd)->real_flags & IMAGE_FILE_LARGE_ADDRESS_AWARE)
3493d8817e4Smiod pe_data (obfd)->real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
3503d8817e4Smiod
3513d8817e4Smiod if (!_bfd_XX_bfd_copy_private_bfd_data_common (ibfd, obfd))
3523d8817e4Smiod return FALSE;
3533d8817e4Smiod
3543d8817e4Smiod if (pe_saved_coff_bfd_copy_private_bfd_data)
3553d8817e4Smiod return pe_saved_coff_bfd_copy_private_bfd_data (ibfd, obfd);
3563d8817e4Smiod
3573d8817e4Smiod return TRUE;
3583d8817e4Smiod }
3593d8817e4Smiod
3603d8817e4Smiod #define coff_bfd_copy_private_section_data \
3613d8817e4Smiod _bfd_XX_bfd_copy_private_section_data
3623d8817e4Smiod
3633d8817e4Smiod #define coff_get_symbol_info _bfd_XX_get_symbol_info
3643d8817e4Smiod
3653d8817e4Smiod #ifdef COFF_IMAGE_WITH_PE
3663d8817e4Smiod
3673d8817e4Smiod /* Code to handle Microsoft's Image Library Format.
3683d8817e4Smiod Also known as LINK6 format.
3693d8817e4Smiod Documentation about this format can be found at:
3703d8817e4Smiod
3713d8817e4Smiod http://msdn.microsoft.com/library/specs/pecoff_section8.htm */
3723d8817e4Smiod
3733d8817e4Smiod /* The following constants specify the sizes of the various data
3743d8817e4Smiod structures that we have to create in order to build a bfd describing
3753d8817e4Smiod an ILF object file. The final "+ 1" in the definitions of SIZEOF_IDATA6
3763d8817e4Smiod and SIZEOF_IDATA7 below is to allow for the possibility that we might
3773d8817e4Smiod need a padding byte in order to ensure 16 bit alignment for the section's
3783d8817e4Smiod contents.
3793d8817e4Smiod
3803d8817e4Smiod The value for SIZEOF_ILF_STRINGS is computed as follows:
3813d8817e4Smiod
3823d8817e4Smiod There will be NUM_ILF_SECTIONS section symbols. Allow 9 characters
3833d8817e4Smiod per symbol for their names (longest section name is .idata$x).
3843d8817e4Smiod
3853d8817e4Smiod There will be two symbols for the imported value, one the symbol name
3863d8817e4Smiod and one with _imp__ prefixed. Allowing for the terminating nul's this
3873d8817e4Smiod is strlen (symbol_name) * 2 + 8 + 21 + strlen (source_dll).
3883d8817e4Smiod
3893d8817e4Smiod The strings in the string table must start STRING__SIZE_SIZE bytes into
3903d8817e4Smiod the table in order to for the string lookup code in coffgen/coffcode to
3913d8817e4Smiod work. */
3923d8817e4Smiod #define NUM_ILF_RELOCS 8
3933d8817e4Smiod #define NUM_ILF_SECTIONS 6
3943d8817e4Smiod #define NUM_ILF_SYMS (2 + NUM_ILF_SECTIONS)
3953d8817e4Smiod
3963d8817e4Smiod #define SIZEOF_ILF_SYMS (NUM_ILF_SYMS * sizeof (* vars.sym_cache))
3973d8817e4Smiod #define SIZEOF_ILF_SYM_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_table))
3983d8817e4Smiod #define SIZEOF_ILF_NATIVE_SYMS (NUM_ILF_SYMS * sizeof (* vars.native_syms))
3993d8817e4Smiod #define SIZEOF_ILF_SYM_PTR_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_ptr_table))
4003d8817e4Smiod #define SIZEOF_ILF_EXT_SYMS (NUM_ILF_SYMS * sizeof (* vars.esym_table))
4013d8817e4Smiod #define SIZEOF_ILF_RELOCS (NUM_ILF_RELOCS * sizeof (* vars.reltab))
4023d8817e4Smiod #define SIZEOF_ILF_INT_RELOCS (NUM_ILF_RELOCS * sizeof (* vars.int_reltab))
4033d8817e4Smiod #define SIZEOF_ILF_STRINGS (strlen (symbol_name) * 2 + 8 \
4043d8817e4Smiod + 21 + strlen (source_dll) \
4053d8817e4Smiod + NUM_ILF_SECTIONS * 9 \
4063d8817e4Smiod + STRING_SIZE_SIZE)
4073d8817e4Smiod #define SIZEOF_IDATA2 (5 * 4)
4083d8817e4Smiod #define SIZEOF_IDATA4 (1 * 4)
4093d8817e4Smiod #define SIZEOF_IDATA5 (1 * 4)
4103d8817e4Smiod #define SIZEOF_IDATA6 (2 + strlen (symbol_name) + 1 + 1)
4113d8817e4Smiod #define SIZEOF_IDATA7 (strlen (source_dll) + 1 + 1)
4123d8817e4Smiod #define SIZEOF_ILF_SECTIONS (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
4133d8817e4Smiod
4143d8817e4Smiod #define ILF_DATA_SIZE \
4153d8817e4Smiod sizeof (* vars.bim) \
4163d8817e4Smiod + SIZEOF_ILF_SYMS \
4173d8817e4Smiod + SIZEOF_ILF_SYM_TABLE \
4183d8817e4Smiod + SIZEOF_ILF_NATIVE_SYMS \
4193d8817e4Smiod + SIZEOF_ILF_SYM_PTR_TABLE \
4203d8817e4Smiod + SIZEOF_ILF_EXT_SYMS \
4213d8817e4Smiod + SIZEOF_ILF_RELOCS \
4223d8817e4Smiod + SIZEOF_ILF_INT_RELOCS \
4233d8817e4Smiod + SIZEOF_ILF_STRINGS \
4243d8817e4Smiod + SIZEOF_IDATA2 \
4253d8817e4Smiod + SIZEOF_IDATA4 \
4263d8817e4Smiod + SIZEOF_IDATA5 \
4273d8817e4Smiod + SIZEOF_IDATA6 \
4283d8817e4Smiod + SIZEOF_IDATA7 \
4293d8817e4Smiod + SIZEOF_ILF_SECTIONS \
4303d8817e4Smiod + MAX_TEXT_SECTION_SIZE
4313d8817e4Smiod
4323d8817e4Smiod /* Create an empty relocation against the given symbol. */
4333d8817e4Smiod
4343d8817e4Smiod static void
pe_ILF_make_a_symbol_reloc(pe_ILF_vars * vars,bfd_vma address,bfd_reloc_code_real_type reloc,struct bfd_symbol ** sym,unsigned int sym_index)4353d8817e4Smiod pe_ILF_make_a_symbol_reloc (pe_ILF_vars * vars,
4363d8817e4Smiod bfd_vma address,
4373d8817e4Smiod bfd_reloc_code_real_type reloc,
4383d8817e4Smiod struct bfd_symbol ** sym,
4393d8817e4Smiod unsigned int sym_index)
4403d8817e4Smiod {
4413d8817e4Smiod arelent * entry;
4423d8817e4Smiod struct internal_reloc * internal;
4433d8817e4Smiod
4443d8817e4Smiod entry = vars->reltab + vars->relcount;
4453d8817e4Smiod internal = vars->int_reltab + vars->relcount;
4463d8817e4Smiod
4473d8817e4Smiod entry->address = address;
4483d8817e4Smiod entry->addend = 0;
4493d8817e4Smiod entry->howto = bfd_reloc_type_lookup (vars->abfd, reloc);
4503d8817e4Smiod entry->sym_ptr_ptr = sym;
4513d8817e4Smiod
4523d8817e4Smiod internal->r_vaddr = address;
4533d8817e4Smiod internal->r_symndx = sym_index;
4543d8817e4Smiod internal->r_type = entry->howto->type;
4553d8817e4Smiod
4563d8817e4Smiod vars->relcount ++;
4573d8817e4Smiod
4583d8817e4Smiod BFD_ASSERT (vars->relcount <= NUM_ILF_RELOCS);
4593d8817e4Smiod }
4603d8817e4Smiod
4613d8817e4Smiod /* Create an empty relocation against the given section. */
4623d8817e4Smiod
4633d8817e4Smiod static void
pe_ILF_make_a_reloc(pe_ILF_vars * vars,bfd_vma address,bfd_reloc_code_real_type reloc,asection_ptr sec)4643d8817e4Smiod pe_ILF_make_a_reloc (pe_ILF_vars * vars,
4653d8817e4Smiod bfd_vma address,
4663d8817e4Smiod bfd_reloc_code_real_type reloc,
4673d8817e4Smiod asection_ptr sec)
4683d8817e4Smiod {
4693d8817e4Smiod pe_ILF_make_a_symbol_reloc (vars, address, reloc, sec->symbol_ptr_ptr,
4703d8817e4Smiod coff_section_data (vars->abfd, sec)->i);
4713d8817e4Smiod }
4723d8817e4Smiod
4733d8817e4Smiod /* Move the queued relocs into the given section. */
4743d8817e4Smiod
4753d8817e4Smiod static void
pe_ILF_save_relocs(pe_ILF_vars * vars,asection_ptr sec)4763d8817e4Smiod pe_ILF_save_relocs (pe_ILF_vars * vars,
4773d8817e4Smiod asection_ptr sec)
4783d8817e4Smiod {
4793d8817e4Smiod /* Make sure that there is somewhere to store the internal relocs. */
4803d8817e4Smiod if (coff_section_data (vars->abfd, sec) == NULL)
4813d8817e4Smiod /* We should probably return an error indication here. */
4823d8817e4Smiod abort ();
4833d8817e4Smiod
4843d8817e4Smiod coff_section_data (vars->abfd, sec)->relocs = vars->int_reltab;
4853d8817e4Smiod coff_section_data (vars->abfd, sec)->keep_relocs = TRUE;
4863d8817e4Smiod
4873d8817e4Smiod sec->relocation = vars->reltab;
4883d8817e4Smiod sec->reloc_count = vars->relcount;
4893d8817e4Smiod sec->flags |= SEC_RELOC;
4903d8817e4Smiod
4913d8817e4Smiod vars->reltab += vars->relcount;
4923d8817e4Smiod vars->int_reltab += vars->relcount;
4933d8817e4Smiod vars->relcount = 0;
4943d8817e4Smiod
4953d8817e4Smiod BFD_ASSERT ((bfd_byte *) vars->int_reltab < (bfd_byte *) vars->string_table);
4963d8817e4Smiod }
4973d8817e4Smiod
4983d8817e4Smiod /* Create a global symbol and add it to the relevant tables. */
4993d8817e4Smiod
5003d8817e4Smiod static void
pe_ILF_make_a_symbol(pe_ILF_vars * vars,const char * prefix,const char * symbol_name,asection_ptr section,flagword extra_flags)5013d8817e4Smiod pe_ILF_make_a_symbol (pe_ILF_vars * vars,
5023d8817e4Smiod const char * prefix,
5033d8817e4Smiod const char * symbol_name,
5043d8817e4Smiod asection_ptr section,
5053d8817e4Smiod flagword extra_flags)
5063d8817e4Smiod {
5073d8817e4Smiod coff_symbol_type * sym;
5083d8817e4Smiod combined_entry_type * ent;
5093d8817e4Smiod SYMENT * esym;
5103d8817e4Smiod unsigned short sclass;
5113d8817e4Smiod
5123d8817e4Smiod if (extra_flags & BSF_LOCAL)
5133d8817e4Smiod sclass = C_STAT;
5143d8817e4Smiod else
5153d8817e4Smiod sclass = C_EXT;
5163d8817e4Smiod
5173d8817e4Smiod #ifdef THUMBPEMAGIC
5183d8817e4Smiod if (vars->magic == THUMBPEMAGIC)
5193d8817e4Smiod {
5203d8817e4Smiod if (extra_flags & BSF_FUNCTION)
5213d8817e4Smiod sclass = C_THUMBEXTFUNC;
5223d8817e4Smiod else if (extra_flags & BSF_LOCAL)
5233d8817e4Smiod sclass = C_THUMBSTAT;
5243d8817e4Smiod else
5253d8817e4Smiod sclass = C_THUMBEXT;
5263d8817e4Smiod }
5273d8817e4Smiod #endif
5283d8817e4Smiod
5293d8817e4Smiod BFD_ASSERT (vars->sym_index < NUM_ILF_SYMS);
5303d8817e4Smiod
5313d8817e4Smiod sym = vars->sym_ptr;
5323d8817e4Smiod ent = vars->native_ptr;
5333d8817e4Smiod esym = vars->esym_ptr;
5343d8817e4Smiod
5353d8817e4Smiod /* Copy the symbol's name into the string table. */
5363d8817e4Smiod sprintf (vars->string_ptr, "%s%s", prefix, symbol_name);
5373d8817e4Smiod
5383d8817e4Smiod if (section == NULL)
5393d8817e4Smiod section = (asection_ptr) & bfd_und_section;
5403d8817e4Smiod
5413d8817e4Smiod /* Initialise the external symbol. */
5423d8817e4Smiod H_PUT_32 (vars->abfd, vars->string_ptr - vars->string_table,
5433d8817e4Smiod esym->e.e.e_offset);
5443d8817e4Smiod H_PUT_16 (vars->abfd, section->target_index, esym->e_scnum);
5453d8817e4Smiod esym->e_sclass[0] = sclass;
5463d8817e4Smiod
5473d8817e4Smiod /* The following initialisations are unnecessary - the memory is
5483d8817e4Smiod zero initialised. They are just kept here as reminders. */
5493d8817e4Smiod
5503d8817e4Smiod /* Initialise the internal symbol structure. */
5513d8817e4Smiod ent->u.syment.n_sclass = sclass;
5523d8817e4Smiod ent->u.syment.n_scnum = section->target_index;
5533d8817e4Smiod ent->u.syment._n._n_n._n_offset = (long) sym;
5543d8817e4Smiod
5553d8817e4Smiod sym->symbol.the_bfd = vars->abfd;
5563d8817e4Smiod sym->symbol.name = vars->string_ptr;
5573d8817e4Smiod sym->symbol.flags = BSF_EXPORT | BSF_GLOBAL | extra_flags;
5583d8817e4Smiod sym->symbol.section = section;
5593d8817e4Smiod sym->native = ent;
5603d8817e4Smiod
5613d8817e4Smiod * vars->table_ptr = vars->sym_index;
5623d8817e4Smiod * vars->sym_ptr_ptr = sym;
5633d8817e4Smiod
5643d8817e4Smiod /* Adjust pointers for the next symbol. */
5653d8817e4Smiod vars->sym_index ++;
5663d8817e4Smiod vars->sym_ptr ++;
5673d8817e4Smiod vars->sym_ptr_ptr ++;
5683d8817e4Smiod vars->table_ptr ++;
5693d8817e4Smiod vars->native_ptr ++;
5703d8817e4Smiod vars->esym_ptr ++;
5713d8817e4Smiod vars->string_ptr += strlen (symbol_name) + strlen (prefix) + 1;
5723d8817e4Smiod
5733d8817e4Smiod BFD_ASSERT (vars->string_ptr < vars->end_string_ptr);
5743d8817e4Smiod }
5753d8817e4Smiod
5763d8817e4Smiod /* Create a section. */
5773d8817e4Smiod
5783d8817e4Smiod static asection_ptr
pe_ILF_make_a_section(pe_ILF_vars * vars,const char * name,unsigned int size,flagword extra_flags)5793d8817e4Smiod pe_ILF_make_a_section (pe_ILF_vars * vars,
5803d8817e4Smiod const char * name,
5813d8817e4Smiod unsigned int size,
5823d8817e4Smiod flagword extra_flags)
5833d8817e4Smiod {
5843d8817e4Smiod asection_ptr sec;
5853d8817e4Smiod flagword flags;
5863d8817e4Smiod
5873d8817e4Smiod sec = bfd_make_section_old_way (vars->abfd, name);
5883d8817e4Smiod if (sec == NULL)
5893d8817e4Smiod return NULL;
5903d8817e4Smiod
5913d8817e4Smiod flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_IN_MEMORY;
5923d8817e4Smiod
5933d8817e4Smiod bfd_set_section_flags (vars->abfd, sec, flags | extra_flags);
5943d8817e4Smiod
5953d8817e4Smiod bfd_set_section_alignment (vars->abfd, sec, 2);
5963d8817e4Smiod
5973d8817e4Smiod /* Check that we will not run out of space. */
5983d8817e4Smiod BFD_ASSERT (vars->data + size < vars->bim->buffer + vars->bim->size);
5993d8817e4Smiod
6003d8817e4Smiod /* Set the section size and contents. The actual
6013d8817e4Smiod contents are filled in by our parent. */
6023d8817e4Smiod bfd_set_section_size (vars->abfd, sec, (bfd_size_type) size);
6033d8817e4Smiod sec->contents = vars->data;
6043d8817e4Smiod sec->target_index = vars->sec_index ++;
6053d8817e4Smiod
6063d8817e4Smiod /* Advance data pointer in the vars structure. */
6073d8817e4Smiod vars->data += size;
6083d8817e4Smiod
6093d8817e4Smiod /* Skip the padding byte if it was not needed.
6103d8817e4Smiod The logic here is that if the string length is odd,
6113d8817e4Smiod then the entire string length, including the null byte,
6123d8817e4Smiod is even and so the extra, padding byte, is not needed. */
6133d8817e4Smiod if (size & 1)
6143d8817e4Smiod vars->data --;
6153d8817e4Smiod
6163d8817e4Smiod /* Create a coff_section_tdata structure for our use. */
6173d8817e4Smiod sec->used_by_bfd = (struct coff_section_tdata *) vars->data;
6183d8817e4Smiod vars->data += sizeof (struct coff_section_tdata);
6193d8817e4Smiod
6203d8817e4Smiod BFD_ASSERT (vars->data <= vars->bim->buffer + vars->bim->size);
6213d8817e4Smiod
6223d8817e4Smiod /* Create a symbol to refer to this section. */
6233d8817e4Smiod pe_ILF_make_a_symbol (vars, "", name, sec, BSF_LOCAL);
6243d8817e4Smiod
6253d8817e4Smiod /* Cache the index to the symbol in the coff_section_data structure. */
6263d8817e4Smiod coff_section_data (vars->abfd, sec)->i = vars->sym_index - 1;
6273d8817e4Smiod
6283d8817e4Smiod return sec;
6293d8817e4Smiod }
6303d8817e4Smiod
6313d8817e4Smiod /* This structure contains the code that goes into the .text section
6323d8817e4Smiod in order to perform a jump into the DLL lookup table. The entries
6333d8817e4Smiod in the table are index by the magic number used to represent the
6343d8817e4Smiod machine type in the PE file. The contents of the data[] arrays in
6353d8817e4Smiod these entries are stolen from the jtab[] arrays in ld/pe-dll.c.
6363d8817e4Smiod The SIZE field says how many bytes in the DATA array are actually
6373d8817e4Smiod used. The OFFSET field says where in the data array the address
6383d8817e4Smiod of the .idata$5 section should be placed. */
6393d8817e4Smiod #define MAX_TEXT_SECTION_SIZE 32
6403d8817e4Smiod
6413d8817e4Smiod typedef struct
6423d8817e4Smiod {
6433d8817e4Smiod unsigned short magic;
6443d8817e4Smiod unsigned char data[MAX_TEXT_SECTION_SIZE];
6453d8817e4Smiod unsigned int size;
6463d8817e4Smiod unsigned int offset;
6473d8817e4Smiod }
6483d8817e4Smiod jump_table;
6493d8817e4Smiod
6503d8817e4Smiod static jump_table jtab[] =
6513d8817e4Smiod {
6523d8817e4Smiod #ifdef I386MAGIC
6533d8817e4Smiod { I386MAGIC,
6543d8817e4Smiod { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 },
6553d8817e4Smiod 8, 2
6563d8817e4Smiod },
6573d8817e4Smiod #endif
6583d8817e4Smiod
6593d8817e4Smiod #ifdef MC68MAGIC
6603d8817e4Smiod { MC68MAGIC, { /* XXX fill me in */ }, 0, 0 },
6613d8817e4Smiod #endif
6623d8817e4Smiod #ifdef MIPS_ARCH_MAGIC_WINCE
6633d8817e4Smiod { MIPS_ARCH_MAGIC_WINCE,
6643d8817e4Smiod { 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d,
6653d8817e4Smiod 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 },
6663d8817e4Smiod 16, 0
6673d8817e4Smiod },
6683d8817e4Smiod #endif
6693d8817e4Smiod
6703d8817e4Smiod #ifdef SH_ARCH_MAGIC_WINCE
6713d8817e4Smiod { SH_ARCH_MAGIC_WINCE,
6723d8817e4Smiod { 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40,
6733d8817e4Smiod 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 },
6743d8817e4Smiod 12, 8
6753d8817e4Smiod },
6763d8817e4Smiod #endif
6773d8817e4Smiod
6783d8817e4Smiod #ifdef ARMPEMAGIC
6793d8817e4Smiod { ARMPEMAGIC,
6803d8817e4Smiod { 0x00, 0xc0, 0x9f, 0xe5, 0x00, 0xf0,
6813d8817e4Smiod 0x9c, 0xe5, 0x00, 0x00, 0x00, 0x00},
6823d8817e4Smiod 12, 8
6833d8817e4Smiod },
6843d8817e4Smiod #endif
6853d8817e4Smiod
6863d8817e4Smiod #ifdef THUMBPEMAGIC
6873d8817e4Smiod { THUMBPEMAGIC,
6883d8817e4Smiod { 0x40, 0xb4, 0x02, 0x4e, 0x36, 0x68, 0xb4, 0x46,
6893d8817e4Smiod 0x40, 0xbc, 0x60, 0x47, 0x00, 0x00, 0x00, 0x00 },
6903d8817e4Smiod 16, 12
6913d8817e4Smiod },
6923d8817e4Smiod #endif
6933d8817e4Smiod { 0, { 0 }, 0, 0 }
6943d8817e4Smiod };
6953d8817e4Smiod
6963d8817e4Smiod #ifndef NUM_ENTRIES
6973d8817e4Smiod #define NUM_ENTRIES(a) (sizeof (a) / sizeof (a)[0])
6983d8817e4Smiod #endif
6993d8817e4Smiod
7003d8817e4Smiod /* Build a full BFD from the information supplied in a ILF object. */
7013d8817e4Smiod
7023d8817e4Smiod static bfd_boolean
pe_ILF_build_a_bfd(bfd * abfd,unsigned int magic,char * symbol_name,char * source_dll,unsigned int ordinal,unsigned int types)7033d8817e4Smiod pe_ILF_build_a_bfd (bfd * abfd,
7043d8817e4Smiod unsigned int magic,
7053d8817e4Smiod char * symbol_name,
7063d8817e4Smiod char * source_dll,
7073d8817e4Smiod unsigned int ordinal,
7083d8817e4Smiod unsigned int types)
7093d8817e4Smiod {
7103d8817e4Smiod bfd_byte * ptr;
7113d8817e4Smiod pe_ILF_vars vars;
7123d8817e4Smiod struct internal_filehdr internal_f;
7133d8817e4Smiod unsigned int import_type;
7143d8817e4Smiod unsigned int import_name_type;
7153d8817e4Smiod asection_ptr id4, id5, id6 = NULL, text = NULL;
7163d8817e4Smiod coff_symbol_type ** imp_sym;
7173d8817e4Smiod unsigned int imp_index;
7183d8817e4Smiod
7193d8817e4Smiod /* Decode and verify the types field of the ILF structure. */
7203d8817e4Smiod import_type = types & 0x3;
7213d8817e4Smiod import_name_type = (types & 0x1c) >> 2;
7223d8817e4Smiod
7233d8817e4Smiod switch (import_type)
7243d8817e4Smiod {
7253d8817e4Smiod case IMPORT_CODE:
7263d8817e4Smiod case IMPORT_DATA:
7273d8817e4Smiod break;
7283d8817e4Smiod
7293d8817e4Smiod case IMPORT_CONST:
7303d8817e4Smiod /* XXX code yet to be written. */
7313d8817e4Smiod _bfd_error_handler (_("%B: Unhandled import type; %x"),
7323d8817e4Smiod abfd, import_type);
7333d8817e4Smiod return FALSE;
7343d8817e4Smiod
7353d8817e4Smiod default:
7363d8817e4Smiod _bfd_error_handler (_("%B: Unrecognised import type; %x"),
7373d8817e4Smiod abfd, import_type);
7383d8817e4Smiod return FALSE;
7393d8817e4Smiod }
7403d8817e4Smiod
7413d8817e4Smiod switch (import_name_type)
7423d8817e4Smiod {
7433d8817e4Smiod case IMPORT_ORDINAL:
7443d8817e4Smiod case IMPORT_NAME:
7453d8817e4Smiod case IMPORT_NAME_NOPREFIX:
7463d8817e4Smiod case IMPORT_NAME_UNDECORATE:
7473d8817e4Smiod break;
7483d8817e4Smiod
7493d8817e4Smiod default:
7503d8817e4Smiod _bfd_error_handler (_("%B: Unrecognised import name type; %x"),
7513d8817e4Smiod abfd, import_name_type);
7523d8817e4Smiod return FALSE;
7533d8817e4Smiod }
7543d8817e4Smiod
7553d8817e4Smiod /* Initialise local variables.
7563d8817e4Smiod
7573d8817e4Smiod Note these are kept in a structure rather than being
7583d8817e4Smiod declared as statics since bfd frowns on global variables.
7593d8817e4Smiod
7603d8817e4Smiod We are going to construct the contents of the BFD in memory,
7613d8817e4Smiod so allocate all the space that we will need right now. */
7623d8817e4Smiod ptr = bfd_zalloc (abfd, (bfd_size_type) ILF_DATA_SIZE);
7633d8817e4Smiod if (ptr == NULL)
7643d8817e4Smiod return FALSE;
7653d8817e4Smiod
7663d8817e4Smiod /* Create a bfd_in_memory structure. */
7673d8817e4Smiod vars.bim = (struct bfd_in_memory *) ptr;
7683d8817e4Smiod vars.bim->buffer = ptr;
7693d8817e4Smiod vars.bim->size = ILF_DATA_SIZE;
7703d8817e4Smiod ptr += sizeof (* vars.bim);
7713d8817e4Smiod
7723d8817e4Smiod /* Initialise the pointers to regions of the memory and the
7733d8817e4Smiod other contents of the pe_ILF_vars structure as well. */
7743d8817e4Smiod vars.sym_cache = (coff_symbol_type *) ptr;
7753d8817e4Smiod vars.sym_ptr = (coff_symbol_type *) ptr;
7763d8817e4Smiod vars.sym_index = 0;
7773d8817e4Smiod ptr += SIZEOF_ILF_SYMS;
7783d8817e4Smiod
7793d8817e4Smiod vars.sym_table = (unsigned int *) ptr;
7803d8817e4Smiod vars.table_ptr = (unsigned int *) ptr;
7813d8817e4Smiod ptr += SIZEOF_ILF_SYM_TABLE;
7823d8817e4Smiod
7833d8817e4Smiod vars.native_syms = (combined_entry_type *) ptr;
7843d8817e4Smiod vars.native_ptr = (combined_entry_type *) ptr;
7853d8817e4Smiod ptr += SIZEOF_ILF_NATIVE_SYMS;
7863d8817e4Smiod
7873d8817e4Smiod vars.sym_ptr_table = (coff_symbol_type **) ptr;
7883d8817e4Smiod vars.sym_ptr_ptr = (coff_symbol_type **) ptr;
7893d8817e4Smiod ptr += SIZEOF_ILF_SYM_PTR_TABLE;
7903d8817e4Smiod
7913d8817e4Smiod vars.esym_table = (SYMENT *) ptr;
7923d8817e4Smiod vars.esym_ptr = (SYMENT *) ptr;
7933d8817e4Smiod ptr += SIZEOF_ILF_EXT_SYMS;
7943d8817e4Smiod
7953d8817e4Smiod vars.reltab = (arelent *) ptr;
7963d8817e4Smiod vars.relcount = 0;
7973d8817e4Smiod ptr += SIZEOF_ILF_RELOCS;
7983d8817e4Smiod
7993d8817e4Smiod vars.int_reltab = (struct internal_reloc *) ptr;
8003d8817e4Smiod ptr += SIZEOF_ILF_INT_RELOCS;
8013d8817e4Smiod
8023d8817e4Smiod vars.string_table = (char *) ptr;
8033d8817e4Smiod vars.string_ptr = (char *) ptr + STRING_SIZE_SIZE;
8043d8817e4Smiod ptr += SIZEOF_ILF_STRINGS;
8053d8817e4Smiod vars.end_string_ptr = (char *) ptr;
8063d8817e4Smiod
8073d8817e4Smiod /* The remaining space in bim->buffer is used
8083d8817e4Smiod by the pe_ILF_make_a_section() function. */
8093d8817e4Smiod vars.data = ptr;
8103d8817e4Smiod vars.abfd = abfd;
8113d8817e4Smiod vars.sec_index = 0;
8123d8817e4Smiod vars.magic = magic;
8133d8817e4Smiod
8143d8817e4Smiod /* Create the initial .idata$<n> sections:
8153d8817e4Smiod [.idata$2: Import Directory Table -- not needed]
8163d8817e4Smiod .idata$4: Import Lookup Table
8173d8817e4Smiod .idata$5: Import Address Table
8183d8817e4Smiod
8193d8817e4Smiod Note we do not create a .idata$3 section as this is
8203d8817e4Smiod created for us by the linker script. */
8213d8817e4Smiod id4 = pe_ILF_make_a_section (& vars, ".idata$4", SIZEOF_IDATA4, 0);
8223d8817e4Smiod id5 = pe_ILF_make_a_section (& vars, ".idata$5", SIZEOF_IDATA5, 0);
8233d8817e4Smiod if (id4 == NULL || id5 == NULL)
8243d8817e4Smiod return FALSE;
8253d8817e4Smiod
8263d8817e4Smiod /* Fill in the contents of these sections. */
8273d8817e4Smiod if (import_name_type == IMPORT_ORDINAL)
8283d8817e4Smiod {
8293d8817e4Smiod if (ordinal == 0)
8303d8817e4Smiod /* XXX - treat as IMPORT_NAME ??? */
8313d8817e4Smiod abort ();
8323d8817e4Smiod
8333d8817e4Smiod * (unsigned int *) id4->contents = ordinal | 0x80000000;
8343d8817e4Smiod * (unsigned int *) id5->contents = ordinal | 0x80000000;
8353d8817e4Smiod }
8363d8817e4Smiod else
8373d8817e4Smiod {
8383d8817e4Smiod char * symbol;
8393d8817e4Smiod unsigned int len;
8403d8817e4Smiod
8413d8817e4Smiod /* Create .idata$6 - the Hint Name Table. */
8423d8817e4Smiod id6 = pe_ILF_make_a_section (& vars, ".idata$6", SIZEOF_IDATA6, 0);
8433d8817e4Smiod if (id6 == NULL)
8443d8817e4Smiod return FALSE;
8453d8817e4Smiod
8463d8817e4Smiod /* If necessary, trim the import symbol name. */
8473d8817e4Smiod symbol = symbol_name;
8483d8817e4Smiod
8493d8817e4Smiod /* As used by MS compiler, '_', '@', and '?' are alternative
8503d8817e4Smiod forms of USER_LABEL_PREFIX, with '?' for c++ mangled names,
8513d8817e4Smiod '@' used for fastcall (in C), '_' everywhere else. Only one
8523d8817e4Smiod of these is used for a symbol. We strip this leading char for
8533d8817e4Smiod IMPORT_NAME_NOPREFIX and IMPORT_NAME_UNDECORATE as per the
8543d8817e4Smiod PE COFF 6.0 spec (section 8.3, Import Name Type). */
8553d8817e4Smiod
8563d8817e4Smiod if (import_name_type != IMPORT_NAME)
8573d8817e4Smiod {
8583d8817e4Smiod char c = symbol[0];
8593d8817e4Smiod if (c == '_' || c == '@' || c == '?')
8603d8817e4Smiod symbol++;
8613d8817e4Smiod }
8623d8817e4Smiod
8633d8817e4Smiod len = strlen (symbol);
8643d8817e4Smiod if (import_name_type == IMPORT_NAME_UNDECORATE)
8653d8817e4Smiod {
8663d8817e4Smiod /* Truncate at the first '@'. */
8673d8817e4Smiod char *at = strchr (symbol, '@');
8683d8817e4Smiod
8693d8817e4Smiod if (at != NULL)
8703d8817e4Smiod len = at - symbol;
8713d8817e4Smiod }
8723d8817e4Smiod
8733d8817e4Smiod id6->contents[0] = ordinal & 0xff;
8743d8817e4Smiod id6->contents[1] = ordinal >> 8;
8753d8817e4Smiod
8763d8817e4Smiod memcpy ((char *) id6->contents + 2, symbol, len);
8773d8817e4Smiod id6->contents[len + 2] = '\0';
8783d8817e4Smiod }
8793d8817e4Smiod
8803d8817e4Smiod if (import_name_type != IMPORT_ORDINAL)
8813d8817e4Smiod {
8823d8817e4Smiod pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_RVA, id6);
8833d8817e4Smiod pe_ILF_save_relocs (&vars, id4);
8843d8817e4Smiod
8853d8817e4Smiod pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_RVA, id6);
8863d8817e4Smiod pe_ILF_save_relocs (&vars, id5);
8873d8817e4Smiod }
8883d8817e4Smiod
8893d8817e4Smiod /* Create extra sections depending upon the type of import we are dealing with. */
8903d8817e4Smiod switch (import_type)
8913d8817e4Smiod {
8923d8817e4Smiod int i;
8933d8817e4Smiod
8943d8817e4Smiod case IMPORT_CODE:
8953d8817e4Smiod /* Create a .text section.
8963d8817e4Smiod First we need to look up its contents in the jump table. */
8973d8817e4Smiod for (i = NUM_ENTRIES (jtab); i--;)
8983d8817e4Smiod {
8993d8817e4Smiod if (jtab[i].size == 0)
9003d8817e4Smiod continue;
9013d8817e4Smiod if (jtab[i].magic == magic)
9023d8817e4Smiod break;
9033d8817e4Smiod }
9043d8817e4Smiod /* If we did not find a matching entry something is wrong. */
9053d8817e4Smiod if (i < 0)
9063d8817e4Smiod abort ();
9073d8817e4Smiod
9083d8817e4Smiod /* Create the .text section. */
9093d8817e4Smiod text = pe_ILF_make_a_section (& vars, ".text", jtab[i].size, SEC_CODE);
9103d8817e4Smiod if (text == NULL)
9113d8817e4Smiod return FALSE;
9123d8817e4Smiod
9133d8817e4Smiod /* Copy in the jump code. */
9143d8817e4Smiod memcpy (text->contents, jtab[i].data, jtab[i].size);
9153d8817e4Smiod
9163d8817e4Smiod /* Create an import symbol. */
9173d8817e4Smiod pe_ILF_make_a_symbol (& vars, "__imp_", symbol_name, id5, 0);
9183d8817e4Smiod imp_sym = vars.sym_ptr_ptr - 1;
9193d8817e4Smiod imp_index = vars.sym_index - 1;
9203d8817e4Smiod
9213d8817e4Smiod /* Create a reloc for the data in the text section. */
9223d8817e4Smiod #ifdef MIPS_ARCH_MAGIC_WINCE
9233d8817e4Smiod if (magic == MIPS_ARCH_MAGIC_WINCE)
9243d8817e4Smiod {
9253d8817e4Smiod pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) 0, BFD_RELOC_HI16_S,
9263d8817e4Smiod (struct bfd_symbol **) imp_sym,
9273d8817e4Smiod imp_index);
9283d8817e4Smiod pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_LO16, text);
9293d8817e4Smiod pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) 4, BFD_RELOC_LO16,
9303d8817e4Smiod (struct bfd_symbol **) imp_sym,
9313d8817e4Smiod imp_index);
9323d8817e4Smiod }
9333d8817e4Smiod else
9343d8817e4Smiod #endif
9353d8817e4Smiod pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
9363d8817e4Smiod BFD_RELOC_32, (asymbol **) imp_sym,
9373d8817e4Smiod imp_index);
9383d8817e4Smiod
9393d8817e4Smiod pe_ILF_save_relocs (& vars, text);
9403d8817e4Smiod break;
9413d8817e4Smiod
9423d8817e4Smiod case IMPORT_DATA:
9433d8817e4Smiod break;
9443d8817e4Smiod
9453d8817e4Smiod default:
9463d8817e4Smiod /* XXX code not yet written. */
9473d8817e4Smiod abort ();
9483d8817e4Smiod }
9493d8817e4Smiod
9503d8817e4Smiod /* Initialise the bfd. */
9513d8817e4Smiod memset (& internal_f, 0, sizeof (internal_f));
9523d8817e4Smiod
9533d8817e4Smiod internal_f.f_magic = magic;
9543d8817e4Smiod internal_f.f_symptr = 0;
9553d8817e4Smiod internal_f.f_nsyms = 0;
9563d8817e4Smiod internal_f.f_flags = F_AR32WR | F_LNNO; /* XXX is this correct ? */
9573d8817e4Smiod
9583d8817e4Smiod if ( ! bfd_set_start_address (abfd, (bfd_vma) 0)
9593d8817e4Smiod || ! bfd_coff_set_arch_mach_hook (abfd, & internal_f))
9603d8817e4Smiod return FALSE;
9613d8817e4Smiod
9623d8817e4Smiod if (bfd_coff_mkobject_hook (abfd, (void *) & internal_f, NULL) == NULL)
9633d8817e4Smiod return FALSE;
9643d8817e4Smiod
9653d8817e4Smiod coff_data (abfd)->pe = 1;
9663d8817e4Smiod #ifdef THUMBPEMAGIC
9673d8817e4Smiod if (vars.magic == THUMBPEMAGIC)
9683d8817e4Smiod /* Stop some linker warnings about thumb code not supporting interworking. */
9693d8817e4Smiod coff_data (abfd)->flags |= F_INTERWORK | F_INTERWORK_SET;
9703d8817e4Smiod #endif
9713d8817e4Smiod
9723d8817e4Smiod /* Switch from file contents to memory contents. */
9733d8817e4Smiod bfd_cache_close (abfd);
9743d8817e4Smiod
9753d8817e4Smiod abfd->iostream = (void *) vars.bim;
9763d8817e4Smiod abfd->flags |= BFD_IN_MEMORY /* | HAS_LOCALS */;
9773d8817e4Smiod abfd->where = 0;
9783d8817e4Smiod obj_sym_filepos (abfd) = 0;
9793d8817e4Smiod
9803d8817e4Smiod /* Now create a symbol describing the imported value. */
9813d8817e4Smiod switch (import_type)
9823d8817e4Smiod {
9833d8817e4Smiod case IMPORT_CODE:
9843d8817e4Smiod pe_ILF_make_a_symbol (& vars, "", symbol_name, text,
9853d8817e4Smiod BSF_NOT_AT_END | BSF_FUNCTION);
9863d8817e4Smiod
9873d8817e4Smiod /* Create an import symbol for the DLL, without the
9883d8817e4Smiod .dll suffix. */
9893d8817e4Smiod ptr = (bfd_byte *) strrchr (source_dll, '.');
9903d8817e4Smiod if (ptr)
9913d8817e4Smiod * ptr = 0;
9923d8817e4Smiod pe_ILF_make_a_symbol (& vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0);
9933d8817e4Smiod if (ptr)
9943d8817e4Smiod * ptr = '.';
9953d8817e4Smiod break;
9963d8817e4Smiod
9973d8817e4Smiod case IMPORT_DATA:
9983d8817e4Smiod /* Nothing to do here. */
9993d8817e4Smiod break;
10003d8817e4Smiod
10013d8817e4Smiod default:
10023d8817e4Smiod /* XXX code not yet written. */
10033d8817e4Smiod abort ();
10043d8817e4Smiod }
10053d8817e4Smiod
10063d8817e4Smiod /* Point the bfd at the symbol table. */
10073d8817e4Smiod obj_symbols (abfd) = vars.sym_cache;
10083d8817e4Smiod bfd_get_symcount (abfd) = vars.sym_index;
10093d8817e4Smiod
10103d8817e4Smiod obj_raw_syments (abfd) = vars.native_syms;
10113d8817e4Smiod obj_raw_syment_count (abfd) = vars.sym_index;
10123d8817e4Smiod
10133d8817e4Smiod obj_coff_external_syms (abfd) = (void *) vars.esym_table;
10143d8817e4Smiod obj_coff_keep_syms (abfd) = TRUE;
10153d8817e4Smiod
10163d8817e4Smiod obj_convert (abfd) = vars.sym_table;
10173d8817e4Smiod obj_conv_table_size (abfd) = vars.sym_index;
10183d8817e4Smiod
10193d8817e4Smiod obj_coff_strings (abfd) = vars.string_table;
10203d8817e4Smiod obj_coff_keep_strings (abfd) = TRUE;
10213d8817e4Smiod
10223d8817e4Smiod abfd->flags |= HAS_SYMS;
10233d8817e4Smiod
10243d8817e4Smiod return TRUE;
10253d8817e4Smiod }
10263d8817e4Smiod
10273d8817e4Smiod /* We have detected a Image Library Format archive element.
10283d8817e4Smiod Decode the element and return the appropriate target. */
10293d8817e4Smiod
10303d8817e4Smiod static const bfd_target *
pe_ILF_object_p(bfd * abfd)10313d8817e4Smiod pe_ILF_object_p (bfd * abfd)
10323d8817e4Smiod {
10333d8817e4Smiod bfd_byte buffer[16];
10343d8817e4Smiod bfd_byte * ptr;
10353d8817e4Smiod char * symbol_name;
10363d8817e4Smiod char * source_dll;
10373d8817e4Smiod unsigned int machine;
10383d8817e4Smiod bfd_size_type size;
10393d8817e4Smiod unsigned int ordinal;
10403d8817e4Smiod unsigned int types;
10413d8817e4Smiod unsigned int magic;
10423d8817e4Smiod
10433d8817e4Smiod /* Upon entry the first four buyes of the ILF header have
10443d8817e4Smiod already been read. Now read the rest of the header. */
10453d8817e4Smiod if (bfd_bread (buffer, (bfd_size_type) 16, abfd) != 16)
10463d8817e4Smiod return NULL;
10473d8817e4Smiod
10483d8817e4Smiod ptr = buffer;
10493d8817e4Smiod
10503d8817e4Smiod /* We do not bother to check the version number.
10513d8817e4Smiod version = H_GET_16 (abfd, ptr); */
10523d8817e4Smiod ptr += 2;
10533d8817e4Smiod
10543d8817e4Smiod machine = H_GET_16 (abfd, ptr);
10553d8817e4Smiod ptr += 2;
10563d8817e4Smiod
10573d8817e4Smiod /* Check that the machine type is recognised. */
10583d8817e4Smiod magic = 0;
10593d8817e4Smiod
10603d8817e4Smiod switch (machine)
10613d8817e4Smiod {
10623d8817e4Smiod case IMAGE_FILE_MACHINE_UNKNOWN:
10633d8817e4Smiod case IMAGE_FILE_MACHINE_ALPHA:
10643d8817e4Smiod case IMAGE_FILE_MACHINE_ALPHA64:
10653d8817e4Smiod case IMAGE_FILE_MACHINE_IA64:
10663d8817e4Smiod break;
10673d8817e4Smiod
10683d8817e4Smiod case IMAGE_FILE_MACHINE_I386:
10693d8817e4Smiod #ifdef I386MAGIC
10703d8817e4Smiod magic = I386MAGIC;
10713d8817e4Smiod #endif
10723d8817e4Smiod break;
10733d8817e4Smiod
1074*6e5cc252Skettenis case IMAGE_FILE_MACHINE_AMD64:
1075*6e5cc252Skettenis #ifdef AMD64MAGIC
1076*6e5cc252Skettenis magic = AMD64MAGIC;
1077*6e5cc252Skettenis #endif
1078*6e5cc252Skettenis break;
1079*6e5cc252Skettenis
10803d8817e4Smiod case IMAGE_FILE_MACHINE_M68K:
10813d8817e4Smiod #ifdef MC68AGIC
10823d8817e4Smiod magic = MC68MAGIC;
10833d8817e4Smiod #endif
10843d8817e4Smiod break;
10853d8817e4Smiod
10863d8817e4Smiod case IMAGE_FILE_MACHINE_R3000:
10873d8817e4Smiod case IMAGE_FILE_MACHINE_R4000:
10883d8817e4Smiod case IMAGE_FILE_MACHINE_R10000:
10893d8817e4Smiod
10903d8817e4Smiod case IMAGE_FILE_MACHINE_MIPS16:
10913d8817e4Smiod case IMAGE_FILE_MACHINE_MIPSFPU:
10923d8817e4Smiod case IMAGE_FILE_MACHINE_MIPSFPU16:
10933d8817e4Smiod #ifdef MIPS_ARCH_MAGIC_WINCE
10943d8817e4Smiod magic = MIPS_ARCH_MAGIC_WINCE;
10953d8817e4Smiod #endif
10963d8817e4Smiod break;
10973d8817e4Smiod
10983d8817e4Smiod case IMAGE_FILE_MACHINE_SH3:
10993d8817e4Smiod case IMAGE_FILE_MACHINE_SH4:
11003d8817e4Smiod #ifdef SH_ARCH_MAGIC_WINCE
11013d8817e4Smiod magic = SH_ARCH_MAGIC_WINCE;
11023d8817e4Smiod #endif
11033d8817e4Smiod break;
11043d8817e4Smiod
11053d8817e4Smiod case IMAGE_FILE_MACHINE_ARM:
11063d8817e4Smiod #ifdef ARMPEMAGIC
11073d8817e4Smiod magic = ARMPEMAGIC;
11083d8817e4Smiod #endif
11093d8817e4Smiod break;
11103d8817e4Smiod
11113d8817e4Smiod case IMAGE_FILE_MACHINE_THUMB:
11123d8817e4Smiod #ifdef THUMBPEMAGIC
11133d8817e4Smiod {
11143d8817e4Smiod extern const bfd_target TARGET_LITTLE_SYM;
11153d8817e4Smiod
11163d8817e4Smiod if (abfd->xvec == & TARGET_LITTLE_SYM)
11173d8817e4Smiod magic = THUMBPEMAGIC;
11183d8817e4Smiod }
11193d8817e4Smiod #endif
11203d8817e4Smiod break;
11213d8817e4Smiod
11223d8817e4Smiod case IMAGE_FILE_MACHINE_POWERPC:
11233d8817e4Smiod /* We no longer support PowerPC. */
11243d8817e4Smiod default:
11253d8817e4Smiod _bfd_error_handler
11263d8817e4Smiod (_("%B: Unrecognised machine type (0x%x)"
11273d8817e4Smiod " in Import Library Format archive"),
11283d8817e4Smiod abfd, machine);
11293d8817e4Smiod bfd_set_error (bfd_error_malformed_archive);
11303d8817e4Smiod
11313d8817e4Smiod return NULL;
11323d8817e4Smiod break;
11333d8817e4Smiod }
11343d8817e4Smiod
11353d8817e4Smiod if (magic == 0)
11363d8817e4Smiod {
11373d8817e4Smiod _bfd_error_handler
11383d8817e4Smiod (_("%B: Recognised but unhandled machine type (0x%x)"
11393d8817e4Smiod " in Import Library Format archive"),
11403d8817e4Smiod abfd, machine);
11413d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
11423d8817e4Smiod
11433d8817e4Smiod return NULL;
11443d8817e4Smiod }
11453d8817e4Smiod
11463d8817e4Smiod /* We do not bother to check the date.
11473d8817e4Smiod date = H_GET_32 (abfd, ptr); */
11483d8817e4Smiod ptr += 4;
11493d8817e4Smiod
11503d8817e4Smiod size = H_GET_32 (abfd, ptr);
11513d8817e4Smiod ptr += 4;
11523d8817e4Smiod
11533d8817e4Smiod if (size == 0)
11543d8817e4Smiod {
11553d8817e4Smiod _bfd_error_handler
11563d8817e4Smiod (_("%B: size field is zero in Import Library Format header"), abfd);
11573d8817e4Smiod bfd_set_error (bfd_error_malformed_archive);
11583d8817e4Smiod
11593d8817e4Smiod return NULL;
11603d8817e4Smiod }
11613d8817e4Smiod
11623d8817e4Smiod ordinal = H_GET_16 (abfd, ptr);
11633d8817e4Smiod ptr += 2;
11643d8817e4Smiod
11653d8817e4Smiod types = H_GET_16 (abfd, ptr);
11663d8817e4Smiod /* ptr += 2; */
11673d8817e4Smiod
11683d8817e4Smiod /* Now read in the two strings that follow. */
11693d8817e4Smiod ptr = bfd_alloc (abfd, size);
11703d8817e4Smiod if (ptr == NULL)
11713d8817e4Smiod return NULL;
11723d8817e4Smiod
11733d8817e4Smiod if (bfd_bread (ptr, size, abfd) != size)
11743d8817e4Smiod {
11753d8817e4Smiod bfd_release (abfd, ptr);
11763d8817e4Smiod return NULL;
11773d8817e4Smiod }
11783d8817e4Smiod
11793d8817e4Smiod symbol_name = (char *) ptr;
11803d8817e4Smiod source_dll = symbol_name + strlen (symbol_name) + 1;
11813d8817e4Smiod
11823d8817e4Smiod /* Verify that the strings are null terminated. */
11833d8817e4Smiod if (ptr[size - 1] != 0
11843d8817e4Smiod || (bfd_size_type) ((bfd_byte *) source_dll - ptr) >= size)
11853d8817e4Smiod {
11863d8817e4Smiod _bfd_error_handler
11873d8817e4Smiod (_("%B: string not null terminated in ILF object file."), abfd);
11883d8817e4Smiod bfd_set_error (bfd_error_malformed_archive);
11893d8817e4Smiod bfd_release (abfd, ptr);
11903d8817e4Smiod return NULL;
11913d8817e4Smiod }
11923d8817e4Smiod
11933d8817e4Smiod /* Now construct the bfd. */
11943d8817e4Smiod if (! pe_ILF_build_a_bfd (abfd, magic, symbol_name,
11953d8817e4Smiod source_dll, ordinal, types))
11963d8817e4Smiod {
11973d8817e4Smiod bfd_release (abfd, ptr);
11983d8817e4Smiod return NULL;
11993d8817e4Smiod }
12003d8817e4Smiod
12013d8817e4Smiod return abfd->xvec;
12023d8817e4Smiod }
12033d8817e4Smiod
12043d8817e4Smiod static const bfd_target *
pe_bfd_object_p(bfd * abfd)12053d8817e4Smiod pe_bfd_object_p (bfd * abfd)
12063d8817e4Smiod {
12073d8817e4Smiod bfd_byte buffer[4];
12083d8817e4Smiod struct external_PEI_DOS_hdr dos_hdr;
12093d8817e4Smiod struct external_PEI_IMAGE_hdr image_hdr;
12103d8817e4Smiod file_ptr offset;
12113d8817e4Smiod
12123d8817e4Smiod /* Detect if this a Microsoft Import Library Format element. */
12133d8817e4Smiod if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
12143d8817e4Smiod || bfd_bread (buffer, (bfd_size_type) 4, abfd) != 4)
12153d8817e4Smiod {
12163d8817e4Smiod if (bfd_get_error () != bfd_error_system_call)
12173d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
12183d8817e4Smiod return NULL;
12193d8817e4Smiod }
12203d8817e4Smiod
12213d8817e4Smiod if (H_GET_32 (abfd, buffer) == 0xffff0000)
12223d8817e4Smiod return pe_ILF_object_p (abfd);
12233d8817e4Smiod
12243d8817e4Smiod if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
12253d8817e4Smiod || bfd_bread (&dos_hdr, (bfd_size_type) sizeof (dos_hdr), abfd)
12263d8817e4Smiod != sizeof (dos_hdr))
12273d8817e4Smiod {
12283d8817e4Smiod if (bfd_get_error () != bfd_error_system_call)
12293d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
12303d8817e4Smiod return NULL;
12313d8817e4Smiod }
12323d8817e4Smiod
12333d8817e4Smiod /* There are really two magic numbers involved; the magic number
12343d8817e4Smiod that says this is a NT executable (PEI) and the magic number that
12353d8817e4Smiod determines the architecture. The former is DOSMAGIC, stored in
12363d8817e4Smiod the e_magic field. The latter is stored in the f_magic field.
12373d8817e4Smiod If the NT magic number isn't valid, the architecture magic number
12383d8817e4Smiod could be mimicked by some other field (specifically, the number
12393d8817e4Smiod of relocs in section 3). Since this routine can only be called
12403d8817e4Smiod correctly for a PEI file, check the e_magic number here, and, if
12413d8817e4Smiod it doesn't match, clobber the f_magic number so that we don't get
12423d8817e4Smiod a false match. */
12433d8817e4Smiod if (H_GET_16 (abfd, dos_hdr.e_magic) != DOSMAGIC)
12443d8817e4Smiod {
12453d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
12463d8817e4Smiod return NULL;
12473d8817e4Smiod }
12483d8817e4Smiod
12493d8817e4Smiod offset = H_GET_32 (abfd, dos_hdr.e_lfanew);
12503d8817e4Smiod if (bfd_seek (abfd, offset, SEEK_SET) != 0
12513d8817e4Smiod || (bfd_bread (&image_hdr, (bfd_size_type) sizeof (image_hdr), abfd)
12523d8817e4Smiod != sizeof (image_hdr)))
12533d8817e4Smiod {
12543d8817e4Smiod if (bfd_get_error () != bfd_error_system_call)
12553d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
12563d8817e4Smiod return NULL;
12573d8817e4Smiod }
12583d8817e4Smiod
12593d8817e4Smiod if (H_GET_32 (abfd, image_hdr.nt_signature) != 0x4550)
12603d8817e4Smiod {
12613d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
12623d8817e4Smiod return NULL;
12633d8817e4Smiod }
12643d8817e4Smiod
12653d8817e4Smiod /* Here is the hack. coff_object_p wants to read filhsz bytes to
12663d8817e4Smiod pick up the COFF header for PE, see "struct external_PEI_filehdr"
12673d8817e4Smiod in include/coff/pe.h. We adjust so that that will work. */
12683d8817e4Smiod if (bfd_seek (abfd, (file_ptr) (offset - sizeof (dos_hdr)), SEEK_SET) != 0)
12693d8817e4Smiod {
12703d8817e4Smiod if (bfd_get_error () != bfd_error_system_call)
12713d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
12723d8817e4Smiod return NULL;
12733d8817e4Smiod }
12743d8817e4Smiod
12753d8817e4Smiod return coff_object_p (abfd);
12763d8817e4Smiod }
12773d8817e4Smiod
12783d8817e4Smiod #define coff_object_p pe_bfd_object_p
12793d8817e4Smiod #endif /* COFF_IMAGE_WITH_PE */
1280