peicode.h revision 94536
184865Sobrien/* Support for the generic parts of PE/PEI, for BFD. 284865Sobrien Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001 384865Sobrien Free Software Foundation, Inc. 484865Sobrien Written by Cygnus Solutions. 584865Sobrien 684865SobrienThis file is part of BFD, the Binary File Descriptor library. 784865Sobrien 884865SobrienThis program is free software; you can redistribute it and/or modify 984865Sobrienit under the terms of the GNU General Public License as published by 1084865Sobrienthe Free Software Foundation; either version 2 of the License, or 1184865Sobrien(at your option) any later version. 1284865Sobrien 1384865SobrienThis program is distributed in the hope that it will be useful, 1484865Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1584865SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1684865SobrienGNU General Public License for more details. 1784865Sobrien 1884865SobrienYou should have received a copy of the GNU General Public License 1984865Sobrienalong with this program; if not, write to the Free Software 2084865SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2184865Sobrien 2284865Sobrien/* 2384865SobrienMost of this hacked by Steve Chamberlain, 2484865Sobrien sac@cygnus.com 2584865Sobrien 2684865SobrienPE/PEI rearrangement (and code added): Donn Terry 2784865Sobrien Softway Systems, Inc. 2884865Sobrien*/ 2984865Sobrien 3084865Sobrien/* Hey look, some documentation [and in a place you expect to find it]! 3184865Sobrien 3284865Sobrien The main reference for the pei format is "Microsoft Portable Executable 3384865Sobrien and Common Object File Format Specification 4.1". Get it if you need to 3484865Sobrien do some serious hacking on this code. 3584865Sobrien 3684865Sobrien Another reference: 3784865Sobrien "Peering Inside the PE: A Tour of the Win32 Portable Executable 3884865Sobrien File Format", MSJ 1994, Volume 9. 3984865Sobrien 4084865Sobrien The *sole* difference between the pe format and the pei format is that the 4184865Sobrien latter has an MSDOS 2.0 .exe header on the front that prints the message 4284865Sobrien "This app must be run under Windows." (or some such). 4384865Sobrien (FIXME: Whether that statement is *really* true or not is unknown. 4484865Sobrien Are there more subtle differences between pe and pei formats? 4584865Sobrien For now assume there aren't. If you find one, then for God sakes 4684865Sobrien document it here!) 4784865Sobrien 4884865Sobrien The Microsoft docs use the word "image" instead of "executable" because 4984865Sobrien the former can also refer to a DLL (shared library). Confusion can arise 5084865Sobrien because the `i' in `pei' also refers to "image". The `pe' format can 5184865Sobrien also create images (i.e. executables), it's just that to run on a win32 5284865Sobrien system you need to use the pei format. 5384865Sobrien 5484865Sobrien FIXME: Please add more docs here so the next poor fool that has to hack 5584865Sobrien on this code has a chance of getting something accomplished without 5684865Sobrien wasting too much time. 5784865Sobrien*/ 5884865Sobrien 5984865Sobrien#include "libpei.h" 6084865Sobrien 6184865Sobrienstatic boolean (*pe_saved_coff_bfd_print_private_bfd_data) 6284865Sobrien PARAMS ((bfd *, PTR)) = 6384865Sobrien#ifndef coff_bfd_print_private_bfd_data 6484865Sobrien NULL; 6584865Sobrien#else 6684865Sobrien coff_bfd_print_private_bfd_data; 6784865Sobrien#undef coff_bfd_print_private_bfd_data 6884865Sobrien#endif 6984865Sobrien 7084865Sobrienstatic boolean pe_print_private_bfd_data PARAMS ((bfd *, PTR)); 7184865Sobrien#define coff_bfd_print_private_bfd_data pe_print_private_bfd_data 7284865Sobrien 7384865Sobrienstatic boolean (*pe_saved_coff_bfd_copy_private_bfd_data) 7484865Sobrien PARAMS ((bfd *, bfd *)) = 7584865Sobrien#ifndef coff_bfd_copy_private_bfd_data 7684865Sobrien NULL; 7784865Sobrien#else 7884865Sobrien coff_bfd_copy_private_bfd_data; 7984865Sobrien#undef coff_bfd_copy_private_bfd_data 8084865Sobrien#endif 8184865Sobrien 8284865Sobrienstatic boolean pe_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *)); 8384865Sobrien#define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data 8484865Sobrien 8584865Sobrien#define coff_mkobject pe_mkobject 8684865Sobrien#define coff_mkobject_hook pe_mkobject_hook 8784865Sobrien 8884865Sobrien#ifndef NO_COFF_RELOCS 8984865Sobrienstatic void coff_swap_reloc_in PARAMS ((bfd *, PTR, PTR)); 9084865Sobrienstatic unsigned int coff_swap_reloc_out PARAMS ((bfd *, PTR, PTR)); 9184865Sobrien#endif 9284865Sobrienstatic void coff_swap_filehdr_in PARAMS ((bfd *, PTR, PTR)); 9384865Sobrienstatic void coff_swap_scnhdr_in PARAMS ((bfd *, PTR, PTR)); 9484865Sobrienstatic boolean pe_mkobject PARAMS ((bfd *)); 9584865Sobrienstatic PTR pe_mkobject_hook PARAMS ((bfd *, PTR, PTR)); 9684865Sobrien 9784865Sobrien#ifdef COFF_IMAGE_WITH_PE 9884865Sobrien/* This structure contains static variables used by the ILF code. */ 9984865Sobrientypedef asection * asection_ptr; 10084865Sobrien 10184865Sobrientypedef struct 10284865Sobrien{ 10384865Sobrien bfd * abfd; 10484865Sobrien bfd_byte * data; 10584865Sobrien struct bfd_in_memory * bim; 10684865Sobrien unsigned short magic; 10784865Sobrien 10884865Sobrien arelent * reltab; 10984865Sobrien unsigned int relcount; 11084865Sobrien 11184865Sobrien coff_symbol_type * sym_cache; 11284865Sobrien coff_symbol_type * sym_ptr; 11384865Sobrien unsigned int sym_index; 11484865Sobrien 11584865Sobrien unsigned int * sym_table; 11684865Sobrien unsigned int * table_ptr; 11784865Sobrien 11884865Sobrien combined_entry_type * native_syms; 11984865Sobrien combined_entry_type * native_ptr; 12084865Sobrien 12184865Sobrien coff_symbol_type ** sym_ptr_table; 12284865Sobrien coff_symbol_type ** sym_ptr_ptr; 12384865Sobrien 12484865Sobrien unsigned int sec_index; 12584865Sobrien 12684865Sobrien char * string_table; 12784865Sobrien char * string_ptr; 12884865Sobrien char * end_string_ptr; 12984865Sobrien 13084865Sobrien SYMENT * esym_table; 13184865Sobrien SYMENT * esym_ptr; 13284865Sobrien 13384865Sobrien struct internal_reloc * int_reltab; 13484865Sobrien} 13584865Sobrienpe_ILF_vars; 13684865Sobrien 13784865Sobrienstatic asection_ptr pe_ILF_make_a_section PARAMS ((pe_ILF_vars *, const char *, unsigned int, flagword)); 13884865Sobrienstatic void pe_ILF_make_a_reloc PARAMS ((pe_ILF_vars *, bfd_vma, bfd_reloc_code_real_type, asection_ptr)); 13984865Sobrienstatic void pe_ILF_make_a_symbol PARAMS ((pe_ILF_vars *, const char *, const char *, asection_ptr, flagword)); 14084865Sobrienstatic void pe_ILF_save_relocs PARAMS ((pe_ILF_vars *, asection_ptr)); 14184865Sobrienstatic void pe_ILF_make_a_symbol_reloc PARAMS ((pe_ILF_vars *, bfd_vma, bfd_reloc_code_real_type, struct symbol_cache_entry **, unsigned int)); 14294536Sobrienstatic boolean pe_ILF_build_a_bfd PARAMS ((bfd *, unsigned int, bfd_byte *, bfd_byte *, unsigned int, unsigned int)); 14384865Sobrienstatic const bfd_target * pe_ILF_object_p PARAMS ((bfd *)); 14484865Sobrienstatic const bfd_target * pe_bfd_object_p PARAMS ((bfd *)); 14584865Sobrien#endif /* COFF_IMAGE_WITH_PE */ 14684865Sobrien 14784865Sobrien/**********************************************************************/ 14884865Sobrien 14984865Sobrien#ifndef NO_COFF_RELOCS 15084865Sobrienstatic void 15184865Sobriencoff_swap_reloc_in (abfd, src, dst) 15284865Sobrien bfd *abfd; 15384865Sobrien PTR src; 15484865Sobrien PTR dst; 15584865Sobrien{ 15684865Sobrien RELOC *reloc_src = (RELOC *) src; 15784865Sobrien struct internal_reloc *reloc_dst = (struct internal_reloc *) dst; 15884865Sobrien 15994536Sobrien reloc_dst->r_vaddr = H_GET_32 (abfd, reloc_src->r_vaddr); 16094536Sobrien reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx); 16184865Sobrien 16294536Sobrien reloc_dst->r_type = H_GET_16 (abfd, reloc_src->r_type); 16384865Sobrien 16484865Sobrien#ifdef SWAP_IN_RELOC_OFFSET 16594536Sobrien reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET (abfd, reloc_src->r_offset); 16684865Sobrien#endif 16784865Sobrien} 16884865Sobrien 16984865Sobrienstatic unsigned int 17084865Sobriencoff_swap_reloc_out (abfd, src, dst) 17184865Sobrien bfd *abfd; 17284865Sobrien PTR src; 17384865Sobrien PTR dst; 17484865Sobrien{ 17584865Sobrien struct internal_reloc *reloc_src = (struct internal_reloc *)src; 17684865Sobrien struct external_reloc *reloc_dst = (struct external_reloc *)dst; 17794536Sobrien H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr); 17894536Sobrien H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx); 17984865Sobrien 18094536Sobrien H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type); 18184865Sobrien 18284865Sobrien#ifdef SWAP_OUT_RELOC_OFFSET 18394536Sobrien SWAP_OUT_RELOC_OFFSET (abfd, reloc_src->r_offset, reloc_dst->r_offset); 18484865Sobrien#endif 18584865Sobrien#ifdef SWAP_OUT_RELOC_EXTRA 18694536Sobrien SWAP_OUT_RELOC_EXTRA(abfd, reloc_src, reloc_dst); 18784865Sobrien#endif 18884865Sobrien return RELSZ; 18984865Sobrien} 19084865Sobrien#endif /* not NO_COFF_RELOCS */ 19184865Sobrien 19284865Sobrienstatic void 19384865Sobriencoff_swap_filehdr_in (abfd, src, dst) 19484865Sobrien bfd *abfd; 19584865Sobrien PTR src; 19684865Sobrien PTR dst; 19784865Sobrien{ 19884865Sobrien FILHDR *filehdr_src = (FILHDR *) src; 19984865Sobrien struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst; 20094536Sobrien filehdr_dst->f_magic = H_GET_16 (abfd, filehdr_src->f_magic); 20194536Sobrien filehdr_dst->f_nscns = H_GET_16 (abfd, filehdr_src-> f_nscns); 20294536Sobrien filehdr_dst->f_timdat = H_GET_32 (abfd, filehdr_src-> f_timdat); 20384865Sobrien 20494536Sobrien filehdr_dst->f_nsyms = H_GET_32 (abfd, filehdr_src-> f_nsyms); 20594536Sobrien filehdr_dst->f_flags = H_GET_16 (abfd, filehdr_src-> f_flags); 20694536Sobrien filehdr_dst->f_symptr = H_GET_32 (abfd, filehdr_src->f_symptr); 20784865Sobrien 20884865Sobrien /* Other people's tools sometimes generate headers with an nsyms but 20984865Sobrien a zero symptr. */ 21084865Sobrien if (filehdr_dst->f_nsyms != 0 && filehdr_dst->f_symptr == 0) 21184865Sobrien { 21284865Sobrien filehdr_dst->f_nsyms = 0; 21384865Sobrien filehdr_dst->f_flags |= F_LSYMS; 21484865Sobrien } 21584865Sobrien 21694536Sobrien filehdr_dst->f_opthdr = H_GET_16 (abfd, filehdr_src-> f_opthdr); 21784865Sobrien} 21884865Sobrien 21984865Sobrien#ifdef COFF_IMAGE_WITH_PE 22084865Sobrien# define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out 22184865Sobrien#else 22284865Sobrien# define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out 22384865Sobrien#endif 22484865Sobrien 22584865Sobrienstatic void 22684865Sobriencoff_swap_scnhdr_in (abfd, ext, in) 22784865Sobrien bfd *abfd; 22884865Sobrien PTR ext; 22984865Sobrien PTR in; 23084865Sobrien{ 23184865Sobrien SCNHDR *scnhdr_ext = (SCNHDR *) ext; 23284865Sobrien struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in; 23384865Sobrien 23484865Sobrien memcpy(scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name)); 23594536Sobrien scnhdr_int->s_vaddr = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr); 23694536Sobrien scnhdr_int->s_paddr = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr); 23794536Sobrien scnhdr_int->s_size = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size); 23894536Sobrien scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr); 23994536Sobrien scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr); 24094536Sobrien scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr); 24194536Sobrien scnhdr_int->s_flags = H_GET_32 (abfd, scnhdr_ext->s_flags); 24284865Sobrien 24384865Sobrien /* MS handles overflow of line numbers by carrying into the reloc 24484865Sobrien field (it appears). Since it's supposed to be zero for PE 24584865Sobrien *IMAGE* format, that's safe. This is still a bit iffy. */ 24684865Sobrien#ifdef COFF_IMAGE_WITH_PE 24794536Sobrien scnhdr_int->s_nlnno = (H_GET_16 (abfd, scnhdr_ext->s_nlnno) 24894536Sobrien + (H_GET_16 (abfd, scnhdr_ext->s_nreloc) << 16)); 24984865Sobrien scnhdr_int->s_nreloc = 0; 25084865Sobrien#else 25194536Sobrien scnhdr_int->s_nreloc = H_GET_16 (abfd, scnhdr_ext->s_nreloc); 25294536Sobrien scnhdr_int->s_nlnno = H_GET_16 (abfd, scnhdr_ext->s_nlnno); 25384865Sobrien#endif 25484865Sobrien 25584865Sobrien if (scnhdr_int->s_vaddr != 0) 25684865Sobrien { 25784865Sobrien scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase; 25884865Sobrien scnhdr_int->s_vaddr &= 0xffffffff; 25984865Sobrien } 26084865Sobrien 26184865Sobrien#ifndef COFF_NO_HACK_SCNHDR_SIZE 26284865Sobrien /* If this section holds uninitialized data, use the virtual size 26384865Sobrien (stored in s_paddr) instead of the physical size. */ 26484865Sobrien if ((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0 26584865Sobrien && (scnhdr_int->s_paddr > 0)) 26684865Sobrien { 26784865Sobrien scnhdr_int->s_size = scnhdr_int->s_paddr; 26884865Sobrien /* This code used to set scnhdr_int->s_paddr to 0. However, 26984865Sobrien coff_set_alignment_hook stores s_paddr in virt_size, which 27084865Sobrien only works if it correctly holds the virtual size of the 27184865Sobrien section. */ 27284865Sobrien } 27384865Sobrien#endif 27484865Sobrien} 27584865Sobrien 27684865Sobrienstatic boolean 27784865Sobrienpe_mkobject (abfd) 27884865Sobrien bfd * abfd; 27984865Sobrien{ 28084865Sobrien pe_data_type *pe; 28194536Sobrien bfd_size_type amt = sizeof (pe_data_type); 28284865Sobrien 28394536Sobrien abfd->tdata.pe_obj_data = (struct pe_tdata *) bfd_zalloc (abfd, amt); 28494536Sobrien 28584865Sobrien if (abfd->tdata.pe_obj_data == 0) 28684865Sobrien return false; 28784865Sobrien 28884865Sobrien pe = pe_data (abfd); 28984865Sobrien 29084865Sobrien pe->coff.pe = 1; 29184865Sobrien 29284865Sobrien /* in_reloc_p is architecture dependent. */ 29384865Sobrien pe->in_reloc_p = in_reloc_p; 29484865Sobrien 29584865Sobrien#ifdef PEI_FORCE_MINIMUM_ALIGNMENT 29684865Sobrien pe->force_minimum_alignment = 1; 29784865Sobrien#endif 29884865Sobrien#ifdef PEI_TARGET_SUBSYSTEM 29984865Sobrien pe->target_subsystem = PEI_TARGET_SUBSYSTEM; 30084865Sobrien#endif 30184865Sobrien 30284865Sobrien return true; 30384865Sobrien} 30484865Sobrien 30584865Sobrien/* Create the COFF backend specific information. */ 30684865Sobrienstatic PTR 30784865Sobrienpe_mkobject_hook (abfd, filehdr, aouthdr) 30884865Sobrien bfd * abfd; 30984865Sobrien PTR filehdr; 31084865Sobrien PTR aouthdr ATTRIBUTE_UNUSED; 31184865Sobrien{ 31284865Sobrien struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; 31384865Sobrien pe_data_type *pe; 31484865Sobrien 31584865Sobrien if (pe_mkobject (abfd) == false) 31684865Sobrien return NULL; 31784865Sobrien 31884865Sobrien pe = pe_data (abfd); 31984865Sobrien pe->coff.sym_filepos = internal_f->f_symptr; 32084865Sobrien /* These members communicate important constants about the symbol 32184865Sobrien table to GDB's symbol-reading code. These `constants' 32284865Sobrien unfortunately vary among coff implementations... */ 32384865Sobrien pe->coff.local_n_btmask = N_BTMASK; 32484865Sobrien pe->coff.local_n_btshft = N_BTSHFT; 32584865Sobrien pe->coff.local_n_tmask = N_TMASK; 32684865Sobrien pe->coff.local_n_tshift = N_TSHIFT; 32784865Sobrien pe->coff.local_symesz = SYMESZ; 32884865Sobrien pe->coff.local_auxesz = AUXESZ; 32984865Sobrien pe->coff.local_linesz = LINESZ; 33084865Sobrien 33184865Sobrien pe->coff.timestamp = internal_f->f_timdat; 33284865Sobrien 33384865Sobrien obj_raw_syment_count (abfd) = 33484865Sobrien obj_conv_table_size (abfd) = 33584865Sobrien internal_f->f_nsyms; 33684865Sobrien 33784865Sobrien pe->real_flags = internal_f->f_flags; 33884865Sobrien 33984865Sobrien if ((internal_f->f_flags & F_DLL) != 0) 34084865Sobrien pe->dll = 1; 34184865Sobrien 34284865Sobrien if ((internal_f->f_flags & IMAGE_FILE_DEBUG_STRIPPED) == 0) 34384865Sobrien abfd->flags |= HAS_DEBUG; 34484865Sobrien 34584865Sobrien#ifdef COFF_IMAGE_WITH_PE 34684865Sobrien if (aouthdr) 34784865Sobrien pe->pe_opthdr = ((struct internal_aouthdr *)aouthdr)->pe; 34884865Sobrien#endif 34984865Sobrien 35084865Sobrien#ifdef ARM 35184865Sobrien if (! _bfd_coff_arm_set_private_flags (abfd, internal_f->f_flags)) 35284865Sobrien coff_data (abfd) ->flags = 0; 35384865Sobrien#endif 35484865Sobrien 35584865Sobrien return (PTR) pe; 35684865Sobrien} 35784865Sobrien 35884865Sobrienstatic boolean 35984865Sobrienpe_print_private_bfd_data (abfd, vfile) 36084865Sobrien bfd *abfd; 36184865Sobrien PTR vfile; 36284865Sobrien{ 36384865Sobrien FILE *file = (FILE *) vfile; 36484865Sobrien 36584865Sobrien if (!_bfd_XX_print_private_bfd_data_common (abfd, vfile)) 36684865Sobrien return false; 36784865Sobrien 36884865Sobrien if (pe_saved_coff_bfd_print_private_bfd_data != NULL) 36984865Sobrien { 37084865Sobrien fputc ('\n', file); 37184865Sobrien 37284865Sobrien return pe_saved_coff_bfd_print_private_bfd_data (abfd, vfile); 37384865Sobrien } 37484865Sobrien 37584865Sobrien return true; 37684865Sobrien} 37784865Sobrien 37884865Sobrien/* Copy any private info we understand from the input bfd 37984865Sobrien to the output bfd. */ 38084865Sobrien 38184865Sobrienstatic boolean 38284865Sobrienpe_bfd_copy_private_bfd_data (ibfd, obfd) 38384865Sobrien bfd *ibfd, *obfd; 38484865Sobrien{ 38584865Sobrien if (!_bfd_XX_bfd_copy_private_bfd_data_common (ibfd, obfd)) 38684865Sobrien return false; 38784865Sobrien 38884865Sobrien if (pe_saved_coff_bfd_copy_private_bfd_data) 38984865Sobrien return pe_saved_coff_bfd_copy_private_bfd_data (ibfd, obfd); 39084865Sobrien 39184865Sobrien return true; 39284865Sobrien} 39384865Sobrien 39484865Sobrien#define coff_bfd_copy_private_section_data \ 39584865Sobrien _bfd_XX_bfd_copy_private_section_data 39684865Sobrien 39784865Sobrien#define coff_get_symbol_info _bfd_XX_get_symbol_info 39884865Sobrien 39984865Sobrien#ifdef COFF_IMAGE_WITH_PE 40084865Sobrien 40184865Sobrien/* Code to handle Microsoft's Image Library Format. 40284865Sobrien Also known as LINK6 format. 40384865Sobrien Documentation about this format can be found at: 40484865Sobrien 40584865Sobrien http://msdn.microsoft.com/library/specs/pecoff_section8.htm */ 40684865Sobrien 40784865Sobrien/* The following constants specify the sizes of the various data 40884865Sobrien structures that we have to create in order to build a bfd describing 40984865Sobrien an ILF object file. The final "+ 1" in the definitions of SIZEOF_IDATA6 41084865Sobrien and SIZEOF_IDATA7 below is to allow for the possibility that we might 41184865Sobrien need a padding byte in order to ensure 16 bit alignment for the section's 41284865Sobrien contents. 41384865Sobrien 41484865Sobrien The value for SIZEOF_ILF_STRINGS is computed as follows: 41584865Sobrien 41684865Sobrien There will be NUM_ILF_SECTIONS section symbols. Allow 9 characters 41784865Sobrien per symbol for their names (longest section name is .idata$x). 41884865Sobrien 41984865Sobrien There will be two symbols for the imported value, one the symbol name 42084865Sobrien and one with _imp__ prefixed. Allowing for the terminating nul's this 42184865Sobrien is strlen (symbol_name) * 2 + 8 + 21 + strlen (source_dll). 42284865Sobrien 42384865Sobrien The strings in the string table must start STRING__SIZE_SIZE bytes into 42484865Sobrien the table in order to for the string lookup code in coffgen/coffcode to 42584865Sobrien work. */ 42684865Sobrien#define NUM_ILF_RELOCS 8 42784865Sobrien#define NUM_ILF_SECTIONS 6 42884865Sobrien#define NUM_ILF_SYMS (2 + NUM_ILF_SECTIONS) 42984865Sobrien 43084865Sobrien#define SIZEOF_ILF_SYMS (NUM_ILF_SYMS * sizeof (* vars.sym_cache)) 43184865Sobrien#define SIZEOF_ILF_SYM_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_table)) 43284865Sobrien#define SIZEOF_ILF_NATIVE_SYMS (NUM_ILF_SYMS * sizeof (* vars.native_syms)) 43384865Sobrien#define SIZEOF_ILF_SYM_PTR_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_ptr_table)) 43484865Sobrien#define SIZEOF_ILF_EXT_SYMS (NUM_ILF_SYMS * sizeof (* vars.esym_table)) 43584865Sobrien#define SIZEOF_ILF_RELOCS (NUM_ILF_RELOCS * sizeof (* vars.reltab)) 43684865Sobrien#define SIZEOF_ILF_INT_RELOCS (NUM_ILF_RELOCS * sizeof (* vars.int_reltab)) 43784865Sobrien#define SIZEOF_ILF_STRINGS (strlen (symbol_name) * 2 + 8 \ 43884865Sobrien + 21 + strlen (source_dll) \ 43984865Sobrien + NUM_ILF_SECTIONS * 9 \ 44084865Sobrien + STRING_SIZE_SIZE) 44184865Sobrien#define SIZEOF_IDATA2 (5 * 4) 44284865Sobrien#define SIZEOF_IDATA4 (1 * 4) 44384865Sobrien#define SIZEOF_IDATA5 (1 * 4) 44484865Sobrien#define SIZEOF_IDATA6 (2 + strlen (symbol_name) + 1 + 1) 44584865Sobrien#define SIZEOF_IDATA7 (strlen (source_dll) + 1 + 1) 44684865Sobrien#define SIZEOF_ILF_SECTIONS (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata)) 44784865Sobrien 44884865Sobrien#define ILF_DATA_SIZE \ 44984865Sobrien sizeof (* vars.bim) \ 45084865Sobrien + SIZEOF_ILF_SYMS \ 45184865Sobrien + SIZEOF_ILF_SYM_TABLE \ 45284865Sobrien + SIZEOF_ILF_NATIVE_SYMS \ 45384865Sobrien + SIZEOF_ILF_SYM_PTR_TABLE \ 45484865Sobrien + SIZEOF_ILF_EXT_SYMS \ 45584865Sobrien + SIZEOF_ILF_RELOCS \ 45684865Sobrien + SIZEOF_ILF_INT_RELOCS \ 45784865Sobrien + SIZEOF_ILF_STRINGS \ 45884865Sobrien + SIZEOF_IDATA2 \ 45984865Sobrien + SIZEOF_IDATA4 \ 46084865Sobrien + SIZEOF_IDATA5 \ 46184865Sobrien + SIZEOF_IDATA6 \ 46284865Sobrien + SIZEOF_IDATA7 \ 46384865Sobrien + SIZEOF_ILF_SECTIONS \ 46484865Sobrien + MAX_TEXT_SECTION_SIZE 46584865Sobrien 46684865Sobrien/* Create an empty relocation against the given symbol. */ 46784865Sobrienstatic void 46884865Sobrienpe_ILF_make_a_symbol_reloc (pe_ILF_vars * vars, 46984865Sobrien bfd_vma address, 47084865Sobrien bfd_reloc_code_real_type reloc, 47184865Sobrien struct symbol_cache_entry ** sym, 47284865Sobrien unsigned int sym_index) 47384865Sobrien{ 47484865Sobrien arelent * entry; 47584865Sobrien struct internal_reloc * internal; 47684865Sobrien 47784865Sobrien entry = vars->reltab + vars->relcount; 47884865Sobrien internal = vars->int_reltab + vars->relcount; 47984865Sobrien 48084865Sobrien entry->address = address; 48184865Sobrien entry->addend = 0; 48284865Sobrien entry->howto = bfd_reloc_type_lookup (vars->abfd, reloc); 48384865Sobrien entry->sym_ptr_ptr = sym; 48484865Sobrien 48584865Sobrien internal->r_vaddr = address; 48684865Sobrien internal->r_symndx = sym_index; 48784865Sobrien internal->r_type = entry->howto->type; 48884865Sobrien#if 0 /* These fields do not need to be initialised. */ 48984865Sobrien internal->r_size = 0; 49084865Sobrien internal->r_extern = 0; 49184865Sobrien internal->r_offset = 0; 49284865Sobrien#endif 49384865Sobrien 49484865Sobrien vars->relcount ++; 49584865Sobrien 49684865Sobrien BFD_ASSERT (vars->relcount <= NUM_ILF_RELOCS); 49784865Sobrien} 49884865Sobrien 49984865Sobrien/* Create an empty relocation against the given section. */ 50084865Sobrienstatic void 50184865Sobrienpe_ILF_make_a_reloc (pe_ILF_vars * vars, 50284865Sobrien bfd_vma address, 50384865Sobrien bfd_reloc_code_real_type reloc, 50484865Sobrien asection_ptr sec) 50584865Sobrien{ 50684865Sobrien pe_ILF_make_a_symbol_reloc (vars, address, reloc, sec->symbol_ptr_ptr, 50784865Sobrien coff_section_data (vars->abfd, sec)->i); 50884865Sobrien} 50984865Sobrien 51084865Sobrien/* Move the queued relocs into the given section. */ 51184865Sobrienstatic void 51284865Sobrienpe_ILF_save_relocs (pe_ILF_vars * vars, 51384865Sobrien asection_ptr sec) 51484865Sobrien{ 51584865Sobrien /* Make sure that there is somewhere to store the internal relocs. */ 51684865Sobrien if (coff_section_data (vars->abfd, sec) == NULL) 51784865Sobrien /* We should probably return an error indication here. */ 51884865Sobrien abort (); 51984865Sobrien 52084865Sobrien coff_section_data (vars->abfd, sec)->relocs = vars->int_reltab; 52184865Sobrien coff_section_data (vars->abfd, sec)->keep_relocs = true; 52284865Sobrien 52384865Sobrien sec->relocation = vars->reltab; 52484865Sobrien sec->reloc_count = vars->relcount; 52584865Sobrien sec->flags |= SEC_RELOC; 52684865Sobrien 52784865Sobrien vars->reltab += vars->relcount; 52884865Sobrien vars->int_reltab += vars->relcount; 52984865Sobrien vars->relcount = 0; 53084865Sobrien 53194536Sobrien BFD_ASSERT ((bfd_byte *) vars->int_reltab < (bfd_byte *) vars->string_table); 53284865Sobrien} 53384865Sobrien 53484865Sobrien/* Create a global symbol and add it to the relevant tables. */ 53584865Sobrienstatic void 53684865Sobrienpe_ILF_make_a_symbol (pe_ILF_vars * vars, 53784865Sobrien const char * prefix, 53884865Sobrien const char * symbol_name, 53984865Sobrien asection_ptr section, 54084865Sobrien flagword extra_flags) 54184865Sobrien{ 54284865Sobrien coff_symbol_type * sym; 54384865Sobrien combined_entry_type * ent; 54484865Sobrien SYMENT * esym; 54584865Sobrien unsigned short sclass; 54684865Sobrien 54784865Sobrien if (extra_flags & BSF_LOCAL) 54884865Sobrien sclass = C_STAT; 54984865Sobrien else 55084865Sobrien sclass = C_EXT; 55184865Sobrien 55284865Sobrien#ifdef THUMBPEMAGIC 55384865Sobrien if (vars->magic == THUMBPEMAGIC) 55484865Sobrien { 55584865Sobrien if (extra_flags & BSF_FUNCTION) 55684865Sobrien sclass = C_THUMBEXTFUNC; 55784865Sobrien else if (extra_flags & BSF_LOCAL) 55884865Sobrien sclass = C_THUMBSTAT; 55984865Sobrien else 56084865Sobrien sclass = C_THUMBEXT; 56184865Sobrien } 56284865Sobrien#endif 56384865Sobrien 56484865Sobrien BFD_ASSERT (vars->sym_index < NUM_ILF_SYMS); 56584865Sobrien 56684865Sobrien sym = vars->sym_ptr; 56784865Sobrien ent = vars->native_ptr; 56884865Sobrien esym = vars->esym_ptr; 56984865Sobrien 57084865Sobrien /* Copy the symbol's name into the string table. */ 57184865Sobrien sprintf (vars->string_ptr, "%s%s", prefix, symbol_name); 57284865Sobrien 57384865Sobrien if (section == NULL) 57484865Sobrien section = (asection_ptr) & bfd_und_section; 57584865Sobrien 57684865Sobrien /* Initialise the external symbol. */ 57794536Sobrien H_PUT_32 (vars->abfd, vars->string_ptr - vars->string_table, 57894536Sobrien esym->e.e.e_offset); 57994536Sobrien H_PUT_16 (vars->abfd, section->target_index, esym->e_scnum); 58084865Sobrien esym->e_sclass[0] = sclass; 58184865Sobrien 58284865Sobrien /* The following initialisations are unnecessary - the memory is 58384865Sobrien zero initialised. They are just kept here as reminders. */ 58484865Sobrien#if 0 58584865Sobrien esym->e.e.e_zeroes = 0; 58684865Sobrien esym->e_value = 0; 58784865Sobrien esym->e_type = T_NULL; 58884865Sobrien esym->e_numaux = 0; 58984865Sobrien#endif 59084865Sobrien 59184865Sobrien /* Initialise the internal symbol structure. */ 59284865Sobrien ent->u.syment.n_sclass = sclass; 59384865Sobrien ent->u.syment.n_scnum = section->target_index; 59484865Sobrien ent->u.syment._n._n_n._n_offset = (long) sym; 59584865Sobrien 59684865Sobrien#if 0 /* See comment above. */ 59784865Sobrien ent->u.syment.n_value = 0; 59884865Sobrien ent->u.syment.n_flags = 0; 59984865Sobrien ent->u.syment.n_type = T_NULL; 60084865Sobrien ent->u.syment.n_numaux = 0; 60184865Sobrien ent->fix_value = 0; 60284865Sobrien#endif 60384865Sobrien 60484865Sobrien sym->symbol.the_bfd = vars->abfd; 60584865Sobrien sym->symbol.name = vars->string_ptr; 60684865Sobrien sym->symbol.flags = BSF_EXPORT | BSF_GLOBAL | extra_flags; 60784865Sobrien sym->symbol.section = section; 60884865Sobrien sym->native = ent; 60984865Sobrien 61084865Sobrien#if 0 /* See comment above. */ 61184865Sobrien sym->symbol.value = 0; 61284865Sobrien sym->symbol.udata.i = 0; 61384865Sobrien sym->done_lineno = false; 61484865Sobrien sym->lineno = NULL; 61584865Sobrien#endif 61684865Sobrien 61784865Sobrien * vars->table_ptr = vars->sym_index; 61884865Sobrien * vars->sym_ptr_ptr = sym; 61984865Sobrien 62084865Sobrien /* Adjust pointers for the next symbol. */ 62184865Sobrien vars->sym_index ++; 62284865Sobrien vars->sym_ptr ++; 62384865Sobrien vars->sym_ptr_ptr ++; 62484865Sobrien vars->table_ptr ++; 62584865Sobrien vars->native_ptr ++; 62684865Sobrien vars->esym_ptr ++; 62784865Sobrien vars->string_ptr += strlen (symbol_name) + strlen (prefix) + 1; 62884865Sobrien 62984865Sobrien BFD_ASSERT (vars->string_ptr < vars->end_string_ptr); 63084865Sobrien} 63184865Sobrien 63284865Sobrien/* Create a section. */ 63384865Sobrienstatic asection_ptr 63484865Sobrienpe_ILF_make_a_section (pe_ILF_vars * vars, 63584865Sobrien const char * name, 63684865Sobrien unsigned int size, 63784865Sobrien flagword extra_flags) 63884865Sobrien{ 63984865Sobrien asection_ptr sec; 64084865Sobrien flagword flags; 64184865Sobrien 64284865Sobrien sec = bfd_make_section_old_way (vars->abfd, name); 64384865Sobrien if (sec == NULL) 64484865Sobrien return NULL; 64584865Sobrien 64684865Sobrien flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_IN_MEMORY; 64784865Sobrien 64884865Sobrien bfd_set_section_flags (vars->abfd, sec, flags | extra_flags); 64984865Sobrien 65084865Sobrien bfd_set_section_alignment (vars->abfd, sec, 2); 65184865Sobrien 65284865Sobrien /* Check that we will not run out of space. */ 65384865Sobrien BFD_ASSERT (vars->data + size < vars->bim->buffer + vars->bim->size); 65484865Sobrien 65584865Sobrien /* Set the section size and contents. The actual 65684865Sobrien contents are filled in by our parent. */ 65794536Sobrien bfd_set_section_size (vars->abfd, sec, (bfd_size_type) size); 65884865Sobrien sec->contents = vars->data; 65984865Sobrien sec->target_index = vars->sec_index ++; 66084865Sobrien 66184865Sobrien /* Advance data pointer in the vars structure. */ 66284865Sobrien vars->data += size; 66384865Sobrien 66484865Sobrien /* Skip the padding byte if it was not needed. 66584865Sobrien The logic here is that if the string length is odd, 66684865Sobrien then the entire string length, including the null byte, 66784865Sobrien is even and so the extra, padding byte, is not needed. */ 66884865Sobrien if (size & 1) 66984865Sobrien vars->data --; 67084865Sobrien 67184865Sobrien /* Create a coff_section_tdata structure for our use. */ 67284865Sobrien sec->used_by_bfd = (struct coff_section_tdata *) vars->data; 67384865Sobrien vars->data += sizeof (struct coff_section_tdata); 67484865Sobrien 67584865Sobrien BFD_ASSERT (vars->data <= vars->bim->buffer + vars->bim->size); 67684865Sobrien 67784865Sobrien /* Create a symbol to refer to this section. */ 67884865Sobrien pe_ILF_make_a_symbol (vars, "", name, sec, BSF_LOCAL); 67984865Sobrien 68084865Sobrien /* Cache the index to the symbol in the coff_section_data structure. */ 68184865Sobrien coff_section_data (vars->abfd, sec)->i = vars->sym_index - 1; 68284865Sobrien 68384865Sobrien return sec; 68484865Sobrien} 68584865Sobrien 68684865Sobrien/* This structure contains the code that goes into the .text section 68784865Sobrien in order to perform a jump into the DLL lookup table. The entries 68884865Sobrien in the table are index by the magic number used to represent the 68984865Sobrien machine type in the PE file. The contents of the data[] arrays in 69084865Sobrien these entries are stolen from the jtab[] arrays in ld/pe-dll.c. 69184865Sobrien The SIZE field says how many bytes in the DATA array are actually 69284865Sobrien used. The OFFSET field says where in the data array the address 69384865Sobrien of the .idata$5 section should be placed. */ 69484865Sobrien#define MAX_TEXT_SECTION_SIZE 32 69584865Sobrien 69684865Sobrientypedef struct 69784865Sobrien{ 69884865Sobrien unsigned short magic; 69984865Sobrien unsigned char data[MAX_TEXT_SECTION_SIZE]; 70084865Sobrien unsigned int size; 70184865Sobrien unsigned int offset; 70284865Sobrien} 70384865Sobrienjump_table; 70484865Sobrien 70584865Sobrienstatic jump_table jtab[] = 70684865Sobrien{ 70784865Sobrien#ifdef I386MAGIC 70884865Sobrien { I386MAGIC, 70984865Sobrien { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 }, 71084865Sobrien 8, 2 71184865Sobrien }, 71284865Sobrien#endif 71384865Sobrien 71484865Sobrien#ifdef MC68MAGIC 71584865Sobrien { MC68MAGIC, { /* XXX fill me in */ }, 0, 0 }, 71684865Sobrien#endif 71784865Sobrien#ifdef MIPS_ARCH_MAGIC_WINCE 71884865Sobrien { MIPS_ARCH_MAGIC_WINCE, 71984865Sobrien { 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d, 72084865Sobrien 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 }, 72184865Sobrien 16, 0 72284865Sobrien }, 72384865Sobrien#endif 72484865Sobrien 72584865Sobrien#ifdef SH_ARCH_MAGIC_WINCE 72684865Sobrien { SH_ARCH_MAGIC_WINCE, 72784865Sobrien { 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 72884865Sobrien 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 }, 72984865Sobrien 12, 8 73084865Sobrien }, 73184865Sobrien#endif 73284865Sobrien 73384865Sobrien#ifdef ARMPEMAGIC 73484865Sobrien { ARMPEMAGIC, 73584865Sobrien { 0x00, 0xc0, 0x9f, 0xe5, 0x00, 0xf0, 73684865Sobrien 0x9c, 0xe5, 0x00, 0x00, 0x00, 0x00}, 73784865Sobrien 12, 8 73884865Sobrien }, 73984865Sobrien#endif 74084865Sobrien 74184865Sobrien#ifdef THUMBPEMAGIC 74284865Sobrien { THUMBPEMAGIC, 74384865Sobrien { 0x40, 0xb4, 0x02, 0x4e, 0x36, 0x68, 0xb4, 0x46, 74484865Sobrien 0x40, 0xbc, 0x60, 0x47, 0x00, 0x00, 0x00, 0x00 }, 74584865Sobrien 16, 12 74684865Sobrien }, 74784865Sobrien#endif 74884865Sobrien { 0, { 0 }, 0, 0 } 74984865Sobrien}; 75084865Sobrien 75184865Sobrien#ifndef NUM_ENTRIES 75284865Sobrien#define NUM_ENTRIES(a) (sizeof (a) / sizeof (a)[0]) 75384865Sobrien#endif 75484865Sobrien 75584865Sobrien/* Build a full BFD from the information supplied in a ILF object. */ 75684865Sobrienstatic boolean 75784865Sobrienpe_ILF_build_a_bfd (bfd * abfd, 75894536Sobrien unsigned int magic, 75984865Sobrien bfd_byte * symbol_name, 76084865Sobrien bfd_byte * source_dll, 76184865Sobrien unsigned int ordinal, 76284865Sobrien unsigned int types) 76384865Sobrien{ 76484865Sobrien bfd_byte * ptr; 76584865Sobrien pe_ILF_vars vars; 76684865Sobrien struct internal_filehdr internal_f; 76784865Sobrien unsigned int import_type; 76884865Sobrien unsigned int import_name_type; 76984865Sobrien asection_ptr id4, id5, id6 = NULL, text = NULL; 77084865Sobrien coff_symbol_type ** imp_sym; 77184865Sobrien unsigned int imp_index; 77284865Sobrien 77384865Sobrien /* Decode and verify the types field of the ILF structure. */ 77484865Sobrien import_type = types & 0x3; 77584865Sobrien import_name_type = (types & 0x1c) >> 2; 77684865Sobrien 77784865Sobrien switch (import_type) 77884865Sobrien { 77984865Sobrien case IMPORT_CODE: 78084865Sobrien case IMPORT_DATA: 78184865Sobrien break; 78284865Sobrien 78384865Sobrien case IMPORT_CONST: 78484865Sobrien /* XXX code yet to be written. */ 78584865Sobrien _bfd_error_handler (_("%s: Unhandled import type; %x"), 78694536Sobrien bfd_archive_filename (abfd), import_type); 78784865Sobrien return false; 78884865Sobrien 78984865Sobrien default: 79084865Sobrien _bfd_error_handler (_("%s: Unrecognised import type; %x"), 79194536Sobrien bfd_archive_filename (abfd), import_type); 79284865Sobrien return false; 79384865Sobrien } 79484865Sobrien 79584865Sobrien switch (import_name_type) 79684865Sobrien { 79784865Sobrien case IMPORT_ORDINAL: 79884865Sobrien case IMPORT_NAME: 79984865Sobrien case IMPORT_NAME_NOPREFIX: 80084865Sobrien case IMPORT_NAME_UNDECORATE: 80184865Sobrien break; 80284865Sobrien 80384865Sobrien default: 80484865Sobrien _bfd_error_handler (_("%s: Unrecognised import name type; %x"), 80594536Sobrien bfd_archive_filename (abfd), import_name_type); 80684865Sobrien return false; 80784865Sobrien } 80884865Sobrien 80984865Sobrien /* Initialise local variables. 81084865Sobrien 81184865Sobrien Note these are kept in a structure rather than being 81284865Sobrien declared as statics since bfd frowns on global variables. 81384865Sobrien 81484865Sobrien We are going to construct the contents of the BFD in memory, 81584865Sobrien so allocate all the space that we will need right now. */ 81694536Sobrien ptr = bfd_zalloc (abfd, (bfd_size_type) ILF_DATA_SIZE); 81784865Sobrien if (ptr == NULL) 81884865Sobrien return false; 81984865Sobrien 82084865Sobrien /* Create a bfd_in_memory structure. */ 82184865Sobrien vars.bim = (struct bfd_in_memory *) ptr; 82284865Sobrien vars.bim->buffer = ptr; 82384865Sobrien vars.bim->size = ILF_DATA_SIZE; 82484865Sobrien ptr += sizeof (* vars.bim); 82584865Sobrien 82684865Sobrien /* Initialise the pointers to regions of the memory and the 82784865Sobrien other contents of the pe_ILF_vars structure as well. */ 82884865Sobrien vars.sym_cache = (coff_symbol_type *) ptr; 82984865Sobrien vars.sym_ptr = (coff_symbol_type *) ptr; 83084865Sobrien vars.sym_index = 0; 83184865Sobrien ptr += SIZEOF_ILF_SYMS; 83284865Sobrien 83384865Sobrien vars.sym_table = (unsigned int *) ptr; 83484865Sobrien vars.table_ptr = (unsigned int *) ptr; 83584865Sobrien ptr += SIZEOF_ILF_SYM_TABLE; 83684865Sobrien 83784865Sobrien vars.native_syms = (combined_entry_type *) ptr; 83884865Sobrien vars.native_ptr = (combined_entry_type *) ptr; 83984865Sobrien ptr += SIZEOF_ILF_NATIVE_SYMS; 84084865Sobrien 84184865Sobrien vars.sym_ptr_table = (coff_symbol_type **) ptr; 84284865Sobrien vars.sym_ptr_ptr = (coff_symbol_type **) ptr; 84384865Sobrien ptr += SIZEOF_ILF_SYM_PTR_TABLE; 84484865Sobrien 84584865Sobrien vars.esym_table = (SYMENT *) ptr; 84684865Sobrien vars.esym_ptr = (SYMENT *) ptr; 84784865Sobrien ptr += SIZEOF_ILF_EXT_SYMS; 84884865Sobrien 84984865Sobrien vars.reltab = (arelent *) ptr; 85084865Sobrien vars.relcount = 0; 85184865Sobrien ptr += SIZEOF_ILF_RELOCS; 85284865Sobrien 85384865Sobrien vars.int_reltab = (struct internal_reloc *) ptr; 85484865Sobrien ptr += SIZEOF_ILF_INT_RELOCS; 85584865Sobrien 85684865Sobrien vars.string_table = ptr; 85784865Sobrien vars.string_ptr = ptr + STRING_SIZE_SIZE; 85884865Sobrien ptr += SIZEOF_ILF_STRINGS; 85984865Sobrien vars.end_string_ptr = ptr; 86084865Sobrien 86184865Sobrien /* The remaining space in bim->buffer is used 86284865Sobrien by the pe_ILF_make_a_section() function. */ 86384865Sobrien vars.data = ptr; 86484865Sobrien vars.abfd = abfd; 86584865Sobrien vars.sec_index = 0; 86684865Sobrien vars.magic = magic; 86784865Sobrien 86884865Sobrien /* Create the initial .idata$<n> sections: 86984865Sobrien [.idata$2: Import Directory Table -- not needed] 87084865Sobrien .idata$4: Import Lookup Table 87184865Sobrien .idata$5: Import Address Table 87284865Sobrien 87384865Sobrien Note we do not create a .idata$3 section as this is 87484865Sobrien created for us by the linker script. */ 87584865Sobrien id4 = pe_ILF_make_a_section (& vars, ".idata$4", SIZEOF_IDATA4, 0); 87684865Sobrien id5 = pe_ILF_make_a_section (& vars, ".idata$5", SIZEOF_IDATA5, 0); 87784865Sobrien if (id4 == NULL || id5 == NULL) 87884865Sobrien return false; 87984865Sobrien 88084865Sobrien /* Fill in the contents of these sections. */ 88184865Sobrien if (import_name_type == IMPORT_ORDINAL) 88284865Sobrien { 88384865Sobrien if (ordinal == 0) 88484865Sobrien /* XXX - treat as IMPORT_NAME ??? */ 88584865Sobrien abort (); 88684865Sobrien 88784865Sobrien * (unsigned int *) id4->contents = ordinal | 0x80000000; 88884865Sobrien * (unsigned int *) id5->contents = ordinal | 0x80000000; 88984865Sobrien } 89084865Sobrien else 89184865Sobrien { 89284865Sobrien char * symbol; 89384865Sobrien 89484865Sobrien /* Create .idata$6 - the Hint Name Table. */ 89584865Sobrien id6 = pe_ILF_make_a_section (& vars, ".idata$6", SIZEOF_IDATA6, 0); 89684865Sobrien if (id6 == NULL) 89784865Sobrien return false; 89884865Sobrien 89984865Sobrien /* If necessary, trim the import symbol name. */ 90084865Sobrien symbol = symbol_name; 90184865Sobrien 90284865Sobrien if (import_name_type != IMPORT_NAME) 90384865Sobrien /* Skip any prefix in symbol_name. */ 90484865Sobrien while (*symbol == '@' || * symbol == '?' || * symbol == '_') 90584865Sobrien ++ symbol; 90684865Sobrien 90784865Sobrien if (import_name_type == IMPORT_NAME_UNDECORATE) 90884865Sobrien { 90984865Sobrien /* Truncate at the first '@' */ 91084865Sobrien while (* symbol != 0 && * symbol != '@') 91184865Sobrien symbol ++; 91284865Sobrien 91384865Sobrien * symbol = 0; 91484865Sobrien } 91584865Sobrien 91684865Sobrien id6->contents[0] = ordinal & 0xff; 91784865Sobrien id6->contents[1] = ordinal >> 8; 91884865Sobrien 91984865Sobrien strcpy (id6->contents + 2, symbol); 92084865Sobrien } 92184865Sobrien 92284865Sobrien if (import_name_type != IMPORT_ORDINAL) 92384865Sobrien { 92494536Sobrien pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_RVA, id6); 92594536Sobrien pe_ILF_save_relocs (&vars, id4); 92684865Sobrien 92794536Sobrien pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_RVA, id6); 92894536Sobrien pe_ILF_save_relocs (&vars, id5); 92984865Sobrien } 93084865Sobrien 93184865Sobrien /* Create extra sections depending upon the type of import we are dealing with. */ 93284865Sobrien switch (import_type) 93384865Sobrien { 93484865Sobrien int i; 93584865Sobrien 93684865Sobrien case IMPORT_CODE: 93784865Sobrien /* Create a .text section. 93884865Sobrien First we need to look up its contents in the jump table. */ 93984865Sobrien for (i = NUM_ENTRIES (jtab); i--;) 94084865Sobrien { 94184865Sobrien if (jtab[i].size == 0) 94284865Sobrien continue; 94384865Sobrien if (jtab[i].magic == magic) 94484865Sobrien break; 94584865Sobrien } 94684865Sobrien /* If we did not find a matching entry something is wrong. */ 94784865Sobrien if (i < 0) 94884865Sobrien abort (); 94984865Sobrien 95084865Sobrien /* Create the .text section. */ 95184865Sobrien text = pe_ILF_make_a_section (& vars, ".text", jtab[i].size, SEC_CODE); 95284865Sobrien if (text == NULL) 95384865Sobrien return false; 95484865Sobrien 95584865Sobrien /* Copy in the jump code. */ 95684865Sobrien memcpy (text->contents, jtab[i].data, jtab[i].size); 95784865Sobrien 95884865Sobrien /* Create an import symbol. */ 95984865Sobrien pe_ILF_make_a_symbol (& vars, "__imp_", symbol_name, id5, 0); 96084865Sobrien imp_sym = vars.sym_ptr_ptr - 1; 96184865Sobrien imp_index = vars.sym_index - 1; 96284865Sobrien 96384865Sobrien /* Create a reloc for the data in the text section. */ 96484865Sobrien#ifdef MIPS_ARCH_MAGIC_WINCE 96584865Sobrien if (magic == MIPS_ARCH_MAGIC_WINCE) 96684865Sobrien { 96794536Sobrien pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) 0, BFD_RELOC_HI16_S, 96894536Sobrien (struct symbol_cache_entry **) imp_sym, 96994536Sobrien imp_index); 97094536Sobrien pe_ILF_make_a_reloc (&vars, (bfd_vma) 0, BFD_RELOC_LO16, text); 97194536Sobrien pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) 4, BFD_RELOC_LO16, 97294536Sobrien (struct symbol_cache_entry **) imp_sym, 97394536Sobrien imp_index); 97484865Sobrien } 97584865Sobrien else 97684865Sobrien#endif 97794536Sobrien pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset, 97894536Sobrien BFD_RELOC_32, (asymbol **) imp_sym, 97994536Sobrien imp_index); 98084865Sobrien 98184865Sobrien pe_ILF_save_relocs (& vars, text); 98284865Sobrien break; 98384865Sobrien 98484865Sobrien case IMPORT_DATA: 98584865Sobrien break; 98684865Sobrien 98784865Sobrien default: 98884865Sobrien /* XXX code not yet written. */ 98984865Sobrien abort (); 99084865Sobrien } 99184865Sobrien 99284865Sobrien /* Initialise the bfd. */ 99384865Sobrien memset (& internal_f, 0, sizeof (internal_f)); 99484865Sobrien 99584865Sobrien internal_f.f_magic = magic; 99684865Sobrien internal_f.f_symptr = 0; 99784865Sobrien internal_f.f_nsyms = 0; 99884865Sobrien internal_f.f_flags = F_AR32WR | F_LNNO; /* XXX is this correct ? */ 99984865Sobrien 100094536Sobrien if ( ! bfd_set_start_address (abfd, (bfd_vma) 0) 100184865Sobrien || ! bfd_coff_set_arch_mach_hook (abfd, & internal_f)) 100284865Sobrien return false; 100384865Sobrien 100484865Sobrien if (bfd_coff_mkobject_hook (abfd, (PTR) & internal_f, NULL) == NULL) 100584865Sobrien return false; 100684865Sobrien 100784865Sobrien coff_data (abfd)->pe = 1; 100884865Sobrien#ifdef THUMBPEMAGIC 100984865Sobrien if (vars.magic == THUMBPEMAGIC) 101084865Sobrien /* Stop some linker warnings about thumb code not supporting interworking. */ 101184865Sobrien coff_data (abfd)->flags |= F_INTERWORK | F_INTERWORK_SET; 101284865Sobrien#endif 101384865Sobrien 101484865Sobrien /* Switch from file contents to memory contents. */ 101584865Sobrien bfd_cache_close (abfd); 101684865Sobrien 101784865Sobrien abfd->iostream = (PTR) vars.bim; 101884865Sobrien abfd->flags |= BFD_IN_MEMORY /* | HAS_LOCALS */; 101984865Sobrien abfd->where = 0; 102084865Sobrien obj_sym_filepos (abfd) = 0; 102184865Sobrien 102284865Sobrien /* Now create a symbol describing the imported value. */ 102384865Sobrien switch (import_type) 102484865Sobrien { 102584865Sobrien case IMPORT_CODE: 102684865Sobrien pe_ILF_make_a_symbol (& vars, "", symbol_name, text, 102784865Sobrien BSF_NOT_AT_END | BSF_FUNCTION); 102884865Sobrien 102984865Sobrien /* Create an import symbol for the DLL, without the 103084865Sobrien .dll suffix. */ 103184865Sobrien ptr = strrchr (source_dll, '.'); 103284865Sobrien if (ptr) 103384865Sobrien * ptr = 0; 103484865Sobrien pe_ILF_make_a_symbol (& vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0); 103584865Sobrien if (ptr) 103684865Sobrien * ptr = '.'; 103784865Sobrien break; 103884865Sobrien 103984865Sobrien case IMPORT_DATA: 104084865Sobrien /* Nothing to do here. */ 104184865Sobrien break; 104284865Sobrien 104384865Sobrien default: 104484865Sobrien /* XXX code not yet written. */ 104584865Sobrien abort (); 104684865Sobrien } 104784865Sobrien 104884865Sobrien /* Point the bfd at the symbol table. */ 104984865Sobrien obj_symbols (abfd) = vars.sym_cache; 105084865Sobrien bfd_get_symcount (abfd) = vars.sym_index; 105184865Sobrien 105284865Sobrien obj_raw_syments (abfd) = vars.native_syms; 105384865Sobrien obj_raw_syment_count (abfd) = vars.sym_index; 105484865Sobrien 105584865Sobrien obj_coff_external_syms (abfd) = (PTR) vars.esym_table; 105684865Sobrien obj_coff_keep_syms (abfd) = true; 105784865Sobrien 105884865Sobrien obj_convert (abfd) = vars.sym_table; 105984865Sobrien obj_conv_table_size (abfd) = vars.sym_index; 106084865Sobrien 106184865Sobrien obj_coff_strings (abfd) = vars.string_table; 106284865Sobrien obj_coff_keep_strings (abfd) = true; 106384865Sobrien 106484865Sobrien abfd->flags |= HAS_SYMS; 106584865Sobrien 106684865Sobrien return true; 106784865Sobrien} 106884865Sobrien 106984865Sobrien/* We have detected a Image Library Format archive element. 107084865Sobrien Decode the element and return the appropriate target. */ 107184865Sobrienstatic const bfd_target * 107284865Sobrienpe_ILF_object_p (bfd * abfd) 107384865Sobrien{ 107484865Sobrien bfd_byte buffer[16]; 107584865Sobrien bfd_byte * ptr; 107684865Sobrien bfd_byte * symbol_name; 107784865Sobrien bfd_byte * source_dll; 107884865Sobrien unsigned int machine; 107994536Sobrien bfd_size_type size; 108084865Sobrien unsigned int ordinal; 108184865Sobrien unsigned int types; 108294536Sobrien unsigned int magic; 108384865Sobrien 108484865Sobrien /* Upon entry the first four buyes of the ILF header have 108584865Sobrien already been read. Now read the rest of the header. */ 108694536Sobrien if (bfd_bread (buffer, (bfd_size_type) 16, abfd) != 16) 108784865Sobrien return NULL; 108884865Sobrien 108984865Sobrien ptr = buffer; 109084865Sobrien 109184865Sobrien /* We do not bother to check the version number. 109294536Sobrien version = H_GET_16 (abfd, ptr); */ 109384865Sobrien ptr += 2; 109484865Sobrien 109594536Sobrien machine = H_GET_16 (abfd, ptr); 109684865Sobrien ptr += 2; 109784865Sobrien 109884865Sobrien /* Check that the machine type is recognised. */ 109984865Sobrien magic = 0; 110084865Sobrien 110184865Sobrien switch (machine) 110284865Sobrien { 110384865Sobrien case IMAGE_FILE_MACHINE_UNKNOWN: 110484865Sobrien case IMAGE_FILE_MACHINE_ALPHA: 110584865Sobrien case IMAGE_FILE_MACHINE_ALPHA64: 110684865Sobrien case IMAGE_FILE_MACHINE_IA64: 110784865Sobrien break; 110884865Sobrien 110984865Sobrien case IMAGE_FILE_MACHINE_I386: 111084865Sobrien#ifdef I386MAGIC 111184865Sobrien magic = I386MAGIC; 111284865Sobrien#endif 111384865Sobrien break; 111484865Sobrien 111584865Sobrien case IMAGE_FILE_MACHINE_M68K: 111684865Sobrien#ifdef MC68AGIC 111784865Sobrien magic = MC68MAGIC; 111884865Sobrien#endif 111984865Sobrien break; 112084865Sobrien 112184865Sobrien case IMAGE_FILE_MACHINE_R3000: 112284865Sobrien case IMAGE_FILE_MACHINE_R4000: 112384865Sobrien case IMAGE_FILE_MACHINE_R10000: 112484865Sobrien 112584865Sobrien case IMAGE_FILE_MACHINE_MIPS16: 112684865Sobrien case IMAGE_FILE_MACHINE_MIPSFPU: 112784865Sobrien case IMAGE_FILE_MACHINE_MIPSFPU16: 112884865Sobrien#ifdef MIPS_ARCH_MAGIC_WINCE 112984865Sobrien magic = MIPS_ARCH_MAGIC_WINCE; 113084865Sobrien#endif 113184865Sobrien break; 113284865Sobrien 113384865Sobrien case IMAGE_FILE_MACHINE_SH3: 113484865Sobrien case IMAGE_FILE_MACHINE_SH4: 113584865Sobrien#ifdef SH_ARCH_MAGIC_WINCE 113684865Sobrien magic = SH_ARCH_MAGIC_WINCE; 113784865Sobrien#endif 113884865Sobrien break; 113984865Sobrien 114084865Sobrien case IMAGE_FILE_MACHINE_ARM: 114184865Sobrien#ifdef ARMPEMAGIC 114284865Sobrien magic = ARMPEMAGIC; 114384865Sobrien#endif 114484865Sobrien break; 114584865Sobrien 114684865Sobrien case IMAGE_FILE_MACHINE_THUMB: 114784865Sobrien#ifdef THUMBPEMAGIC 114884865Sobrien { 114984865Sobrien extern const bfd_target TARGET_LITTLE_SYM; 115084865Sobrien 115184865Sobrien if (abfd->xvec == & TARGET_LITTLE_SYM) 115284865Sobrien magic = THUMBPEMAGIC; 115384865Sobrien } 115484865Sobrien#endif 115584865Sobrien break; 115684865Sobrien 115784865Sobrien case IMAGE_FILE_MACHINE_POWERPC: 115884865Sobrien /* We no longer support PowerPC. */ 115984865Sobrien default: 116084865Sobrien _bfd_error_handler 116184865Sobrien ( 116284865Sobrien_("%s: Unrecognised machine type (0x%x) in Import Library Format archive"), 116394536Sobrien bfd_archive_filename (abfd), machine); 116484865Sobrien bfd_set_error (bfd_error_malformed_archive); 116584865Sobrien 116684865Sobrien return NULL; 116784865Sobrien break; 116884865Sobrien } 116984865Sobrien 117084865Sobrien if (magic == 0) 117184865Sobrien { 117284865Sobrien _bfd_error_handler 117384865Sobrien ( 117484865Sobrien_("%s: Recognised but unhandled machine type (0x%x) in Import Library Format archive"), 117594536Sobrien bfd_archive_filename (abfd), machine); 117684865Sobrien bfd_set_error (bfd_error_wrong_format); 117784865Sobrien 117884865Sobrien return NULL; 117984865Sobrien } 118084865Sobrien 118184865Sobrien /* We do not bother to check the date. 118294536Sobrien date = H_GET_32 (abfd, ptr); */ 118384865Sobrien ptr += 4; 118484865Sobrien 118594536Sobrien size = H_GET_32 (abfd, ptr); 118684865Sobrien ptr += 4; 118784865Sobrien 118884865Sobrien if (size == 0) 118984865Sobrien { 119084865Sobrien _bfd_error_handler 119184865Sobrien (_("%s: size field is zero in Import Library Format header"), 119294536Sobrien bfd_archive_filename (abfd)); 119384865Sobrien bfd_set_error (bfd_error_malformed_archive); 119484865Sobrien 119584865Sobrien return NULL; 119684865Sobrien } 119784865Sobrien 119894536Sobrien ordinal = H_GET_16 (abfd, ptr); 119984865Sobrien ptr += 2; 120084865Sobrien 120194536Sobrien types = H_GET_16 (abfd, ptr); 120284865Sobrien /* ptr += 2; */ 120384865Sobrien 120484865Sobrien /* Now read in the two strings that follow. */ 120584865Sobrien ptr = bfd_alloc (abfd, size); 120684865Sobrien if (ptr == NULL) 120784865Sobrien return NULL; 120884865Sobrien 120994536Sobrien if (bfd_bread (ptr, size, abfd) != size) 121084865Sobrien return NULL; 121184865Sobrien 121284865Sobrien symbol_name = ptr; 121384865Sobrien source_dll = ptr + strlen (ptr) + 1; 121484865Sobrien 121584865Sobrien /* Verify that the strings are null terminated. */ 121684865Sobrien if (ptr[size - 1] != 0 || ((unsigned long) (source_dll - ptr) >= size)) 121784865Sobrien { 121884865Sobrien _bfd_error_handler 121984865Sobrien (_("%s: string not null terminated in ILF object file."), 122094536Sobrien bfd_archive_filename (abfd)); 122184865Sobrien bfd_set_error (bfd_error_malformed_archive); 122284865Sobrien 122384865Sobrien return NULL; 122484865Sobrien } 122584865Sobrien 122684865Sobrien /* Now construct the bfd. */ 122784865Sobrien if (! pe_ILF_build_a_bfd (abfd, magic, symbol_name, 122884865Sobrien source_dll, ordinal, types)) 122984865Sobrien return NULL; 123084865Sobrien 123184865Sobrien return abfd->xvec; 123284865Sobrien} 123384865Sobrien 123484865Sobrienstatic const bfd_target * 123584865Sobrienpe_bfd_object_p (bfd * abfd) 123684865Sobrien{ 123784865Sobrien bfd_byte buffer[4]; 123884865Sobrien struct external_PEI_DOS_hdr dos_hdr; 123984865Sobrien struct external_PEI_IMAGE_hdr image_hdr; 124084865Sobrien file_ptr offset; 124184865Sobrien 124284865Sobrien /* Detect if this a Microsoft Import Library Format element. */ 124394536Sobrien if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 124494536Sobrien || bfd_bread (buffer, (bfd_size_type) 4, abfd) != 4) 124584865Sobrien { 124684865Sobrien if (bfd_get_error () != bfd_error_system_call) 124784865Sobrien bfd_set_error (bfd_error_wrong_format); 124884865Sobrien return NULL; 124984865Sobrien } 125084865Sobrien 125194536Sobrien if (H_GET_32 (abfd, buffer) == 0xffff0000) 125284865Sobrien return pe_ILF_object_p (abfd); 125384865Sobrien 125494536Sobrien if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 125594536Sobrien || bfd_bread (&dos_hdr, (bfd_size_type) sizeof (dos_hdr), abfd) 125684865Sobrien != sizeof (dos_hdr)) 125784865Sobrien { 125884865Sobrien if (bfd_get_error () != bfd_error_system_call) 125984865Sobrien bfd_set_error (bfd_error_wrong_format); 126084865Sobrien return NULL; 126184865Sobrien } 126284865Sobrien 126384865Sobrien /* There are really two magic numbers involved; the magic number 126484865Sobrien that says this is a NT executable (PEI) and the magic number that 126584865Sobrien determines the architecture. The former is DOSMAGIC, stored in 126684865Sobrien the e_magic field. The latter is stored in the f_magic field. 126784865Sobrien If the NT magic number isn't valid, the architecture magic number 126884865Sobrien could be mimicked by some other field (specifically, the number 126984865Sobrien of relocs in section 3). Since this routine can only be called 127084865Sobrien correctly for a PEI file, check the e_magic number here, and, if 127184865Sobrien it doesn't match, clobber the f_magic number so that we don't get 127284865Sobrien a false match. */ 127394536Sobrien if (H_GET_16 (abfd, dos_hdr.e_magic) != DOSMAGIC) 127484865Sobrien { 127584865Sobrien bfd_set_error (bfd_error_wrong_format); 127684865Sobrien return NULL; 127784865Sobrien } 127884865Sobrien 127994536Sobrien offset = H_GET_32 (abfd, dos_hdr.e_lfanew); 128094536Sobrien if (bfd_seek (abfd, offset, SEEK_SET) != 0 128194536Sobrien || (bfd_bread (&image_hdr, (bfd_size_type) sizeof (image_hdr), abfd) 128294536Sobrien != sizeof (image_hdr))) 128384865Sobrien { 128484865Sobrien if (bfd_get_error () != bfd_error_system_call) 128584865Sobrien bfd_set_error (bfd_error_wrong_format); 128684865Sobrien return NULL; 128784865Sobrien } 128884865Sobrien 128994536Sobrien if (H_GET_32 (abfd, image_hdr.nt_signature) != 0x4550) 129084865Sobrien { 129184865Sobrien bfd_set_error (bfd_error_wrong_format); 129284865Sobrien return NULL; 129384865Sobrien } 129484865Sobrien 129584865Sobrien /* Here is the hack. coff_object_p wants to read filhsz bytes to 129684865Sobrien pick up the COFF header for PE, see "struct external_PEI_filehdr" 129784865Sobrien in include/coff/pe.h. We adjust so that that will work. */ 129894536Sobrien if (bfd_seek (abfd, (file_ptr) (offset - sizeof (dos_hdr)), SEEK_SET) != 0) 129984865Sobrien { 130084865Sobrien if (bfd_get_error () != bfd_error_system_call) 130184865Sobrien bfd_set_error (bfd_error_wrong_format); 130284865Sobrien return NULL; 130384865Sobrien } 130484865Sobrien 130584865Sobrien return coff_object_p (abfd); 130684865Sobrien} 130784865Sobrien 130884865Sobrien#define coff_object_p pe_bfd_object_p 130984865Sobrien#endif /* COFF_IMAGE_WITH_PE */ 1310