178828Sobrien/* Support for the generic parts of PE/PEI; the common executable parts. 2218822Sdim Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 3218822Sdim 2005, 2006, 2007 Free Software Foundation, Inc. 478828Sobrien Written by Cygnus Solutions. 578828Sobrien 6104834Sobrien This file is part of BFD, the Binary File Descriptor library. 778828Sobrien 8104834Sobrien This program is free software; you can redistribute it and/or modify 9104834Sobrien it under the terms of the GNU General Public License as published by 10104834Sobrien the Free Software Foundation; either version 2 of the License, or 11104834Sobrien (at your option) any later version. 1278828Sobrien 13104834Sobrien This program is distributed in the hope that it will be useful, 14104834Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15104834Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16104834Sobrien GNU General Public License for more details. 1778828Sobrien 18104834Sobrien You should have received a copy of the GNU General Public License 19104834Sobrien along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2178828Sobrien 2278828Sobrien/* Most of this hacked by Steve Chamberlain <sac@cygnus.com>. 2378828Sobrien 2478828Sobrien PE/PEI rearrangement (and code added): Donn Terry 2591041Sobrien Softway Systems, Inc. */ 2678828Sobrien 2778828Sobrien/* Hey look, some documentation [and in a place you expect to find it]! 2878828Sobrien 2978828Sobrien The main reference for the pei format is "Microsoft Portable Executable 3078828Sobrien and Common Object File Format Specification 4.1". Get it if you need to 3178828Sobrien do some serious hacking on this code. 3278828Sobrien 3378828Sobrien Another reference: 3478828Sobrien "Peering Inside the PE: A Tour of the Win32 Portable Executable 3578828Sobrien File Format", MSJ 1994, Volume 9. 3678828Sobrien 3778828Sobrien The *sole* difference between the pe format and the pei format is that the 3878828Sobrien latter has an MSDOS 2.0 .exe header on the front that prints the message 3978828Sobrien "This app must be run under Windows." (or some such). 4078828Sobrien (FIXME: Whether that statement is *really* true or not is unknown. 4178828Sobrien Are there more subtle differences between pe and pei formats? 4278828Sobrien For now assume there aren't. If you find one, then for God sakes 4378828Sobrien document it here!) 4478828Sobrien 4578828Sobrien The Microsoft docs use the word "image" instead of "executable" because 4678828Sobrien the former can also refer to a DLL (shared library). Confusion can arise 4778828Sobrien because the `i' in `pei' also refers to "image". The `pe' format can 4878828Sobrien also create images (i.e. executables), it's just that to run on a win32 4978828Sobrien system you need to use the pei format. 5078828Sobrien 5178828Sobrien FIXME: Please add more docs here so the next poor fool that has to hack 5278828Sobrien on this code has a chance of getting something accomplished without 5391041Sobrien wasting too much time. */ 5478828Sobrien 55218822Sdim/* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64 56218822Sdim depending on whether we're compiling for straight PE or PE+. */ 5778828Sobrien#define COFF_WITH_XX 5878828Sobrien 59218822Sdim#include "sysdep.h" 6078828Sobrien#include "bfd.h" 6178828Sobrien#include "libbfd.h" 6278828Sobrien#include "coff/internal.h" 6378828Sobrien 6478828Sobrien/* NOTE: it's strange to be including an architecture specific header 6578828Sobrien in what's supposed to be general (to PE/PEI) code. However, that's 6678828Sobrien where the definitions are, and they don't vary per architecture 6778828Sobrien within PE/PEI, so we get them from there. FIXME: The lack of 6878828Sobrien variance is an assumption which may prove to be incorrect if new 6978828Sobrien PE/PEI targets are created. */ 70218822Sdim#if defined COFF_WITH_pex64 71218822Sdim# include "coff/x86_64.h" 72218822Sdim#elif defined COFF_WITH_pep 7378828Sobrien# include "coff/ia64.h" 7478828Sobrien#else 7578828Sobrien# include "coff/i386.h" 7678828Sobrien#endif 7778828Sobrien 7878828Sobrien#include "coff/pe.h" 7978828Sobrien#include "libcoff.h" 8078828Sobrien#include "libpei.h" 8178828Sobrien 82218822Sdim#if defined COFF_WITH_pep || defined COFF_WITH_pex64 8378828Sobrien# undef AOUTSZ 8478828Sobrien# define AOUTSZ PEPAOUTSZ 8578828Sobrien# define PEAOUTHDR PEPAOUTHDR 8678828Sobrien#endif 8778828Sobrien 8878828Sobrien/* FIXME: This file has various tests of POWERPC_LE_PE. Those tests 8978828Sobrien worked when the code was in peicode.h, but no longer work now that 9078828Sobrien the code is in peigen.c. PowerPC NT is said to be dead. If 9178828Sobrien anybody wants to revive the code, you will have to figure out how 9278828Sobrien to handle those issues. */ 9389857Sobrien 9478828Sobrienvoid 95218822Sdim_bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1) 9678828Sobrien{ 9778828Sobrien SYMENT *ext = (SYMENT *) ext1; 9878828Sobrien struct internal_syment *in = (struct internal_syment *) in1; 9978828Sobrien 10078828Sobrien if (ext->e.e_name[0] == 0) 10178828Sobrien { 10278828Sobrien in->_n._n_n._n_zeroes = 0; 10389857Sobrien in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e.e.e_offset); 10478828Sobrien } 10578828Sobrien else 10689857Sobrien memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN); 10778828Sobrien 10889857Sobrien in->n_value = H_GET_32 (abfd, ext->e_value); 10989857Sobrien in->n_scnum = H_GET_16 (abfd, ext->e_scnum); 11089857Sobrien 11178828Sobrien if (sizeof (ext->e_type) == 2) 11289857Sobrien in->n_type = H_GET_16 (abfd, ext->e_type); 11378828Sobrien else 11489857Sobrien in->n_type = H_GET_32 (abfd, ext->e_type); 11578828Sobrien 11689857Sobrien in->n_sclass = H_GET_8 (abfd, ext->e_sclass); 11789857Sobrien in->n_numaux = H_GET_8 (abfd, ext->e_numaux); 11889857Sobrien 11978828Sobrien#ifndef STRICT_PE_FORMAT 12078828Sobrien /* This is for Gnu-created DLLs. */ 12178828Sobrien 12278828Sobrien /* The section symbols for the .idata$ sections have class 0x68 12378828Sobrien (C_SECTION), which MS documentation indicates is a section 12478828Sobrien symbol. Unfortunately, the value field in the symbol is simply a 12578828Sobrien copy of the .idata section's flags rather than something useful. 12678828Sobrien When these symbols are encountered, change the value to 0 so that 12778828Sobrien they will be handled somewhat correctly in the bfd code. */ 12878828Sobrien if (in->n_sclass == C_SECTION) 12978828Sobrien { 13078828Sobrien in->n_value = 0x0; 13178828Sobrien 13278828Sobrien /* Create synthetic empty sections as needed. DJ */ 13378828Sobrien if (in->n_scnum == 0) 13478828Sobrien { 13578828Sobrien asection *sec; 13689857Sobrien 13778828Sobrien for (sec = abfd->sections; sec; sec = sec->next) 13878828Sobrien { 13978828Sobrien if (strcmp (sec->name, in->n_name) == 0) 14078828Sobrien { 14178828Sobrien in->n_scnum = sec->target_index; 14278828Sobrien break; 14378828Sobrien } 14478828Sobrien } 14578828Sobrien } 14689857Sobrien 14778828Sobrien if (in->n_scnum == 0) 14878828Sobrien { 14978828Sobrien int unused_section_number = 0; 15078828Sobrien asection *sec; 15178828Sobrien char *name; 152218822Sdim flagword flags; 15389857Sobrien 15478828Sobrien for (sec = abfd->sections; sec; sec = sec->next) 15578828Sobrien if (unused_section_number <= sec->target_index) 15678828Sobrien unused_section_number = sec->target_index + 1; 15778828Sobrien 15889857Sobrien name = bfd_alloc (abfd, (bfd_size_type) strlen (in->n_name) + 10); 15978828Sobrien if (name == NULL) 16078828Sobrien return; 16178828Sobrien strcpy (name, in->n_name); 162218822Sdim flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD; 163218822Sdim sec = bfd_make_section_anyway_with_flags (abfd, name, flags); 16478828Sobrien 16578828Sobrien sec->vma = 0; 16678828Sobrien sec->lma = 0; 167218822Sdim sec->size = 0; 16878828Sobrien sec->filepos = 0; 16978828Sobrien sec->rel_filepos = 0; 17078828Sobrien sec->reloc_count = 0; 17178828Sobrien sec->line_filepos = 0; 17278828Sobrien sec->lineno_count = 0; 17378828Sobrien sec->userdata = NULL; 174218822Sdim sec->next = NULL; 17578828Sobrien sec->alignment_power = 2; 17678828Sobrien 17778828Sobrien sec->target_index = unused_section_number; 17878828Sobrien 17978828Sobrien in->n_scnum = unused_section_number; 18078828Sobrien } 18178828Sobrien in->n_sclass = C_STAT; 18278828Sobrien } 18378828Sobrien#endif 18478828Sobrien 18578828Sobrien#ifdef coff_swap_sym_in_hook 18678828Sobrien /* This won't work in peigen.c, but since it's for PPC PE, it's not 18778828Sobrien worth fixing. */ 18878828Sobrien coff_swap_sym_in_hook (abfd, ext1, in1); 18978828Sobrien#endif 19078828Sobrien} 19178828Sobrien 19278828Sobrienunsigned int 193218822Sdim_bfd_XXi_swap_sym_out (bfd * abfd, void * inp, void * extp) 19478828Sobrien{ 19578828Sobrien struct internal_syment *in = (struct internal_syment *) inp; 19678828Sobrien SYMENT *ext = (SYMENT *) extp; 19789857Sobrien 19878828Sobrien if (in->_n._n_name[0] == 0) 19978828Sobrien { 20089857Sobrien H_PUT_32 (abfd, 0, ext->e.e.e_zeroes); 20189857Sobrien H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e.e.e_offset); 20278828Sobrien } 20378828Sobrien else 20489857Sobrien memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN); 20578828Sobrien 20689857Sobrien H_PUT_32 (abfd, in->n_value, ext->e_value); 20789857Sobrien H_PUT_16 (abfd, in->n_scnum, ext->e_scnum); 20889857Sobrien 20978828Sobrien if (sizeof (ext->e_type) == 2) 21089857Sobrien H_PUT_16 (abfd, in->n_type, ext->e_type); 21178828Sobrien else 21289857Sobrien H_PUT_32 (abfd, in->n_type, ext->e_type); 21378828Sobrien 21489857Sobrien H_PUT_8 (abfd, in->n_sclass, ext->e_sclass); 21589857Sobrien H_PUT_8 (abfd, in->n_numaux, ext->e_numaux); 21689857Sobrien 21778828Sobrien return SYMESZ; 21878828Sobrien} 21978828Sobrien 22078828Sobrienvoid 221218822Sdim_bfd_XXi_swap_aux_in (bfd * abfd, 222218822Sdim void * ext1, 223218822Sdim int type, 224218822Sdim int class, 225218822Sdim int indx ATTRIBUTE_UNUSED, 226218822Sdim int numaux ATTRIBUTE_UNUSED, 227218822Sdim void * in1) 22878828Sobrien{ 22978828Sobrien AUXENT *ext = (AUXENT *) ext1; 23078828Sobrien union internal_auxent *in = (union internal_auxent *) in1; 23178828Sobrien 23278828Sobrien switch (class) 23378828Sobrien { 23478828Sobrien case C_FILE: 23578828Sobrien if (ext->x_file.x_fname[0] == 0) 23678828Sobrien { 23778828Sobrien in->x_file.x_n.x_zeroes = 0; 23889857Sobrien in->x_file.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset); 23978828Sobrien } 24078828Sobrien else 24189857Sobrien memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN); 24278828Sobrien return; 24378828Sobrien 24478828Sobrien case C_STAT: 24578828Sobrien case C_LEAFSTAT: 24678828Sobrien case C_HIDDEN: 24778828Sobrien if (type == T_NULL) 24878828Sobrien { 24978828Sobrien in->x_scn.x_scnlen = GET_SCN_SCNLEN (abfd, ext); 25078828Sobrien in->x_scn.x_nreloc = GET_SCN_NRELOC (abfd, ext); 25178828Sobrien in->x_scn.x_nlinno = GET_SCN_NLINNO (abfd, ext); 25289857Sobrien in->x_scn.x_checksum = H_GET_32 (abfd, ext->x_scn.x_checksum); 25389857Sobrien in->x_scn.x_associated = H_GET_16 (abfd, ext->x_scn.x_associated); 25489857Sobrien in->x_scn.x_comdat = H_GET_8 (abfd, ext->x_scn.x_comdat); 25578828Sobrien return; 25678828Sobrien } 25778828Sobrien break; 25878828Sobrien } 25978828Sobrien 26089857Sobrien in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx); 26189857Sobrien in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx); 26278828Sobrien 26378828Sobrien if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class)) 26478828Sobrien { 26578828Sobrien in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext); 26678828Sobrien in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext); 26778828Sobrien } 26878828Sobrien else 26978828Sobrien { 27078828Sobrien in->x_sym.x_fcnary.x_ary.x_dimen[0] = 27189857Sobrien H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]); 27278828Sobrien in->x_sym.x_fcnary.x_ary.x_dimen[1] = 27389857Sobrien H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]); 27478828Sobrien in->x_sym.x_fcnary.x_ary.x_dimen[2] = 27589857Sobrien H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]); 27678828Sobrien in->x_sym.x_fcnary.x_ary.x_dimen[3] = 27789857Sobrien H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]); 27878828Sobrien } 27978828Sobrien 28078828Sobrien if (ISFCN (type)) 28178828Sobrien { 28289857Sobrien in->x_sym.x_misc.x_fsize = H_GET_32 (abfd, ext->x_sym.x_misc.x_fsize); 28378828Sobrien } 28478828Sobrien else 28578828Sobrien { 28678828Sobrien in->x_sym.x_misc.x_lnsz.x_lnno = GET_LNSZ_LNNO (abfd, ext); 28778828Sobrien in->x_sym.x_misc.x_lnsz.x_size = GET_LNSZ_SIZE (abfd, ext); 28878828Sobrien } 28978828Sobrien} 29078828Sobrien 29178828Sobrienunsigned int 292218822Sdim_bfd_XXi_swap_aux_out (bfd * abfd, 293218822Sdim void * inp, 294218822Sdim int type, 295218822Sdim int class, 296218822Sdim int indx ATTRIBUTE_UNUSED, 297218822Sdim int numaux ATTRIBUTE_UNUSED, 298218822Sdim void * extp) 29978828Sobrien{ 30078828Sobrien union internal_auxent *in = (union internal_auxent *) inp; 30178828Sobrien AUXENT *ext = (AUXENT *) extp; 30278828Sobrien 303218822Sdim memset (ext, 0, AUXESZ); 304218822Sdim 30578828Sobrien switch (class) 30678828Sobrien { 30778828Sobrien case C_FILE: 30878828Sobrien if (in->x_file.x_fname[0] == 0) 30978828Sobrien { 31089857Sobrien H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes); 31189857Sobrien H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset); 31278828Sobrien } 31378828Sobrien else 31489857Sobrien memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN); 31589857Sobrien 31678828Sobrien return AUXESZ; 31778828Sobrien 31878828Sobrien case C_STAT: 31978828Sobrien case C_LEAFSTAT: 32078828Sobrien case C_HIDDEN: 32178828Sobrien if (type == T_NULL) 32278828Sobrien { 32378828Sobrien PUT_SCN_SCNLEN (abfd, in->x_scn.x_scnlen, ext); 32478828Sobrien PUT_SCN_NRELOC (abfd, in->x_scn.x_nreloc, ext); 32578828Sobrien PUT_SCN_NLINNO (abfd, in->x_scn.x_nlinno, ext); 32689857Sobrien H_PUT_32 (abfd, in->x_scn.x_checksum, ext->x_scn.x_checksum); 32789857Sobrien H_PUT_16 (abfd, in->x_scn.x_associated, ext->x_scn.x_associated); 32889857Sobrien H_PUT_8 (abfd, in->x_scn.x_comdat, ext->x_scn.x_comdat); 32978828Sobrien return AUXESZ; 33078828Sobrien } 33178828Sobrien break; 33278828Sobrien } 33378828Sobrien 33489857Sobrien H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx); 33589857Sobrien H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx); 33678828Sobrien 33778828Sobrien if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class)) 33878828Sobrien { 33978828Sobrien PUT_FCN_LNNOPTR (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext); 34078828Sobrien PUT_FCN_ENDNDX (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext); 34178828Sobrien } 34278828Sobrien else 34378828Sobrien { 34489857Sobrien H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0], 34589857Sobrien ext->x_sym.x_fcnary.x_ary.x_dimen[0]); 34689857Sobrien H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1], 34789857Sobrien ext->x_sym.x_fcnary.x_ary.x_dimen[1]); 34889857Sobrien H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2], 34989857Sobrien ext->x_sym.x_fcnary.x_ary.x_dimen[2]); 35089857Sobrien H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3], 35189857Sobrien ext->x_sym.x_fcnary.x_ary.x_dimen[3]); 35278828Sobrien } 35378828Sobrien 35478828Sobrien if (ISFCN (type)) 35589857Sobrien H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize); 35678828Sobrien else 35778828Sobrien { 35878828Sobrien PUT_LNSZ_LNNO (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext); 35978828Sobrien PUT_LNSZ_SIZE (abfd, in->x_sym.x_misc.x_lnsz.x_size, ext); 36078828Sobrien } 36178828Sobrien 36278828Sobrien return AUXESZ; 36378828Sobrien} 36478828Sobrien 36578828Sobrienvoid 366218822Sdim_bfd_XXi_swap_lineno_in (bfd * abfd, void * ext1, void * in1) 36778828Sobrien{ 36878828Sobrien LINENO *ext = (LINENO *) ext1; 36978828Sobrien struct internal_lineno *in = (struct internal_lineno *) in1; 37078828Sobrien 37189857Sobrien in->l_addr.l_symndx = H_GET_32 (abfd, ext->l_addr.l_symndx); 37278828Sobrien in->l_lnno = GET_LINENO_LNNO (abfd, ext); 37378828Sobrien} 37478828Sobrien 37578828Sobrienunsigned int 376218822Sdim_bfd_XXi_swap_lineno_out (bfd * abfd, void * inp, void * outp) 37778828Sobrien{ 37878828Sobrien struct internal_lineno *in = (struct internal_lineno *) inp; 37978828Sobrien struct external_lineno *ext = (struct external_lineno *) outp; 38089857Sobrien H_PUT_32 (abfd, in->l_addr.l_symndx, ext->l_addr.l_symndx); 38178828Sobrien 38278828Sobrien PUT_LINENO_LNNO (abfd, in->l_lnno, ext); 38378828Sobrien return LINESZ; 38478828Sobrien} 38578828Sobrien 38678828Sobrienvoid 387218822Sdim_bfd_XXi_swap_aouthdr_in (bfd * abfd, 388218822Sdim void * aouthdr_ext1, 389218822Sdim void * aouthdr_int1) 39078828Sobrien{ 391218822Sdim PEAOUTHDR * src = (PEAOUTHDR *) aouthdr_ext1; 392218822Sdim AOUTHDR * aouthdr_ext = (AOUTHDR *) aouthdr_ext1; 393218822Sdim struct internal_aouthdr *aouthdr_int 394218822Sdim = (struct internal_aouthdr *) aouthdr_int1; 395218822Sdim struct internal_extra_pe_aouthdr *a = &aouthdr_int->pe; 39678828Sobrien 39789857Sobrien aouthdr_int->magic = H_GET_16 (abfd, aouthdr_ext->magic); 39889857Sobrien aouthdr_int->vstamp = H_GET_16 (abfd, aouthdr_ext->vstamp); 39989857Sobrien aouthdr_int->tsize = GET_AOUTHDR_TSIZE (abfd, aouthdr_ext->tsize); 40089857Sobrien aouthdr_int->dsize = GET_AOUTHDR_DSIZE (abfd, aouthdr_ext->dsize); 40189857Sobrien aouthdr_int->bsize = GET_AOUTHDR_BSIZE (abfd, aouthdr_ext->bsize); 40289857Sobrien aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry); 40378828Sobrien aouthdr_int->text_start = 40489857Sobrien GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start); 405218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 406218822Sdim /* PE32+ does not have data_start member! */ 40778828Sobrien aouthdr_int->data_start = 40889857Sobrien GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start); 409218822Sdim a->BaseOfData = aouthdr_int->data_start; 41078828Sobrien#endif 41178828Sobrien 412218822Sdim a->Magic = aouthdr_int->magic; 413218822Sdim a->MajorLinkerVersion = H_GET_8 (abfd, aouthdr_ext->vstamp); 414218822Sdim a->MinorLinkerVersion = H_GET_8 (abfd, aouthdr_ext->vstamp + 1); 415218822Sdim a->SizeOfCode = aouthdr_int->tsize ; 416218822Sdim a->SizeOfInitializedData = aouthdr_int->dsize ; 417218822Sdim a->SizeOfUninitializedData = aouthdr_int->bsize ; 418218822Sdim a->AddressOfEntryPoint = aouthdr_int->entry; 419218822Sdim a->BaseOfCode = aouthdr_int->text_start; 42089857Sobrien a->ImageBase = GET_OPTHDR_IMAGE_BASE (abfd, src->ImageBase); 42189857Sobrien a->SectionAlignment = H_GET_32 (abfd, src->SectionAlignment); 42289857Sobrien a->FileAlignment = H_GET_32 (abfd, src->FileAlignment); 42378828Sobrien a->MajorOperatingSystemVersion = 42489857Sobrien H_GET_16 (abfd, src->MajorOperatingSystemVersion); 42578828Sobrien a->MinorOperatingSystemVersion = 42689857Sobrien H_GET_16 (abfd, src->MinorOperatingSystemVersion); 42789857Sobrien a->MajorImageVersion = H_GET_16 (abfd, src->MajorImageVersion); 42889857Sobrien a->MinorImageVersion = H_GET_16 (abfd, src->MinorImageVersion); 42989857Sobrien a->MajorSubsystemVersion = H_GET_16 (abfd, src->MajorSubsystemVersion); 43089857Sobrien a->MinorSubsystemVersion = H_GET_16 (abfd, src->MinorSubsystemVersion); 43189857Sobrien a->Reserved1 = H_GET_32 (abfd, src->Reserved1); 43289857Sobrien a->SizeOfImage = H_GET_32 (abfd, src->SizeOfImage); 43389857Sobrien a->SizeOfHeaders = H_GET_32 (abfd, src->SizeOfHeaders); 43489857Sobrien a->CheckSum = H_GET_32 (abfd, src->CheckSum); 43589857Sobrien a->Subsystem = H_GET_16 (abfd, src->Subsystem); 43689857Sobrien a->DllCharacteristics = H_GET_16 (abfd, src->DllCharacteristics); 43789857Sobrien a->SizeOfStackReserve = 43889857Sobrien GET_OPTHDR_SIZE_OF_STACK_RESERVE (abfd, src->SizeOfStackReserve); 43989857Sobrien a->SizeOfStackCommit = 44089857Sobrien GET_OPTHDR_SIZE_OF_STACK_COMMIT (abfd, src->SizeOfStackCommit); 44189857Sobrien a->SizeOfHeapReserve = 44289857Sobrien GET_OPTHDR_SIZE_OF_HEAP_RESERVE (abfd, src->SizeOfHeapReserve); 44389857Sobrien a->SizeOfHeapCommit = 44489857Sobrien GET_OPTHDR_SIZE_OF_HEAP_COMMIT (abfd, src->SizeOfHeapCommit); 44589857Sobrien a->LoaderFlags = H_GET_32 (abfd, src->LoaderFlags); 44689857Sobrien a->NumberOfRvaAndSizes = H_GET_32 (abfd, src->NumberOfRvaAndSizes); 44778828Sobrien 44878828Sobrien { 44978828Sobrien int idx; 45089857Sobrien 451326380Semaste /* PR 17512: Corrupt PE binaries can cause seg-faults. */ 452326380Semaste if (a->NumberOfRvaAndSizes > 16) 453326380Semaste { 454326380Semaste (*_bfd_error_handler) 455326380Semaste (_("%B: aout header specifies an invalid number of data-directory entries: %d"), 456326380Semaste abfd, a->NumberOfRvaAndSizes); 457326380Semaste /* Paranoia: If the number is corrupt, then assume that the 458326380Semaste actual entries themselves might be corrupt as well. */ 459326380Semaste a->NumberOfRvaAndSizes = 0; 460326380Semaste } 461326380Semaste 46278828Sobrien for (idx = 0; idx < 16; idx++) 46378828Sobrien { 46478828Sobrien /* If data directory is empty, rva also should be 0. */ 46578828Sobrien int size = 46689857Sobrien H_GET_32 (abfd, src->DataDirectory[idx][1]); 467218822Sdim 46878828Sobrien a->DataDirectory[idx].Size = size; 46978828Sobrien 47078828Sobrien if (size) 47189857Sobrien a->DataDirectory[idx].VirtualAddress = 47289857Sobrien H_GET_32 (abfd, src->DataDirectory[idx][0]); 47378828Sobrien else 47478828Sobrien a->DataDirectory[idx].VirtualAddress = 0; 47578828Sobrien } 47678828Sobrien } 47778828Sobrien 47878828Sobrien if (aouthdr_int->entry) 47978828Sobrien { 48078828Sobrien aouthdr_int->entry += a->ImageBase; 481218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 48278828Sobrien aouthdr_int->entry &= 0xffffffff; 48378828Sobrien#endif 48478828Sobrien } 48589857Sobrien 48678828Sobrien if (aouthdr_int->tsize) 48778828Sobrien { 48878828Sobrien aouthdr_int->text_start += a->ImageBase; 489218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 49078828Sobrien aouthdr_int->text_start &= 0xffffffff; 49178828Sobrien#endif 49278828Sobrien } 49389857Sobrien 494218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 495218822Sdim /* PE32+ does not have data_start member! */ 49678828Sobrien if (aouthdr_int->dsize) 49778828Sobrien { 49878828Sobrien aouthdr_int->data_start += a->ImageBase; 49978828Sobrien aouthdr_int->data_start &= 0xffffffff; 50078828Sobrien } 50178828Sobrien#endif 50278828Sobrien 50378828Sobrien#ifdef POWERPC_LE_PE 50478828Sobrien /* These three fields are normally set up by ppc_relocate_section. 50578828Sobrien In the case of reading a file in, we can pick them up from the 50678828Sobrien DataDirectory. */ 507218822Sdim first_thunk_address = a->DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress; 508218822Sdim thunk_size = a->DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size; 509218822Sdim import_table_size = a->DataDirectory[PE_IMPORT_TABLE].Size; 51078828Sobrien#endif 51178828Sobrien} 51278828Sobrien 51378828Sobrien/* A support function for below. */ 51478828Sobrien 51578828Sobrienstatic void 516218822Sdimadd_data_entry (bfd * abfd, 517218822Sdim struct internal_extra_pe_aouthdr *aout, 518218822Sdim int idx, 519218822Sdim char *name, 520218822Sdim bfd_vma base) 52178828Sobrien{ 52278828Sobrien asection *sec = bfd_get_section_by_name (abfd, name); 52378828Sobrien 52489857Sobrien /* Add import directory information if it exists. */ 52578828Sobrien if ((sec != NULL) 52678828Sobrien && (coff_section_data (abfd, sec) != NULL) 52778828Sobrien && (pei_section_data (abfd, sec) != NULL)) 52878828Sobrien { 52989857Sobrien /* If data directory is empty, rva also should be 0. */ 53078828Sobrien int size = pei_section_data (abfd, sec)->virt_size; 53178828Sobrien aout->DataDirectory[idx].Size = size; 53278828Sobrien 53378828Sobrien if (size) 53478828Sobrien { 53578828Sobrien aout->DataDirectory[idx].VirtualAddress = 53678828Sobrien (sec->vma - base) & 0xffffffff; 53778828Sobrien sec->flags |= SEC_DATA; 53878828Sobrien } 53978828Sobrien } 54078828Sobrien} 54178828Sobrien 54278828Sobrienunsigned int 543218822Sdim_bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out) 54478828Sobrien{ 54578828Sobrien struct internal_aouthdr *aouthdr_in = (struct internal_aouthdr *) in; 54678828Sobrien pe_data_type *pe = pe_data (abfd); 54778828Sobrien struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; 54878828Sobrien PEAOUTHDR *aouthdr_out = (PEAOUTHDR *) out; 54978828Sobrien bfd_vma sa, fa, ib; 550130561Sobrien IMAGE_DATA_DIRECTORY idata2, idata5, tls; 551130561Sobrien 55278828Sobrien if (pe->force_minimum_alignment) 55378828Sobrien { 55478828Sobrien if (!extra->FileAlignment) 55578828Sobrien extra->FileAlignment = PE_DEF_FILE_ALIGNMENT; 55678828Sobrien if (!extra->SectionAlignment) 55778828Sobrien extra->SectionAlignment = PE_DEF_SECTION_ALIGNMENT; 55878828Sobrien } 55978828Sobrien 56078828Sobrien if (extra->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) 56178828Sobrien extra->Subsystem = pe->target_subsystem; 56278828Sobrien 56378828Sobrien sa = extra->SectionAlignment; 56478828Sobrien fa = extra->FileAlignment; 56578828Sobrien ib = extra->ImageBase; 56678828Sobrien 567218822Sdim idata2 = pe->pe_opthdr.DataDirectory[PE_IMPORT_TABLE]; 568218822Sdim idata5 = pe->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE]; 569218822Sdim tls = pe->pe_opthdr.DataDirectory[PE_TLS_TABLE]; 570130561Sobrien 57178828Sobrien if (aouthdr_in->tsize) 57278828Sobrien { 57378828Sobrien aouthdr_in->text_start -= ib; 574218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 57578828Sobrien aouthdr_in->text_start &= 0xffffffff; 57678828Sobrien#endif 57778828Sobrien } 57889857Sobrien 57978828Sobrien if (aouthdr_in->dsize) 58078828Sobrien { 58178828Sobrien aouthdr_in->data_start -= ib; 582218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 58378828Sobrien aouthdr_in->data_start &= 0xffffffff; 58478828Sobrien#endif 58578828Sobrien } 58689857Sobrien 58778828Sobrien if (aouthdr_in->entry) 58878828Sobrien { 58978828Sobrien aouthdr_in->entry -= ib; 590218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 59178828Sobrien aouthdr_in->entry &= 0xffffffff; 59278828Sobrien#endif 59378828Sobrien } 59478828Sobrien 59578828Sobrien#define FA(x) (((x) + fa -1 ) & (- fa)) 59678828Sobrien#define SA(x) (((x) + sa -1 ) & (- sa)) 59778828Sobrien 59878828Sobrien /* We like to have the sizes aligned. */ 59978828Sobrien aouthdr_in->bsize = FA (aouthdr_in->bsize); 60078828Sobrien 60178828Sobrien extra->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 60278828Sobrien 603130561Sobrien /* First null out all data directory entries. */ 604104834Sobrien memset (extra->DataDirectory, 0, sizeof (extra->DataDirectory)); 60578828Sobrien 60678828Sobrien add_data_entry (abfd, extra, 0, ".edata", ib); 607130561Sobrien add_data_entry (abfd, extra, 2, ".rsrc", ib); 608130561Sobrien add_data_entry (abfd, extra, 3, ".pdata", ib); 60978828Sobrien 610130561Sobrien /* In theory we do not need to call add_data_entry for .idata$2 or 611130561Sobrien .idata$5. It will be done in bfd_coff_final_link where all the 612130561Sobrien required information is available. If however, we are not going 613130561Sobrien to perform a final link, eg because we have been invoked by objcopy 614130561Sobrien or strip, then we need to make sure that these Data Directory 615130561Sobrien entries are initialised properly. 61678828Sobrien 617130561Sobrien So - we copy the input values into the output values, and then, if 618130561Sobrien a final link is going to be performed, it can overwrite them. */ 619218822Sdim extra->DataDirectory[PE_IMPORT_TABLE] = idata2; 620218822Sdim extra->DataDirectory[PE_IMPORT_ADDRESS_TABLE] = idata5; 621218822Sdim extra->DataDirectory[PE_TLS_TABLE] = tls; 62278828Sobrien 623218822Sdim if (extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress == 0) 624130561Sobrien /* Until other .idata fixes are made (pending patch), the entry for 625130561Sobrien .idata is needed for backwards compatibility. FIXME. */ 626130561Sobrien add_data_entry (abfd, extra, 1, ".idata", ib); 627130561Sobrien 62878828Sobrien /* For some reason, the virtual size (which is what's set by 62978828Sobrien add_data_entry) for .reloc is not the same as the size recorded 63078828Sobrien in this slot by MSVC; it doesn't seem to cause problems (so far), 63178828Sobrien but since it's the best we've got, use it. It does do the right 63278828Sobrien thing for .pdata. */ 63378828Sobrien if (pe->has_reloc_section) 63478828Sobrien add_data_entry (abfd, extra, 5, ".reloc", ib); 63578828Sobrien 63678828Sobrien { 63778828Sobrien asection *sec; 638218822Sdim bfd_vma hsize = 0; 63978828Sobrien bfd_vma dsize = 0; 640218822Sdim bfd_vma isize = 0; 64178828Sobrien bfd_vma tsize = 0; 64278828Sobrien 64378828Sobrien for (sec = abfd->sections; sec; sec = sec->next) 64478828Sobrien { 645218822Sdim int rounded = FA (sec->size); 64678828Sobrien 647218822Sdim /* The first non-zero section filepos is the header size. 648218822Sdim Sections without contents will have a filepos of 0. */ 649218822Sdim if (hsize == 0) 650218822Sdim hsize = sec->filepos; 65178828Sobrien if (sec->flags & SEC_DATA) 65278828Sobrien dsize += rounded; 65378828Sobrien if (sec->flags & SEC_CODE) 65478828Sobrien tsize += rounded; 65578828Sobrien /* The image size is the total VIRTUAL size (which is what is 65678828Sobrien in the virt_size field). Files have been seen (from MSVC 65778828Sobrien 5.0 link.exe) where the file size of the .data segment is 65878828Sobrien quite small compared to the virtual size. Without this 659218822Sdim fix, strip munges the file. 660218822Sdim 661218822Sdim FIXME: We need to handle holes between sections, which may 662218822Sdim happpen when we covert from another format. We just use 663218822Sdim the virtual address and virtual size of the last section 664218822Sdim for the image size. */ 665130561Sobrien if (coff_section_data (abfd, sec) != NULL 666130561Sobrien && pei_section_data (abfd, sec) != NULL) 667218822Sdim isize = (sec->vma - extra->ImageBase 668218822Sdim + SA (FA (pei_section_data (abfd, sec)->virt_size))); 66978828Sobrien } 67078828Sobrien 67178828Sobrien aouthdr_in->dsize = dsize; 67278828Sobrien aouthdr_in->tsize = tsize; 673218822Sdim extra->SizeOfHeaders = hsize; 67478828Sobrien extra->SizeOfImage = isize; 67578828Sobrien } 67678828Sobrien 67789857Sobrien H_PUT_16 (abfd, aouthdr_in->magic, aouthdr_out->standard.magic); 67878828Sobrien 67978828Sobrien#define LINKER_VERSION 256 /* That is, 2.56 */ 68078828Sobrien 68178828Sobrien /* This piece of magic sets the "linker version" field to 68278828Sobrien LINKER_VERSION. */ 68389857Sobrien H_PUT_16 (abfd, (LINKER_VERSION / 100 + (LINKER_VERSION % 100) * 256), 68489857Sobrien aouthdr_out->standard.vstamp); 68578828Sobrien 68689857Sobrien PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, aouthdr_out->standard.tsize); 68789857Sobrien PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, aouthdr_out->standard.dsize); 68889857Sobrien PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, aouthdr_out->standard.bsize); 68989857Sobrien PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, aouthdr_out->standard.entry); 69078828Sobrien PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start, 69189857Sobrien aouthdr_out->standard.text_start); 69278828Sobrien 693218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 694130561Sobrien /* PE32+ does not have data_start member! */ 69578828Sobrien PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start, 69689857Sobrien aouthdr_out->standard.data_start); 69778828Sobrien#endif 69878828Sobrien 69989857Sobrien PUT_OPTHDR_IMAGE_BASE (abfd, extra->ImageBase, aouthdr_out->ImageBase); 70089857Sobrien H_PUT_32 (abfd, extra->SectionAlignment, aouthdr_out->SectionAlignment); 70189857Sobrien H_PUT_32 (abfd, extra->FileAlignment, aouthdr_out->FileAlignment); 70289857Sobrien H_PUT_16 (abfd, extra->MajorOperatingSystemVersion, 70389857Sobrien aouthdr_out->MajorOperatingSystemVersion); 70489857Sobrien H_PUT_16 (abfd, extra->MinorOperatingSystemVersion, 70589857Sobrien aouthdr_out->MinorOperatingSystemVersion); 70689857Sobrien H_PUT_16 (abfd, extra->MajorImageVersion, aouthdr_out->MajorImageVersion); 70789857Sobrien H_PUT_16 (abfd, extra->MinorImageVersion, aouthdr_out->MinorImageVersion); 70889857Sobrien H_PUT_16 (abfd, extra->MajorSubsystemVersion, 70989857Sobrien aouthdr_out->MajorSubsystemVersion); 71089857Sobrien H_PUT_16 (abfd, extra->MinorSubsystemVersion, 71189857Sobrien aouthdr_out->MinorSubsystemVersion); 71289857Sobrien H_PUT_32 (abfd, extra->Reserved1, aouthdr_out->Reserved1); 71389857Sobrien H_PUT_32 (abfd, extra->SizeOfImage, aouthdr_out->SizeOfImage); 71489857Sobrien H_PUT_32 (abfd, extra->SizeOfHeaders, aouthdr_out->SizeOfHeaders); 71589857Sobrien H_PUT_32 (abfd, extra->CheckSum, aouthdr_out->CheckSum); 71689857Sobrien H_PUT_16 (abfd, extra->Subsystem, aouthdr_out->Subsystem); 71789857Sobrien H_PUT_16 (abfd, extra->DllCharacteristics, aouthdr_out->DllCharacteristics); 71878828Sobrien PUT_OPTHDR_SIZE_OF_STACK_RESERVE (abfd, extra->SizeOfStackReserve, 71989857Sobrien aouthdr_out->SizeOfStackReserve); 72078828Sobrien PUT_OPTHDR_SIZE_OF_STACK_COMMIT (abfd, extra->SizeOfStackCommit, 72189857Sobrien aouthdr_out->SizeOfStackCommit); 72278828Sobrien PUT_OPTHDR_SIZE_OF_HEAP_RESERVE (abfd, extra->SizeOfHeapReserve, 72389857Sobrien aouthdr_out->SizeOfHeapReserve); 72478828Sobrien PUT_OPTHDR_SIZE_OF_HEAP_COMMIT (abfd, extra->SizeOfHeapCommit, 72589857Sobrien aouthdr_out->SizeOfHeapCommit); 72689857Sobrien H_PUT_32 (abfd, extra->LoaderFlags, aouthdr_out->LoaderFlags); 72789857Sobrien H_PUT_32 (abfd, extra->NumberOfRvaAndSizes, 72889857Sobrien aouthdr_out->NumberOfRvaAndSizes); 72978828Sobrien { 73078828Sobrien int idx; 73189857Sobrien 73278828Sobrien for (idx = 0; idx < 16; idx++) 73378828Sobrien { 73489857Sobrien H_PUT_32 (abfd, extra->DataDirectory[idx].VirtualAddress, 73589857Sobrien aouthdr_out->DataDirectory[idx][0]); 73689857Sobrien H_PUT_32 (abfd, extra->DataDirectory[idx].Size, 73789857Sobrien aouthdr_out->DataDirectory[idx][1]); 73878828Sobrien } 73978828Sobrien } 74078828Sobrien 74178828Sobrien return AOUTSZ; 74278828Sobrien} 74378828Sobrien 74478828Sobrienunsigned int 745218822Sdim_bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out) 74678828Sobrien{ 74778828Sobrien int idx; 74878828Sobrien struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; 74978828Sobrien struct external_PEI_filehdr *filehdr_out = (struct external_PEI_filehdr *) out; 75078828Sobrien 75178828Sobrien if (pe_data (abfd)->has_reloc_section) 75278828Sobrien filehdr_in->f_flags &= ~F_RELFLG; 75378828Sobrien 75478828Sobrien if (pe_data (abfd)->dll) 75578828Sobrien filehdr_in->f_flags |= F_DLL; 75678828Sobrien 75778828Sobrien filehdr_in->pe.e_magic = DOSMAGIC; 75878828Sobrien filehdr_in->pe.e_cblp = 0x90; 75978828Sobrien filehdr_in->pe.e_cp = 0x3; 76078828Sobrien filehdr_in->pe.e_crlc = 0x0; 76178828Sobrien filehdr_in->pe.e_cparhdr = 0x4; 76278828Sobrien filehdr_in->pe.e_minalloc = 0x0; 76378828Sobrien filehdr_in->pe.e_maxalloc = 0xffff; 76478828Sobrien filehdr_in->pe.e_ss = 0x0; 76578828Sobrien filehdr_in->pe.e_sp = 0xb8; 76678828Sobrien filehdr_in->pe.e_csum = 0x0; 76778828Sobrien filehdr_in->pe.e_ip = 0x0; 76878828Sobrien filehdr_in->pe.e_cs = 0x0; 76978828Sobrien filehdr_in->pe.e_lfarlc = 0x40; 77078828Sobrien filehdr_in->pe.e_ovno = 0x0; 77178828Sobrien 77278828Sobrien for (idx = 0; idx < 4; idx++) 77378828Sobrien filehdr_in->pe.e_res[idx] = 0x0; 77478828Sobrien 77578828Sobrien filehdr_in->pe.e_oemid = 0x0; 77678828Sobrien filehdr_in->pe.e_oeminfo = 0x0; 77778828Sobrien 77878828Sobrien for (idx = 0; idx < 10; idx++) 77978828Sobrien filehdr_in->pe.e_res2[idx] = 0x0; 78078828Sobrien 78178828Sobrien filehdr_in->pe.e_lfanew = 0x80; 78278828Sobrien 78378828Sobrien /* This next collection of data are mostly just characters. It 78478828Sobrien appears to be constant within the headers put on NT exes. */ 78578828Sobrien filehdr_in->pe.dos_message[0] = 0x0eba1f0e; 78678828Sobrien filehdr_in->pe.dos_message[1] = 0xcd09b400; 78778828Sobrien filehdr_in->pe.dos_message[2] = 0x4c01b821; 78878828Sobrien filehdr_in->pe.dos_message[3] = 0x685421cd; 78978828Sobrien filehdr_in->pe.dos_message[4] = 0x70207369; 79078828Sobrien filehdr_in->pe.dos_message[5] = 0x72676f72; 79178828Sobrien filehdr_in->pe.dos_message[6] = 0x63206d61; 79278828Sobrien filehdr_in->pe.dos_message[7] = 0x6f6e6e61; 79378828Sobrien filehdr_in->pe.dos_message[8] = 0x65622074; 79478828Sobrien filehdr_in->pe.dos_message[9] = 0x6e757220; 79578828Sobrien filehdr_in->pe.dos_message[10] = 0x206e6920; 79678828Sobrien filehdr_in->pe.dos_message[11] = 0x20534f44; 79778828Sobrien filehdr_in->pe.dos_message[12] = 0x65646f6d; 79878828Sobrien filehdr_in->pe.dos_message[13] = 0x0a0d0d2e; 79978828Sobrien filehdr_in->pe.dos_message[14] = 0x24; 80078828Sobrien filehdr_in->pe.dos_message[15] = 0x0; 80178828Sobrien filehdr_in->pe.nt_signature = NT_SIGNATURE; 80278828Sobrien 80389857Sobrien H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic); 80489857Sobrien H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns); 80578828Sobrien 80689857Sobrien H_PUT_32 (abfd, time (0), filehdr_out->f_timdat); 80789857Sobrien PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, 80889857Sobrien filehdr_out->f_symptr); 80989857Sobrien H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms); 81089857Sobrien H_PUT_16 (abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr); 81189857Sobrien H_PUT_16 (abfd, filehdr_in->f_flags, filehdr_out->f_flags); 81278828Sobrien 81389857Sobrien /* Put in extra dos header stuff. This data remains essentially 81478828Sobrien constant, it just has to be tacked on to the beginning of all exes 81589857Sobrien for NT. */ 81689857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_magic, filehdr_out->e_magic); 81789857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_cblp, filehdr_out->e_cblp); 81889857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_cp, filehdr_out->e_cp); 81989857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_crlc, filehdr_out->e_crlc); 82089857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_cparhdr, filehdr_out->e_cparhdr); 82189857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_minalloc, filehdr_out->e_minalloc); 82289857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_maxalloc, filehdr_out->e_maxalloc); 82389857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_ss, filehdr_out->e_ss); 82489857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_sp, filehdr_out->e_sp); 82589857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_csum, filehdr_out->e_csum); 82689857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_ip, filehdr_out->e_ip); 82789857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_cs, filehdr_out->e_cs); 82889857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_lfarlc, filehdr_out->e_lfarlc); 82989857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_ovno, filehdr_out->e_ovno); 83078828Sobrien 83189857Sobrien for (idx = 0; idx < 4; idx++) 83289857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_res[idx], filehdr_out->e_res[idx]); 83378828Sobrien 83489857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_oemid, filehdr_out->e_oemid); 83589857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_oeminfo, filehdr_out->e_oeminfo); 83689857Sobrien 83789857Sobrien for (idx = 0; idx < 10; idx++) 83889857Sobrien H_PUT_16 (abfd, filehdr_in->pe.e_res2[idx], filehdr_out->e_res2[idx]); 83989857Sobrien 84089857Sobrien H_PUT_32 (abfd, filehdr_in->pe.e_lfanew, filehdr_out->e_lfanew); 84189857Sobrien 84289857Sobrien for (idx = 0; idx < 16; idx++) 84389857Sobrien H_PUT_32 (abfd, filehdr_in->pe.dos_message[idx], 84489857Sobrien filehdr_out->dos_message[idx]); 84589857Sobrien 84678828Sobrien /* Also put in the NT signature. */ 84789857Sobrien H_PUT_32 (abfd, filehdr_in->pe.nt_signature, filehdr_out->nt_signature); 84878828Sobrien 84978828Sobrien return FILHSZ; 85078828Sobrien} 85178828Sobrien 85278828Sobrienunsigned int 853218822Sdim_bfd_XX_only_swap_filehdr_out (bfd * abfd, void * in, void * out) 85478828Sobrien{ 85578828Sobrien struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; 85678828Sobrien FILHDR *filehdr_out = (FILHDR *) out; 85778828Sobrien 85889857Sobrien H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic); 85989857Sobrien H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns); 86089857Sobrien H_PUT_32 (abfd, filehdr_in->f_timdat, filehdr_out->f_timdat); 86189857Sobrien PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, filehdr_out->f_symptr); 86289857Sobrien H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms); 86389857Sobrien H_PUT_16 (abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr); 86489857Sobrien H_PUT_16 (abfd, filehdr_in->f_flags, filehdr_out->f_flags); 86578828Sobrien 86678828Sobrien return FILHSZ; 86778828Sobrien} 86878828Sobrien 86978828Sobrienunsigned int 870218822Sdim_bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out) 87178828Sobrien{ 87278828Sobrien struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in; 87378828Sobrien SCNHDR *scnhdr_ext = (SCNHDR *) out; 87478828Sobrien unsigned int ret = SCNHSZ; 87578828Sobrien bfd_vma ps; 87678828Sobrien bfd_vma ss; 87778828Sobrien 87878828Sobrien memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name)); 87978828Sobrien 88078828Sobrien PUT_SCNHDR_VADDR (abfd, 88178828Sobrien ((scnhdr_int->s_vaddr 88278828Sobrien - pe_data (abfd)->pe_opthdr.ImageBase) 88378828Sobrien & 0xffffffff), 88489857Sobrien scnhdr_ext->s_vaddr); 88578828Sobrien 88678828Sobrien /* NT wants the size data to be rounded up to the next 88778828Sobrien NT_FILE_ALIGNMENT, but zero if it has no content (as in .bss, 88878828Sobrien sometimes). */ 88978828Sobrien if ((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0) 89078828Sobrien { 891130561Sobrien if (bfd_pe_executable_p (abfd)) 892130561Sobrien { 893130561Sobrien ps = scnhdr_int->s_size; 894130561Sobrien ss = 0; 895130561Sobrien } 896130561Sobrien else 897130561Sobrien { 898130561Sobrien ps = 0; 899130561Sobrien ss = scnhdr_int->s_size; 900130561Sobrien } 90178828Sobrien } 90278828Sobrien else 90378828Sobrien { 904130561Sobrien if (bfd_pe_executable_p (abfd)) 905130561Sobrien ps = scnhdr_int->s_paddr; 906130561Sobrien else 907130561Sobrien ps = 0; 908130561Sobrien 90978828Sobrien ss = scnhdr_int->s_size; 91078828Sobrien } 91178828Sobrien 91278828Sobrien PUT_SCNHDR_SIZE (abfd, ss, 91389857Sobrien scnhdr_ext->s_size); 91478828Sobrien 91578828Sobrien /* s_paddr in PE is really the virtual size. */ 91689857Sobrien PUT_SCNHDR_PADDR (abfd, ps, scnhdr_ext->s_paddr); 91778828Sobrien 91878828Sobrien PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, 91989857Sobrien scnhdr_ext->s_scnptr); 92078828Sobrien PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr, 92189857Sobrien scnhdr_ext->s_relptr); 92278828Sobrien PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr, 92389857Sobrien scnhdr_ext->s_lnnoptr); 92478828Sobrien 925130561Sobrien { 926130561Sobrien /* Extra flags must be set when dealing with PE. All sections should also 927130561Sobrien have the IMAGE_SCN_MEM_READ (0x40000000) flag set. In addition, the 928130561Sobrien .text section must have IMAGE_SCN_MEM_EXECUTE (0x20000000) and the data 929130561Sobrien sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set 930130561Sobrien (this is especially important when dealing with the .idata section since 931130561Sobrien the addresses for routines from .dlls must be overwritten). If .reloc 932130561Sobrien section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE 933130561Sobrien (0x02000000). Also, the resource data should also be read and 934130561Sobrien writable. */ 93578828Sobrien 936130561Sobrien /* FIXME: Alignment is also encoded in this field, at least on PPC and 937130561Sobrien ARM-WINCE. Although - how do we get the original alignment field 938130561Sobrien back ? */ 93978828Sobrien 940130561Sobrien typedef struct 941130561Sobrien { 942130561Sobrien const char * section_name; 943130561Sobrien unsigned long must_have; 944130561Sobrien } 945130561Sobrien pe_required_section_flags; 946130561Sobrien 947130561Sobrien pe_required_section_flags known_sections [] = 948130561Sobrien { 949130561Sobrien { ".arch", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_ALIGN_8BYTES }, 950130561Sobrien { ".bss", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 951130561Sobrien { ".data", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 952130561Sobrien { ".edata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA }, 953130561Sobrien { ".idata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 954130561Sobrien { ".pdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA }, 955130561Sobrien { ".rdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA }, 956130561Sobrien { ".reloc", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE }, 957130561Sobrien { ".rsrc", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 958130561Sobrien { ".text" , IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE }, 959130561Sobrien { ".tls", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 960130561Sobrien { ".xdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA }, 961130561Sobrien { NULL, 0} 962130561Sobrien }; 963130561Sobrien 964130561Sobrien pe_required_section_flags * p; 96589857Sobrien 966130561Sobrien /* We have defaulted to adding the IMAGE_SCN_MEM_WRITE flag, but now 967130561Sobrien we know exactly what this specific section wants so we remove it 968130561Sobrien and then allow the must_have field to add it back in if necessary. 969130561Sobrien However, we don't remove IMAGE_SCN_MEM_WRITE flag from .text if the 970130561Sobrien default WP_TEXT file flag has been cleared. WP_TEXT may be cleared 971130561Sobrien by ld --enable-auto-import (if auto-import is actually needed), 972130561Sobrien by ld --omagic, or by obcopy --writable-text. */ 973130561Sobrien 974130561Sobrien for (p = known_sections; p->section_name; p++) 975130561Sobrien if (strcmp (scnhdr_int->s_name, p->section_name) == 0) 976130561Sobrien { 977130561Sobrien if (strcmp (scnhdr_int->s_name, ".text") 978130561Sobrien || (bfd_get_file_flags (abfd) & WP_TEXT)) 979218822Sdim scnhdr_int->s_flags &= ~IMAGE_SCN_MEM_WRITE; 980218822Sdim scnhdr_int->s_flags |= p->must_have; 981130561Sobrien break; 982130561Sobrien } 983130561Sobrien 984218822Sdim H_PUT_32 (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags); 98578828Sobrien } 98678828Sobrien 98778828Sobrien if (coff_data (abfd)->link_info 988130561Sobrien && ! coff_data (abfd)->link_info->relocatable 98978828Sobrien && ! coff_data (abfd)->link_info->shared 99078828Sobrien && strcmp (scnhdr_int->s_name, ".text") == 0) 99178828Sobrien { 99278828Sobrien /* By inference from looking at MS output, the 32 bit field 993130561Sobrien which is the combination of the number_of_relocs and 99478828Sobrien number_of_linenos is used for the line number count in 99578828Sobrien executables. A 16-bit field won't do for cc1. The MS 99678828Sobrien document says that the number of relocs is zero for 99778828Sobrien executables, but the 17-th bit has been observed to be there. 99878828Sobrien Overflow is not an issue: a 4G-line program will overflow a 99978828Sobrien bunch of other fields long before this! */ 100089857Sobrien H_PUT_16 (abfd, (scnhdr_int->s_nlnno & 0xffff), scnhdr_ext->s_nlnno); 100189857Sobrien H_PUT_16 (abfd, (scnhdr_int->s_nlnno >> 16), scnhdr_ext->s_nreloc); 100278828Sobrien } 100378828Sobrien else 100478828Sobrien { 100578828Sobrien if (scnhdr_int->s_nlnno <= 0xffff) 100689857Sobrien H_PUT_16 (abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno); 100778828Sobrien else 100878828Sobrien { 100978828Sobrien (*_bfd_error_handler) (_("%s: line number overflow: 0x%lx > 0xffff"), 101078828Sobrien bfd_get_filename (abfd), 101178828Sobrien scnhdr_int->s_nlnno); 101278828Sobrien bfd_set_error (bfd_error_file_truncated); 101389857Sobrien H_PUT_16 (abfd, 0xffff, scnhdr_ext->s_nlnno); 101478828Sobrien ret = 0; 101578828Sobrien } 101689857Sobrien 1017130561Sobrien /* Although we could encode 0xffff relocs here, we do not, to be 1018130561Sobrien consistent with other parts of bfd. Also it lets us warn, as 1019130561Sobrien we should never see 0xffff here w/o having the overflow flag 1020130561Sobrien set. */ 1021130561Sobrien if (scnhdr_int->s_nreloc < 0xffff) 102289857Sobrien H_PUT_16 (abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc); 102378828Sobrien else 102478828Sobrien { 102589857Sobrien /* PE can deal with large #s of relocs, but not here. */ 102689857Sobrien H_PUT_16 (abfd, 0xffff, scnhdr_ext->s_nreloc); 102778828Sobrien scnhdr_int->s_flags |= IMAGE_SCN_LNK_NRELOC_OVFL; 102889857Sobrien H_PUT_32 (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags); 102978828Sobrien } 103078828Sobrien } 103178828Sobrien return ret; 103278828Sobrien} 103378828Sobrien 103489857Sobrienstatic char * dir_names[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = 1035218822Sdim{ 1036218822Sdim N_("Export Directory [.edata (or where ever we found it)]"), 1037218822Sdim N_("Import Directory [parts of .idata]"), 1038218822Sdim N_("Resource Directory [.rsrc]"), 1039218822Sdim N_("Exception Directory [.pdata]"), 1040218822Sdim N_("Security Directory"), 1041218822Sdim N_("Base Relocation Directory [.reloc]"), 1042218822Sdim N_("Debug Directory"), 1043218822Sdim N_("Description Directory"), 1044218822Sdim N_("Special Directory"), 1045218822Sdim N_("Thread Storage Directory [.tls]"), 1046218822Sdim N_("Load Configuration Directory"), 1047218822Sdim N_("Bound Import Directory"), 1048218822Sdim N_("Import Address Table Directory"), 1049218822Sdim N_("Delay Import Directory"), 1050218822Sdim N_("CLR Runtime Header"), 1051218822Sdim N_("Reserved") 1052218822Sdim}; 105378828Sobrien 105478828Sobrien#ifdef POWERPC_LE_PE 105578828Sobrien/* The code for the PPC really falls in the "architecture dependent" 105678828Sobrien category. However, it's not clear that anyone will ever care, so 105778828Sobrien we're ignoring the issue for now; if/when PPC matters, some of this 105878828Sobrien may need to go into peicode.h, or arguments passed to enable the 105978828Sobrien PPC- specific code. */ 106078828Sobrien#endif 106178828Sobrien 1062130561Sobrienstatic bfd_boolean 1063218822Sdimpe_print_idata (bfd * abfd, void * vfile) 106478828Sobrien{ 106578828Sobrien FILE *file = (FILE *) vfile; 106678828Sobrien bfd_byte *data; 106778828Sobrien asection *section; 106878828Sobrien bfd_signed_vma adj; 106978828Sobrien 107078828Sobrien#ifdef POWERPC_LE_PE 107178828Sobrien asection *rel_section = bfd_get_section_by_name (abfd, ".reldata"); 107278828Sobrien#endif 107378828Sobrien 107478828Sobrien bfd_size_type datasize = 0; 107578828Sobrien bfd_size_type dataoff; 107678828Sobrien bfd_size_type i; 107778828Sobrien int onaline = 20; 107878828Sobrien 107978828Sobrien pe_data_type *pe = pe_data (abfd); 108078828Sobrien struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; 108178828Sobrien 108278828Sobrien bfd_vma addr; 108378828Sobrien 1084218822Sdim addr = extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress; 108578828Sobrien 1086218822Sdim if (addr == 0 && extra->DataDirectory[PE_IMPORT_TABLE].Size == 0) 108778828Sobrien { 108878828Sobrien /* Maybe the extra header isn't there. Look for the section. */ 108978828Sobrien section = bfd_get_section_by_name (abfd, ".idata"); 109078828Sobrien if (section == NULL) 1091130561Sobrien return TRUE; 109278828Sobrien 109378828Sobrien addr = section->vma; 1094218822Sdim datasize = section->size; 109578828Sobrien if (datasize == 0) 1096130561Sobrien return TRUE; 109778828Sobrien } 109878828Sobrien else 109978828Sobrien { 110078828Sobrien addr += extra->ImageBase; 110178828Sobrien for (section = abfd->sections; section != NULL; section = section->next) 110278828Sobrien { 1103218822Sdim datasize = section->size; 110478828Sobrien if (addr >= section->vma && addr < section->vma + datasize) 110578828Sobrien break; 110678828Sobrien } 110778828Sobrien 110878828Sobrien if (section == NULL) 110978828Sobrien { 111078828Sobrien fprintf (file, 111178828Sobrien _("\nThere is an import table, but the section containing it could not be found\n")); 1112130561Sobrien return TRUE; 111378828Sobrien } 111478828Sobrien } 111578828Sobrien 111678828Sobrien fprintf (file, _("\nThere is an import table in %s at 0x%lx\n"), 111778828Sobrien section->name, (unsigned long) addr); 111878828Sobrien 111978828Sobrien dataoff = addr - section->vma; 112078828Sobrien datasize -= dataoff; 112178828Sobrien 112278828Sobrien#ifdef POWERPC_LE_PE 1123218822Sdim if (rel_section != 0 && rel_section->size != 0) 112478828Sobrien { 112578828Sobrien /* The toc address can be found by taking the starting address, 112678828Sobrien which on the PPC locates a function descriptor. The 112778828Sobrien descriptor consists of the function code starting address 112878828Sobrien followed by the address of the toc. The starting address we 112978828Sobrien get from the bfd, and the descriptor is supposed to be in the 113078828Sobrien .reldata section. */ 113178828Sobrien 113278828Sobrien bfd_vma loadable_toc_address; 113378828Sobrien bfd_vma toc_address; 113478828Sobrien bfd_vma start_address; 1135218822Sdim bfd_byte *data; 1136218822Sdim bfd_vma offset; 113778828Sobrien 1138218822Sdim if (!bfd_malloc_and_get_section (abfd, rel_section, &data)) 1139218822Sdim { 1140218822Sdim if (data != NULL) 1141218822Sdim free (data); 1142218822Sdim return FALSE; 1143218822Sdim } 114478828Sobrien 114578828Sobrien offset = abfd->start_address - rel_section->vma; 114678828Sobrien 1147218822Sdim if (offset >= rel_section->size || offset + 8 > rel_section->size) 1148218822Sdim { 1149218822Sdim if (data != NULL) 1150218822Sdim free (data); 1151218822Sdim return FALSE; 1152218822Sdim } 1153218822Sdim 115478828Sobrien start_address = bfd_get_32 (abfd, data + offset); 115578828Sobrien loadable_toc_address = bfd_get_32 (abfd, data + offset + 4); 115678828Sobrien toc_address = loadable_toc_address - 32768; 115778828Sobrien 115878828Sobrien fprintf (file, 115978828Sobrien _("\nFunction descriptor located at the start address: %04lx\n"), 116078828Sobrien (unsigned long int) (abfd->start_address)); 116178828Sobrien fprintf (file, 116278828Sobrien _("\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n"), 116378828Sobrien start_address, loadable_toc_address, toc_address); 1164218822Sdim if (data != NULL) 1165218822Sdim free (data); 116678828Sobrien } 116778828Sobrien else 116878828Sobrien { 116978828Sobrien fprintf (file, 117078828Sobrien _("\nNo reldata section! Function descriptor not decoded.\n")); 117178828Sobrien } 117278828Sobrien#endif 117378828Sobrien 117478828Sobrien fprintf (file, 117578828Sobrien _("\nThe Import Tables (interpreted %s section contents)\n"), 117678828Sobrien section->name); 117778828Sobrien fprintf (file, 117891041Sobrien _("\ 117991041Sobrien vma: Hint Time Forward DLL First\n\ 118091041Sobrien Table Stamp Chain Name Thunk\n")); 118178828Sobrien 118278828Sobrien /* Read the whole section. Some of the fields might be before dataoff. */ 1183218822Sdim if (!bfd_malloc_and_get_section (abfd, section, &data)) 1184218822Sdim { 1185218822Sdim if (data != NULL) 1186218822Sdim free (data); 1187218822Sdim return FALSE; 1188218822Sdim } 118978828Sobrien 119078828Sobrien adj = section->vma - extra->ImageBase; 119178828Sobrien 1192104834Sobrien /* Print all image import descriptors. */ 119378828Sobrien for (i = 0; i < datasize; i += onaline) 119478828Sobrien { 119578828Sobrien bfd_vma hint_addr; 119678828Sobrien bfd_vma time_stamp; 119778828Sobrien bfd_vma forward_chain; 119878828Sobrien bfd_vma dll_name; 119978828Sobrien bfd_vma first_thunk; 120078828Sobrien int idx = 0; 120178828Sobrien bfd_size_type j; 120278828Sobrien char *dll; 120378828Sobrien 1204218822Sdim /* Print (i + extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress). */ 120578828Sobrien fprintf (file, " %08lx\t", (unsigned long) (i + adj + dataoff)); 120678828Sobrien hint_addr = bfd_get_32 (abfd, data + i + dataoff); 120778828Sobrien time_stamp = bfd_get_32 (abfd, data + i + 4 + dataoff); 120878828Sobrien forward_chain = bfd_get_32 (abfd, data + i + 8 + dataoff); 120978828Sobrien dll_name = bfd_get_32 (abfd, data + i + 12 + dataoff); 121078828Sobrien first_thunk = bfd_get_32 (abfd, data + i + 16 + dataoff); 121178828Sobrien 121278828Sobrien fprintf (file, "%08lx %08lx %08lx %08lx %08lx\n", 121378828Sobrien (unsigned long) hint_addr, 121478828Sobrien (unsigned long) time_stamp, 121578828Sobrien (unsigned long) forward_chain, 121678828Sobrien (unsigned long) dll_name, 121778828Sobrien (unsigned long) first_thunk); 121878828Sobrien 121978828Sobrien if (hint_addr == 0 && first_thunk == 0) 122078828Sobrien break; 122178828Sobrien 1222218822Sdim if (dll_name - adj >= section->size) 1223218822Sdim break; 1224218822Sdim 122578828Sobrien dll = (char *) data + dll_name - adj; 122678828Sobrien fprintf (file, _("\n\tDLL Name: %s\n"), dll); 122778828Sobrien 122878828Sobrien if (hint_addr != 0) 122978828Sobrien { 1230104834Sobrien bfd_byte *ft_data; 1231104834Sobrien asection *ft_section; 1232104834Sobrien bfd_vma ft_addr; 1233104834Sobrien bfd_size_type ft_datasize; 1234104834Sobrien int ft_idx; 1235104834Sobrien int ft_allocated = 0; 123678828Sobrien 1237104834Sobrien fprintf (file, _("\tvma: Hint/Ord Member-Name Bound-To\n")); 1238104834Sobrien 123978828Sobrien idx = hint_addr - adj; 1240104834Sobrien 1241104834Sobrien ft_addr = first_thunk + extra->ImageBase; 1242104834Sobrien ft_data = data; 1243104834Sobrien ft_idx = first_thunk - adj; 1244104834Sobrien ft_allocated = 0; 1245218822Sdim 1246218822Sdim if (first_thunk != hint_addr) 1247104834Sobrien { 1248104834Sobrien /* Find the section which contains the first thunk. */ 1249104834Sobrien for (ft_section = abfd->sections; 1250104834Sobrien ft_section != NULL; 1251104834Sobrien ft_section = ft_section->next) 1252104834Sobrien { 1253218822Sdim ft_datasize = ft_section->size; 1254104834Sobrien if (ft_addr >= ft_section->vma 1255104834Sobrien && ft_addr < ft_section->vma + ft_datasize) 1256104834Sobrien break; 1257104834Sobrien } 125878828Sobrien 1259104834Sobrien if (ft_section == NULL) 1260104834Sobrien { 1261104834Sobrien fprintf (file, 1262104834Sobrien _("\nThere is a first thunk, but the section containing it could not be found\n")); 1263104834Sobrien continue; 1264104834Sobrien } 1265104834Sobrien 1266104834Sobrien /* Now check to see if this section is the same as our current 1267104834Sobrien section. If it is not then we will have to load its data in. */ 1268104834Sobrien if (ft_section == section) 1269104834Sobrien { 1270104834Sobrien ft_data = data; 1271104834Sobrien ft_idx = first_thunk - adj; 1272104834Sobrien } 1273104834Sobrien else 1274104834Sobrien { 1275104834Sobrien ft_idx = first_thunk - (ft_section->vma - extra->ImageBase); 1276218822Sdim ft_data = bfd_malloc (datasize); 1277104834Sobrien if (ft_data == NULL) 1278104834Sobrien continue; 1279104834Sobrien 1280104834Sobrien /* Read datasize bfd_bytes starting at offset ft_idx. */ 1281218822Sdim if (! bfd_get_section_contents 1282218822Sdim (abfd, ft_section, ft_data, (bfd_vma) ft_idx, datasize)) 1283104834Sobrien { 1284104834Sobrien free (ft_data); 1285104834Sobrien continue; 1286104834Sobrien } 1287104834Sobrien 1288104834Sobrien ft_idx = 0; 1289104834Sobrien ft_allocated = 1; 1290104834Sobrien } 1291104834Sobrien } 1292104834Sobrien 1293104834Sobrien /* Print HintName vector entries. */ 1294218822Sdim#ifdef COFF_WITH_pex64 1295218822Sdim for (j = 0; j < datasize; j += 8) 1296218822Sdim { 1297218822Sdim unsigned long member = bfd_get_32 (abfd, data + idx + j); 1298218822Sdim unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4); 1299218822Sdim 1300218822Sdim if (!member && !member_high) 1301218822Sdim break; 1302218822Sdim 1303218822Sdim if (member_high & 0x80000000) 1304218822Sdim fprintf (file, "\t%lx%08lx\t %4lx%08lx <none>", 1305218822Sdim member_high,member, member_high & 0x7fffffff, member); 1306218822Sdim else 1307218822Sdim { 1308218822Sdim int ordinal; 1309218822Sdim char *member_name; 1310218822Sdim 1311218822Sdim ordinal = bfd_get_16 (abfd, data + member - adj); 1312218822Sdim member_name = (char *) data + member - adj + 2; 1313218822Sdim fprintf (file, "\t%04lx\t %4d %s",member, ordinal, member_name); 1314218822Sdim } 1315218822Sdim 1316218822Sdim /* If the time stamp is not zero, the import address 1317218822Sdim table holds actual addresses. */ 1318218822Sdim if (time_stamp != 0 1319218822Sdim && first_thunk != 0 1320218822Sdim && first_thunk != hint_addr) 1321218822Sdim fprintf (file, "\t%04lx", 1322218822Sdim (long) bfd_get_32 (abfd, ft_data + ft_idx + j)); 1323218822Sdim fprintf (file, "\n"); 1324218822Sdim } 1325218822Sdim#else 132678828Sobrien for (j = 0; j < datasize; j += 4) 132778828Sobrien { 132878828Sobrien unsigned long member = bfd_get_32 (abfd, data + idx + j); 132978828Sobrien 1330104834Sobrien /* Print single IMAGE_IMPORT_BY_NAME vector. */ 133178828Sobrien if (member == 0) 133278828Sobrien break; 1333104834Sobrien 133478828Sobrien if (member & 0x80000000) 1335104834Sobrien fprintf (file, "\t%04lx\t %4lu <none>", 1336104834Sobrien member, member & 0x7fffffff); 133778828Sobrien else 133878828Sobrien { 133978828Sobrien int ordinal; 134078828Sobrien char *member_name; 134178828Sobrien 134278828Sobrien ordinal = bfd_get_16 (abfd, data + member - adj); 134378828Sobrien member_name = (char *) data + member - adj + 2; 134478828Sobrien fprintf (file, "\t%04lx\t %4d %s", 134578828Sobrien member, ordinal, member_name); 134678828Sobrien } 134778828Sobrien 134878828Sobrien /* If the time stamp is not zero, the import address 1349104834Sobrien table holds actual addresses. */ 135078828Sobrien if (time_stamp != 0 135178828Sobrien && first_thunk != 0 135278828Sobrien && first_thunk != hint_addr) 135378828Sobrien fprintf (file, "\t%04lx", 1354104834Sobrien (long) bfd_get_32 (abfd, ft_data + ft_idx + j)); 135578828Sobrien 135678828Sobrien fprintf (file, "\n"); 135778828Sobrien } 1358218822Sdim#endif 1359104834Sobrien if (ft_allocated) 1360104834Sobrien free (ft_data); 136178828Sobrien } 136278828Sobrien 136378828Sobrien fprintf (file, "\n"); 136478828Sobrien } 136578828Sobrien 136678828Sobrien free (data); 136778828Sobrien 1368130561Sobrien return TRUE; 136978828Sobrien} 137078828Sobrien 1371130561Sobrienstatic bfd_boolean 1372218822Sdimpe_print_edata (bfd * abfd, void * vfile) 137378828Sobrien{ 137478828Sobrien FILE *file = (FILE *) vfile; 137578828Sobrien bfd_byte *data; 137678828Sobrien asection *section; 137778828Sobrien bfd_size_type datasize = 0; 137878828Sobrien bfd_size_type dataoff; 137978828Sobrien bfd_size_type i; 138078828Sobrien bfd_signed_vma adj; 138189857Sobrien struct EDT_type 138289857Sobrien { 1383218822Sdim long export_flags; /* Reserved - should be zero. */ 138478828Sobrien long time_stamp; 138578828Sobrien short major_ver; 138678828Sobrien short minor_ver; 1387218822Sdim bfd_vma name; /* RVA - relative to image base. */ 1388218822Sdim long base; /* Ordinal base. */ 1389218822Sdim unsigned long num_functions;/* Number in the export address table. */ 1390218822Sdim unsigned long num_names; /* Number in the name pointer table. */ 1391218822Sdim bfd_vma eat_addr; /* RVA to the export address table. */ 1392218822Sdim bfd_vma npt_addr; /* RVA to the Export Name Pointer Table. */ 1393218822Sdim bfd_vma ot_addr; /* RVA to the Ordinal Table. */ 139478828Sobrien } edt; 139578828Sobrien 139678828Sobrien pe_data_type *pe = pe_data (abfd); 139778828Sobrien struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; 139878828Sobrien 139978828Sobrien bfd_vma addr; 140078828Sobrien 1401218822Sdim addr = extra->DataDirectory[PE_EXPORT_TABLE].VirtualAddress; 140278828Sobrien 1403218822Sdim if (addr == 0 && extra->DataDirectory[PE_EXPORT_TABLE].Size == 0) 140478828Sobrien { 140578828Sobrien /* Maybe the extra header isn't there. Look for the section. */ 140678828Sobrien section = bfd_get_section_by_name (abfd, ".edata"); 140778828Sobrien if (section == NULL) 1408130561Sobrien return TRUE; 140978828Sobrien 141078828Sobrien addr = section->vma; 1411218822Sdim dataoff = 0; 1412218822Sdim datasize = section->size; 141378828Sobrien if (datasize == 0) 1414130561Sobrien return TRUE; 141578828Sobrien } 141678828Sobrien else 141778828Sobrien { 141878828Sobrien addr += extra->ImageBase; 141989857Sobrien 142078828Sobrien for (section = abfd->sections; section != NULL; section = section->next) 1421218822Sdim if (addr >= section->vma && addr < section->vma + section->size) 1422218822Sdim break; 142389857Sobrien 142478828Sobrien if (section == NULL) 142578828Sobrien { 142678828Sobrien fprintf (file, 142778828Sobrien _("\nThere is an export table, but the section containing it could not be found\n")); 1428130561Sobrien return TRUE; 142978828Sobrien } 1430218822Sdim 1431218822Sdim dataoff = addr - section->vma; 1432218822Sdim datasize = extra->DataDirectory[PE_EXPORT_TABLE].Size; 1433218822Sdim if (datasize > section->size - dataoff) 1434218822Sdim { 1435218822Sdim fprintf (file, 1436218822Sdim _("\nThere is an export table in %s, but it does not fit into that section\n"), 1437218822Sdim section->name); 1438218822Sdim return TRUE; 1439218822Sdim } 144078828Sobrien } 144178828Sobrien 1442326380Semaste /* PR 17512: Handle corrupt PE binaries. */ 1443326380Semaste if (datasize < 36) 1444326380Semaste { 1445326380Semaste fprintf (file, 1446326380Semaste _("\nThere is an export table in %s, but it is too small (%d)\n"), 1447326380Semaste section->name, (int) datasize); 1448326380Semaste return TRUE; 1449326380Semaste } 1450326380Semaste 145178828Sobrien fprintf (file, _("\nThere is an export table in %s at 0x%lx\n"), 145278828Sobrien section->name, (unsigned long) addr); 145378828Sobrien 1454218822Sdim data = bfd_malloc (datasize); 145578828Sobrien if (data == NULL) 1456130561Sobrien return FALSE; 145778828Sobrien 1458218822Sdim if (! bfd_get_section_contents (abfd, section, data, 145989857Sobrien (file_ptr) dataoff, datasize)) 1460130561Sobrien return FALSE; 146178828Sobrien 146278828Sobrien /* Go get Export Directory Table. */ 146378828Sobrien edt.export_flags = bfd_get_32 (abfd, data + 0); 146478828Sobrien edt.time_stamp = bfd_get_32 (abfd, data + 4); 146578828Sobrien edt.major_ver = bfd_get_16 (abfd, data + 8); 146678828Sobrien edt.minor_ver = bfd_get_16 (abfd, data + 10); 146778828Sobrien edt.name = bfd_get_32 (abfd, data + 12); 146878828Sobrien edt.base = bfd_get_32 (abfd, data + 16); 146978828Sobrien edt.num_functions = bfd_get_32 (abfd, data + 20); 147078828Sobrien edt.num_names = bfd_get_32 (abfd, data + 24); 147178828Sobrien edt.eat_addr = bfd_get_32 (abfd, data + 28); 147278828Sobrien edt.npt_addr = bfd_get_32 (abfd, data + 32); 147378828Sobrien edt.ot_addr = bfd_get_32 (abfd, data + 36); 147478828Sobrien 147578828Sobrien adj = section->vma - extra->ImageBase + dataoff; 147678828Sobrien 147789857Sobrien /* Dump the EDT first. */ 147878828Sobrien fprintf (file, 147978828Sobrien _("\nThe Export Tables (interpreted %s section contents)\n\n"), 148078828Sobrien section->name); 148178828Sobrien 148278828Sobrien fprintf (file, 148378828Sobrien _("Export Flags \t\t\t%lx\n"), (unsigned long) edt.export_flags); 148478828Sobrien 148578828Sobrien fprintf (file, 148678828Sobrien _("Time/Date stamp \t\t%lx\n"), (unsigned long) edt.time_stamp); 148778828Sobrien 148878828Sobrien fprintf (file, 148978828Sobrien _("Major/Minor \t\t\t%d/%d\n"), edt.major_ver, edt.minor_ver); 149078828Sobrien 149178828Sobrien fprintf (file, 149278828Sobrien _("Name \t\t\t\t")); 149378828Sobrien fprintf_vma (file, edt.name); 149478828Sobrien fprintf (file, 149578828Sobrien " %s\n", data + edt.name - adj); 149678828Sobrien 149778828Sobrien fprintf (file, 149878828Sobrien _("Ordinal Base \t\t\t%ld\n"), edt.base); 149978828Sobrien 150078828Sobrien fprintf (file, 150178828Sobrien _("Number in:\n")); 150278828Sobrien 150378828Sobrien fprintf (file, 150478828Sobrien _("\tExport Address Table \t\t%08lx\n"), 150578828Sobrien edt.num_functions); 150678828Sobrien 150778828Sobrien fprintf (file, 150878828Sobrien _("\t[Name Pointer/Ordinal] Table\t%08lx\n"), edt.num_names); 150978828Sobrien 151078828Sobrien fprintf (file, 151178828Sobrien _("Table Addresses\n")); 151278828Sobrien 151378828Sobrien fprintf (file, 151478828Sobrien _("\tExport Address Table \t\t")); 151578828Sobrien fprintf_vma (file, edt.eat_addr); 151678828Sobrien fprintf (file, "\n"); 151778828Sobrien 151878828Sobrien fprintf (file, 151978828Sobrien _("\tName Pointer Table \t\t")); 152078828Sobrien fprintf_vma (file, edt.npt_addr); 152178828Sobrien fprintf (file, "\n"); 152278828Sobrien 152378828Sobrien fprintf (file, 152478828Sobrien _("\tOrdinal Table \t\t\t")); 152578828Sobrien fprintf_vma (file, edt.ot_addr); 152678828Sobrien fprintf (file, "\n"); 152778828Sobrien 152878828Sobrien /* The next table to find is the Export Address Table. It's basically 152978828Sobrien a list of pointers that either locate a function in this dll, or 153078828Sobrien forward the call to another dll. Something like: 153189857Sobrien typedef union 153289857Sobrien { 153378828Sobrien long export_rva; 153478828Sobrien long forwarder_rva; 1535218822Sdim } export_address_table_entry; */ 153678828Sobrien 153778828Sobrien fprintf (file, 153878828Sobrien _("\nExport Address Table -- Ordinal Base %ld\n"), 153978828Sobrien edt.base); 154078828Sobrien 154178828Sobrien for (i = 0; i < edt.num_functions; ++i) 154278828Sobrien { 154378828Sobrien bfd_vma eat_member = bfd_get_32 (abfd, 154478828Sobrien data + edt.eat_addr + (i * 4) - adj); 154578828Sobrien if (eat_member == 0) 154678828Sobrien continue; 154778828Sobrien 154878828Sobrien if (eat_member - adj <= datasize) 154978828Sobrien { 155078828Sobrien /* This rva is to a name (forwarding function) in our section. */ 155178828Sobrien /* Should locate a function descriptor. */ 155278828Sobrien fprintf (file, 155378828Sobrien "\t[%4ld] +base[%4ld] %04lx %s -- %s\n", 155478828Sobrien (long) i, 155578828Sobrien (long) (i + edt.base), 155678828Sobrien (unsigned long) eat_member, 155778828Sobrien _("Forwarder RVA"), 155878828Sobrien data + eat_member - adj); 155978828Sobrien } 156078828Sobrien else 156178828Sobrien { 156278828Sobrien /* Should locate a function descriptor in the reldata section. */ 156378828Sobrien fprintf (file, 156478828Sobrien "\t[%4ld] +base[%4ld] %04lx %s\n", 156578828Sobrien (long) i, 156678828Sobrien (long) (i + edt.base), 156778828Sobrien (unsigned long) eat_member, 156878828Sobrien _("Export RVA")); 156978828Sobrien } 157078828Sobrien } 157178828Sobrien 157278828Sobrien /* The Export Name Pointer Table is paired with the Export Ordinal Table. */ 157378828Sobrien /* Dump them in parallel for clarity. */ 157478828Sobrien fprintf (file, 157578828Sobrien _("\n[Ordinal/Name Pointer] Table\n")); 157678828Sobrien 157778828Sobrien for (i = 0; i < edt.num_names; ++i) 157878828Sobrien { 157978828Sobrien bfd_vma name_ptr = bfd_get_32 (abfd, 158078828Sobrien data + 158178828Sobrien edt.npt_addr 158278828Sobrien + (i*4) - adj); 158378828Sobrien 158478828Sobrien char *name = (char *) data + name_ptr - adj; 158578828Sobrien 158678828Sobrien bfd_vma ord = bfd_get_16 (abfd, 158778828Sobrien data + 158878828Sobrien edt.ot_addr 158978828Sobrien + (i*2) - adj); 159078828Sobrien fprintf (file, 159178828Sobrien "\t[%4ld] %s\n", (long) ord, name); 159278828Sobrien } 159378828Sobrien 159478828Sobrien free (data); 159578828Sobrien 1596130561Sobrien return TRUE; 159778828Sobrien} 159878828Sobrien 159978828Sobrien/* This really is architecture dependent. On IA-64, a .pdata entry 160078828Sobrien consists of three dwords containing relative virtual addresses that 160178828Sobrien specify the start and end address of the code range the entry 160278828Sobrien covers and the address of the corresponding unwind info data. */ 160378828Sobrien 1604130561Sobrienstatic bfd_boolean 1605218822Sdimpe_print_pdata (bfd * abfd, void * vfile) 160678828Sobrien{ 1607218822Sdim#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 1608218822Sdim# define PDATA_ROW_SIZE (3 * 8) 160978828Sobrien#else 1610218822Sdim# define PDATA_ROW_SIZE (5 * 4) 161178828Sobrien#endif 161278828Sobrien FILE *file = (FILE *) vfile; 161378828Sobrien bfd_byte *data = 0; 161478828Sobrien asection *section = bfd_get_section_by_name (abfd, ".pdata"); 161578828Sobrien bfd_size_type datasize = 0; 161678828Sobrien bfd_size_type i; 161778828Sobrien bfd_size_type start, stop; 161878828Sobrien int onaline = PDATA_ROW_SIZE; 161978828Sobrien 162078828Sobrien if (section == NULL 162178828Sobrien || coff_section_data (abfd, section) == NULL 162278828Sobrien || pei_section_data (abfd, section) == NULL) 1623130561Sobrien return TRUE; 162478828Sobrien 162578828Sobrien stop = pei_section_data (abfd, section)->virt_size; 162678828Sobrien if ((stop % onaline) != 0) 162778828Sobrien fprintf (file, 162878828Sobrien _("Warning, .pdata section size (%ld) is not a multiple of %d\n"), 162978828Sobrien (long) stop, onaline); 163078828Sobrien 163178828Sobrien fprintf (file, 163278828Sobrien _("\nThe Function Table (interpreted .pdata section contents)\n")); 1633218822Sdim#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 163478828Sobrien fprintf (file, 163578828Sobrien _(" vma:\t\t\tBegin Address End Address Unwind Info\n")); 163678828Sobrien#else 163791041Sobrien fprintf (file, _("\ 163891041Sobrien vma:\t\tBegin End EH EH PrologEnd Exception\n\ 163991041Sobrien \t\tAddress Address Handler Data Address Mask\n")); 164078828Sobrien#endif 164178828Sobrien 1642218822Sdim datasize = section->size; 164389857Sobrien if (datasize == 0) 1644130561Sobrien return TRUE; 164578828Sobrien 1646218822Sdim if (! bfd_malloc_and_get_section (abfd, section, &data)) 1647218822Sdim { 1648218822Sdim if (data != NULL) 1649218822Sdim free (data); 1650218822Sdim return FALSE; 1651218822Sdim } 165278828Sobrien 165378828Sobrien start = 0; 165478828Sobrien 165578828Sobrien for (i = start; i < stop; i += onaline) 165678828Sobrien { 165778828Sobrien bfd_vma begin_addr; 165878828Sobrien bfd_vma end_addr; 165978828Sobrien bfd_vma eh_handler; 166078828Sobrien bfd_vma eh_data; 166178828Sobrien bfd_vma prolog_end_addr; 166278828Sobrien int em_data; 166378828Sobrien 166478828Sobrien if (i + PDATA_ROW_SIZE > stop) 166578828Sobrien break; 166678828Sobrien 166778828Sobrien begin_addr = GET_PDATA_ENTRY (abfd, data + i ); 166878828Sobrien end_addr = GET_PDATA_ENTRY (abfd, data + i + 4); 166978828Sobrien eh_handler = GET_PDATA_ENTRY (abfd, data + i + 8); 167078828Sobrien eh_data = GET_PDATA_ENTRY (abfd, data + i + 12); 167178828Sobrien prolog_end_addr = GET_PDATA_ENTRY (abfd, data + i + 16); 167278828Sobrien 167378828Sobrien if (begin_addr == 0 && end_addr == 0 && eh_handler == 0 167478828Sobrien && eh_data == 0 && prolog_end_addr == 0) 167589857Sobrien /* We are probably into the padding of the section now. */ 167689857Sobrien break; 167778828Sobrien 167878828Sobrien em_data = ((eh_handler & 0x1) << 2) | (prolog_end_addr & 0x3); 167978828Sobrien eh_handler &= ~(bfd_vma) 0x3; 168078828Sobrien prolog_end_addr &= ~(bfd_vma) 0x3; 168178828Sobrien 168278828Sobrien fputc (' ', file); 168378828Sobrien fprintf_vma (file, i + section->vma); fputc ('\t', file); 168478828Sobrien fprintf_vma (file, begin_addr); fputc (' ', file); 168578828Sobrien fprintf_vma (file, end_addr); fputc (' ', file); 168678828Sobrien fprintf_vma (file, eh_handler); 1687218822Sdim#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) 168878828Sobrien fputc (' ', file); 168978828Sobrien fprintf_vma (file, eh_data); fputc (' ', file); 169078828Sobrien fprintf_vma (file, prolog_end_addr); 169178828Sobrien fprintf (file, " %x", em_data); 169278828Sobrien#endif 169378828Sobrien 169478828Sobrien#ifdef POWERPC_LE_PE 169578828Sobrien if (eh_handler == 0 && eh_data != 0) 169678828Sobrien { 169778828Sobrien /* Special bits here, although the meaning may be a little 1698218822Sdim mysterious. The only one I know for sure is 0x03 1699218822Sdim Code Significance 1700218822Sdim 0x00 None 1701218822Sdim 0x01 Register Save Millicode 1702218822Sdim 0x02 Register Restore Millicode 1703218822Sdim 0x03 Glue Code Sequence. */ 170478828Sobrien switch (eh_data) 170578828Sobrien { 170678828Sobrien case 0x01: 170778828Sobrien fprintf (file, _(" Register save millicode")); 170878828Sobrien break; 170978828Sobrien case 0x02: 171078828Sobrien fprintf (file, _(" Register restore millicode")); 171178828Sobrien break; 171278828Sobrien case 0x03: 171378828Sobrien fprintf (file, _(" Glue code sequence")); 171478828Sobrien break; 171578828Sobrien default: 171678828Sobrien break; 171778828Sobrien } 171878828Sobrien } 171978828Sobrien#endif 172078828Sobrien fprintf (file, "\n"); 172178828Sobrien } 172278828Sobrien 172378828Sobrien free (data); 172478828Sobrien 1725130561Sobrien return TRUE; 172678828Sobrien} 172778828Sobrien 172878828Sobrien#define IMAGE_REL_BASED_HIGHADJ 4 172989857Sobrienstatic const char * const tbl[] = 1730218822Sdim{ 1731218822Sdim "ABSOLUTE", 1732218822Sdim "HIGH", 1733218822Sdim "LOW", 1734218822Sdim "HIGHLOW", 1735218822Sdim "HIGHADJ", 1736218822Sdim "MIPS_JMPADDR", 1737218822Sdim "SECTION", 1738218822Sdim "REL32", 1739218822Sdim "RESERVED1", 1740218822Sdim "MIPS_JMPADDR16", 1741218822Sdim "DIR64", 1742218822Sdim "HIGH3ADJ", 1743218822Sdim "UNKNOWN", /* MUST be last. */ 1744218822Sdim}; 174578828Sobrien 1746130561Sobrienstatic bfd_boolean 1747218822Sdimpe_print_reloc (bfd * abfd, void * vfile) 174878828Sobrien{ 174978828Sobrien FILE *file = (FILE *) vfile; 175078828Sobrien bfd_byte *data = 0; 175178828Sobrien asection *section = bfd_get_section_by_name (abfd, ".reloc"); 175289857Sobrien bfd_size_type datasize; 175378828Sobrien bfd_size_type i; 175478828Sobrien bfd_size_type start, stop; 175578828Sobrien 175678828Sobrien if (section == NULL) 1757130561Sobrien return TRUE; 175878828Sobrien 1759218822Sdim if (section->size == 0) 1760130561Sobrien return TRUE; 176178828Sobrien 176278828Sobrien fprintf (file, 176378828Sobrien _("\n\nPE File Base Relocations (interpreted .reloc section contents)\n")); 176478828Sobrien 1765218822Sdim datasize = section->size; 1766218822Sdim if (! bfd_malloc_and_get_section (abfd, section, &data)) 1767218822Sdim { 1768218822Sdim if (data != NULL) 1769218822Sdim free (data); 1770218822Sdim return FALSE; 1771218822Sdim } 177278828Sobrien 177378828Sobrien start = 0; 177478828Sobrien 1775218822Sdim stop = section->size; 177678828Sobrien 177778828Sobrien for (i = start; i < stop;) 177878828Sobrien { 177978828Sobrien int j; 178078828Sobrien bfd_vma virtual_address; 178178828Sobrien long number, size; 178278828Sobrien 178378828Sobrien /* The .reloc section is a sequence of blocks, with a header consisting 178489857Sobrien of two 32 bit quantities, followed by a number of 16 bit entries. */ 178578828Sobrien virtual_address = bfd_get_32 (abfd, data+i); 178678828Sobrien size = bfd_get_32 (abfd, data+i+4); 178778828Sobrien number = (size - 8) / 2; 178878828Sobrien 178978828Sobrien if (size == 0) 179089857Sobrien break; 179178828Sobrien 179278828Sobrien fprintf (file, 179378828Sobrien _("\nVirtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n"), 179478828Sobrien (unsigned long) virtual_address, size, size, number); 179578828Sobrien 179678828Sobrien for (j = 0; j < number; ++j) 179778828Sobrien { 179878828Sobrien unsigned short e = bfd_get_16 (abfd, data + i + 8 + j * 2); 179978828Sobrien unsigned int t = (e & 0xF000) >> 12; 180078828Sobrien int off = e & 0x0FFF; 180178828Sobrien 180278828Sobrien if (t >= sizeof (tbl) / sizeof (tbl[0])) 180378828Sobrien t = (sizeof (tbl) / sizeof (tbl[0])) - 1; 180478828Sobrien 180578828Sobrien fprintf (file, 180678828Sobrien _("\treloc %4d offset %4x [%4lx] %s"), 180778828Sobrien j, off, (long) (off + virtual_address), tbl[t]); 180878828Sobrien 180978828Sobrien /* HIGHADJ takes an argument, - the next record *is* the 181078828Sobrien low 16 bits of addend. */ 181178828Sobrien if (t == IMAGE_REL_BASED_HIGHADJ) 181278828Sobrien { 181378828Sobrien fprintf (file, " (%4x)", 181478828Sobrien ((unsigned int) 181578828Sobrien bfd_get_16 (abfd, data + i + 8 + j * 2 + 2))); 181678828Sobrien j++; 181778828Sobrien } 181878828Sobrien 181978828Sobrien fprintf (file, "\n"); 182078828Sobrien } 182189857Sobrien 182278828Sobrien i += size; 182378828Sobrien } 182478828Sobrien 182578828Sobrien free (data); 182678828Sobrien 1827130561Sobrien return TRUE; 182878828Sobrien} 182978828Sobrien 183078828Sobrien/* Print out the program headers. */ 183178828Sobrien 1832130561Sobrienbfd_boolean 1833218822Sdim_bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile) 183478828Sobrien{ 183578828Sobrien FILE *file = (FILE *) vfile; 183678828Sobrien int j; 183778828Sobrien pe_data_type *pe = pe_data (abfd); 183878828Sobrien struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr; 183978828Sobrien const char *subsystem_name = NULL; 1840218822Sdim const char *name; 184178828Sobrien 184278828Sobrien /* The MS dumpbin program reportedly ands with 0xff0f before 184378828Sobrien printing the characteristics field. Not sure why. No reason to 184478828Sobrien emulate it here. */ 184578828Sobrien fprintf (file, _("\nCharacteristics 0x%x\n"), pe->real_flags); 184678828Sobrien#undef PF 184778828Sobrien#define PF(x, y) if (pe->real_flags & x) { fprintf (file, "\t%s\n", y); } 1848218822Sdim PF (IMAGE_FILE_RELOCS_STRIPPED, "relocations stripped"); 1849218822Sdim PF (IMAGE_FILE_EXECUTABLE_IMAGE, "executable"); 1850218822Sdim PF (IMAGE_FILE_LINE_NUMS_STRIPPED, "line numbers stripped"); 1851218822Sdim PF (IMAGE_FILE_LOCAL_SYMS_STRIPPED, "symbols stripped"); 1852218822Sdim PF (IMAGE_FILE_LARGE_ADDRESS_AWARE, "large address aware"); 1853218822Sdim PF (IMAGE_FILE_BYTES_REVERSED_LO, "little endian"); 1854218822Sdim PF (IMAGE_FILE_32BIT_MACHINE, "32 bit words"); 1855218822Sdim PF (IMAGE_FILE_DEBUG_STRIPPED, "debugging information removed"); 1856218822Sdim PF (IMAGE_FILE_SYSTEM, "system file"); 1857218822Sdim PF (IMAGE_FILE_DLL, "DLL"); 1858218822Sdim PF (IMAGE_FILE_BYTES_REVERSED_HI, "big endian"); 185978828Sobrien#undef PF 186078828Sobrien 186178828Sobrien /* ctime implies '\n'. */ 186285815Sobrien { 186385815Sobrien time_t t = pe->coff.timestamp; 186485815Sobrien fprintf (file, "\nTime/Date\t\t%s", ctime (&t)); 186585815Sobrien } 1866218822Sdim 1867218822Sdim#ifndef IMAGE_NT_OPTIONAL_HDR_MAGIC 1868218822Sdim# define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b 1869218822Sdim#endif 1870218822Sdim#ifndef IMAGE_NT_OPTIONAL_HDR64_MAGIC 1871218822Sdim# define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b 1872218822Sdim#endif 1873218822Sdim#ifndef IMAGE_NT_OPTIONAL_HDRROM_MAGIC 1874218822Sdim# define IMAGE_NT_OPTIONAL_HDRROM_MAGIC 0x107 1875218822Sdim#endif 1876218822Sdim 1877218822Sdim switch (i->Magic) 1878218822Sdim { 1879218822Sdim case IMAGE_NT_OPTIONAL_HDR_MAGIC: 1880218822Sdim name = "PE32"; 1881218822Sdim break; 1882218822Sdim case IMAGE_NT_OPTIONAL_HDR64_MAGIC: 1883218822Sdim name = "PE32+"; 1884218822Sdim break; 1885218822Sdim case IMAGE_NT_OPTIONAL_HDRROM_MAGIC: 1886218822Sdim name = "ROM"; 1887218822Sdim break; 1888218822Sdim default: 1889218822Sdim name = NULL; 1890218822Sdim break; 1891218822Sdim } 1892218822Sdim fprintf (file, "Magic\t\t\t%04x", i->Magic); 1893218822Sdim if (name) 1894218822Sdim fprintf (file, "\t(%s)",name); 1895218822Sdim fprintf (file, "\nMajorLinkerVersion\t%d\n", i->MajorLinkerVersion); 1896218822Sdim fprintf (file, "MinorLinkerVersion\t%d\n", i->MinorLinkerVersion); 1897218822Sdim fprintf (file, "SizeOfCode\t\t%08lx\n", i->SizeOfCode); 1898218822Sdim fprintf (file, "SizeOfInitializedData\t%08lx\n", 1899218822Sdim i->SizeOfInitializedData); 1900218822Sdim fprintf (file, "SizeOfUninitializedData\t%08lx\n", 1901218822Sdim i->SizeOfUninitializedData); 1902218822Sdim fprintf (file, "AddressOfEntryPoint\t"); 1903218822Sdim fprintf_vma (file, i->AddressOfEntryPoint); 1904218822Sdim fprintf (file, "\nBaseOfCode\t\t"); 1905218822Sdim fprintf_vma (file, i->BaseOfCode); 1906218822Sdim#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 1907218822Sdim /* PE32+ does not have BaseOfData member! */ 1908218822Sdim fprintf (file, "\nBaseOfData\t\t"); 1909218822Sdim fprintf_vma (file, i->BaseOfData); 1910218822Sdim#endif 1911218822Sdim 191278828Sobrien fprintf (file, "\nImageBase\t\t"); 191378828Sobrien fprintf_vma (file, i->ImageBase); 191478828Sobrien fprintf (file, "\nSectionAlignment\t"); 191578828Sobrien fprintf_vma (file, i->SectionAlignment); 191678828Sobrien fprintf (file, "\nFileAlignment\t\t"); 191778828Sobrien fprintf_vma (file, i->FileAlignment); 191878828Sobrien fprintf (file, "\nMajorOSystemVersion\t%d\n", i->MajorOperatingSystemVersion); 191978828Sobrien fprintf (file, "MinorOSystemVersion\t%d\n", i->MinorOperatingSystemVersion); 192078828Sobrien fprintf (file, "MajorImageVersion\t%d\n", i->MajorImageVersion); 192178828Sobrien fprintf (file, "MinorImageVersion\t%d\n", i->MinorImageVersion); 192278828Sobrien fprintf (file, "MajorSubsystemVersion\t%d\n", i->MajorSubsystemVersion); 192378828Sobrien fprintf (file, "MinorSubsystemVersion\t%d\n", i->MinorSubsystemVersion); 192478828Sobrien fprintf (file, "Win32Version\t\t%08lx\n", i->Reserved1); 192578828Sobrien fprintf (file, "SizeOfImage\t\t%08lx\n", i->SizeOfImage); 192678828Sobrien fprintf (file, "SizeOfHeaders\t\t%08lx\n", i->SizeOfHeaders); 192778828Sobrien fprintf (file, "CheckSum\t\t%08lx\n", i->CheckSum); 192889857Sobrien 192978828Sobrien switch (i->Subsystem) 193078828Sobrien { 193178828Sobrien case IMAGE_SUBSYSTEM_UNKNOWN: 193278828Sobrien subsystem_name = "unspecified"; 193378828Sobrien break; 193478828Sobrien case IMAGE_SUBSYSTEM_NATIVE: 193578828Sobrien subsystem_name = "NT native"; 193678828Sobrien break; 193778828Sobrien case IMAGE_SUBSYSTEM_WINDOWS_GUI: 193878828Sobrien subsystem_name = "Windows GUI"; 193978828Sobrien break; 194078828Sobrien case IMAGE_SUBSYSTEM_WINDOWS_CUI: 194178828Sobrien subsystem_name = "Windows CUI"; 194278828Sobrien break; 194378828Sobrien case IMAGE_SUBSYSTEM_POSIX_CUI: 194478828Sobrien subsystem_name = "POSIX CUI"; 194578828Sobrien break; 194678828Sobrien case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: 194778828Sobrien subsystem_name = "Wince CUI"; 194878828Sobrien break; 194978828Sobrien case IMAGE_SUBSYSTEM_EFI_APPLICATION: 195078828Sobrien subsystem_name = "EFI application"; 195178828Sobrien break; 195278828Sobrien case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: 195378828Sobrien subsystem_name = "EFI boot service driver"; 195478828Sobrien break; 195578828Sobrien case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: 195678828Sobrien subsystem_name = "EFI runtime driver"; 195778828Sobrien break; 1958218822Sdim // These are from revision 8.0 of the MS PE/COFF spec 1959218822Sdim case IMAGE_SUBSYSTEM_EFI_ROM: 1960218822Sdim subsystem_name = "EFI ROM"; 1961218822Sdim break; 1962218822Sdim case IMAGE_SUBSYSTEM_XBOX: 1963218822Sdim subsystem_name = "XBOX"; 1964218822Sdim break; 1965218822Sdim // Added default case for clarity - subsystem_name is NULL anyway. 1966218822Sdim default: 1967218822Sdim subsystem_name = NULL; 196878828Sobrien } 196989857Sobrien 197078828Sobrien fprintf (file, "Subsystem\t\t%08x", i->Subsystem); 197178828Sobrien if (subsystem_name) 197278828Sobrien fprintf (file, "\t(%s)", subsystem_name); 197378828Sobrien fprintf (file, "\nDllCharacteristics\t%08x\n", i->DllCharacteristics); 197478828Sobrien fprintf (file, "SizeOfStackReserve\t"); 197578828Sobrien fprintf_vma (file, i->SizeOfStackReserve); 197678828Sobrien fprintf (file, "\nSizeOfStackCommit\t"); 197778828Sobrien fprintf_vma (file, i->SizeOfStackCommit); 197878828Sobrien fprintf (file, "\nSizeOfHeapReserve\t"); 197978828Sobrien fprintf_vma (file, i->SizeOfHeapReserve); 198078828Sobrien fprintf (file, "\nSizeOfHeapCommit\t"); 198178828Sobrien fprintf_vma (file, i->SizeOfHeapCommit); 198278828Sobrien fprintf (file, "\nLoaderFlags\t\t%08lx\n", i->LoaderFlags); 198378828Sobrien fprintf (file, "NumberOfRvaAndSizes\t%08lx\n", i->NumberOfRvaAndSizes); 198478828Sobrien 198578828Sobrien fprintf (file, "\nThe Data Directory\n"); 198678828Sobrien for (j = 0; j < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; j++) 198778828Sobrien { 198878828Sobrien fprintf (file, "Entry %1x ", j); 198978828Sobrien fprintf_vma (file, i->DataDirectory[j].VirtualAddress); 199078828Sobrien fprintf (file, " %08lx ", i->DataDirectory[j].Size); 199178828Sobrien fprintf (file, "%s\n", dir_names[j]); 199278828Sobrien } 199378828Sobrien 199478828Sobrien pe_print_idata (abfd, vfile); 199578828Sobrien pe_print_edata (abfd, vfile); 199678828Sobrien pe_print_pdata (abfd, vfile); 199778828Sobrien pe_print_reloc (abfd, vfile); 199878828Sobrien 1999130561Sobrien return TRUE; 200078828Sobrien} 200178828Sobrien 200278828Sobrien/* Copy any private info we understand from the input bfd 200378828Sobrien to the output bfd. */ 200478828Sobrien 2005130561Sobrienbfd_boolean 2006218822Sdim_bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd) 200778828Sobrien{ 200878828Sobrien /* One day we may try to grok other private data. */ 200978828Sobrien if (ibfd->xvec->flavour != bfd_target_coff_flavour 201078828Sobrien || obfd->xvec->flavour != bfd_target_coff_flavour) 2011130561Sobrien return TRUE; 201278828Sobrien 201378828Sobrien pe_data (obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr; 201478828Sobrien pe_data (obfd)->dll = pe_data (ibfd)->dll; 201578828Sobrien 201689857Sobrien /* For strip: if we removed .reloc, we'll make a real mess of things 201778828Sobrien if we don't remove this entry as well. */ 201878828Sobrien if (! pe_data (obfd)->has_reloc_section) 201978828Sobrien { 2020218822Sdim pe_data (obfd)->pe_opthdr.DataDirectory[PE_BASE_RELOCATION_TABLE].VirtualAddress = 0; 2021218822Sdim pe_data (obfd)->pe_opthdr.DataDirectory[PE_BASE_RELOCATION_TABLE].Size = 0; 202278828Sobrien } 2023130561Sobrien return TRUE; 202478828Sobrien} 202578828Sobrien 202678828Sobrien/* Copy private section data. */ 202789857Sobrien 2028130561Sobrienbfd_boolean 2029218822Sdim_bfd_XX_bfd_copy_private_section_data (bfd *ibfd, 2030218822Sdim asection *isec, 2031218822Sdim bfd *obfd, 2032218822Sdim asection *osec) 203378828Sobrien{ 203478828Sobrien if (bfd_get_flavour (ibfd) != bfd_target_coff_flavour 203578828Sobrien || bfd_get_flavour (obfd) != bfd_target_coff_flavour) 2036130561Sobrien return TRUE; 203778828Sobrien 203878828Sobrien if (coff_section_data (ibfd, isec) != NULL 203978828Sobrien && pei_section_data (ibfd, isec) != NULL) 204078828Sobrien { 204178828Sobrien if (coff_section_data (obfd, osec) == NULL) 204278828Sobrien { 204389857Sobrien bfd_size_type amt = sizeof (struct coff_section_tdata); 2044218822Sdim osec->used_by_bfd = bfd_zalloc (obfd, amt); 204578828Sobrien if (osec->used_by_bfd == NULL) 2046130561Sobrien return FALSE; 204778828Sobrien } 204889857Sobrien 204978828Sobrien if (pei_section_data (obfd, osec) == NULL) 205078828Sobrien { 205189857Sobrien bfd_size_type amt = sizeof (struct pei_section_tdata); 2052218822Sdim coff_section_data (obfd, osec)->tdata = bfd_zalloc (obfd, amt); 205378828Sobrien if (coff_section_data (obfd, osec)->tdata == NULL) 2054130561Sobrien return FALSE; 205578828Sobrien } 205689857Sobrien 205778828Sobrien pei_section_data (obfd, osec)->virt_size = 205878828Sobrien pei_section_data (ibfd, isec)->virt_size; 205978828Sobrien pei_section_data (obfd, osec)->pe_flags = 206078828Sobrien pei_section_data (ibfd, isec)->pe_flags; 206178828Sobrien } 206278828Sobrien 2063130561Sobrien return TRUE; 206478828Sobrien} 206578828Sobrien 206678828Sobrienvoid 2067218822Sdim_bfd_XX_get_symbol_info (bfd * abfd, asymbol *symbol, symbol_info *ret) 206878828Sobrien{ 206978828Sobrien coff_get_symbol_info (abfd, symbol, ret); 207078828Sobrien} 207178828Sobrien 207278828Sobrien/* Handle the .idata section and other things that need symbol table 207378828Sobrien access. */ 207478828Sobrien 2075130561Sobrienbfd_boolean 2076218822Sdim_bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo) 207778828Sobrien{ 207878828Sobrien struct coff_link_hash_entry *h1; 207978828Sobrien struct bfd_link_info *info = pfinfo->info; 2080218822Sdim bfd_boolean result = TRUE; 208178828Sobrien 208278828Sobrien /* There are a few fields that need to be filled in now while we 208378828Sobrien have symbol table access. 208478828Sobrien 208578828Sobrien The .idata subsections aren't directly available as sections, but 208678828Sobrien they are in the symbol table, so get them from there. */ 208778828Sobrien 208878828Sobrien /* The import directory. This is the address of .idata$2, with size 208978828Sobrien of .idata$2 + .idata$3. */ 209078828Sobrien h1 = coff_link_hash_lookup (coff_hash_table (info), 2091130561Sobrien ".idata$2", FALSE, FALSE, TRUE); 209278828Sobrien if (h1 != NULL) 209378828Sobrien { 2094218822Sdim /* PR ld/2729: We cannot rely upon all the output sections having been 2095218822Sdim created properly, so check before referencing them. Issue a warning 2096218822Sdim message for any sections tht could not be found. */ 2097218822Sdim if (h1->root.u.def.section != NULL 2098218822Sdim && h1->root.u.def.section->output_section != NULL) 2099218822Sdim pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress = 2100218822Sdim (h1->root.u.def.value 2101218822Sdim + h1->root.u.def.section->output_section->vma 2102218822Sdim + h1->root.u.def.section->output_offset); 2103218822Sdim else 2104218822Sdim { 2105218822Sdim _bfd_error_handler 2106218822Sdim (_("%B: unable to fill in DataDictionary[1] because .idata$2 is missing"), 2107218822Sdim abfd); 2108218822Sdim result = FALSE; 2109218822Sdim } 2110218822Sdim 211178828Sobrien h1 = coff_link_hash_lookup (coff_hash_table (info), 2112130561Sobrien ".idata$4", FALSE, FALSE, TRUE); 2113218822Sdim if (h1 != NULL 2114218822Sdim && h1->root.u.def.section != NULL 2115218822Sdim && h1->root.u.def.section->output_section != NULL) 2116218822Sdim pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].Size = 2117218822Sdim ((h1->root.u.def.value 2118218822Sdim + h1->root.u.def.section->output_section->vma 2119218822Sdim + h1->root.u.def.section->output_offset) 2120218822Sdim - pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress); 2121218822Sdim else 2122218822Sdim { 2123218822Sdim _bfd_error_handler 2124218822Sdim (_("%B: unable to fill in DataDictionary[1] because .idata$4 is missing"), 2125218822Sdim abfd); 2126218822Sdim result = FALSE; 2127218822Sdim } 212878828Sobrien 212978828Sobrien /* The import address table. This is the size/address of 213078828Sobrien .idata$5. */ 213178828Sobrien h1 = coff_link_hash_lookup (coff_hash_table (info), 2132130561Sobrien ".idata$5", FALSE, FALSE, TRUE); 2133218822Sdim if (h1 != NULL 2134218822Sdim && h1->root.u.def.section != NULL 2135218822Sdim && h1->root.u.def.section->output_section != NULL) 2136218822Sdim pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress = 2137218822Sdim (h1->root.u.def.value 2138218822Sdim + h1->root.u.def.section->output_section->vma 2139218822Sdim + h1->root.u.def.section->output_offset); 2140218822Sdim else 2141218822Sdim { 2142218822Sdim _bfd_error_handler 2143218822Sdim (_("%B: unable to fill in DataDictionary[12] because .idata$5 is missing"), 2144218822Sdim abfd); 2145218822Sdim result = FALSE; 2146218822Sdim } 2147218822Sdim 214878828Sobrien h1 = coff_link_hash_lookup (coff_hash_table (info), 2149130561Sobrien ".idata$6", FALSE, FALSE, TRUE); 2150218822Sdim if (h1 != NULL 2151218822Sdim && h1->root.u.def.section != NULL 2152218822Sdim && h1->root.u.def.section->output_section != NULL) 2153218822Sdim pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size = 2154218822Sdim ((h1->root.u.def.value 2155218822Sdim + h1->root.u.def.section->output_section->vma 2156218822Sdim + h1->root.u.def.section->output_offset) 2157218822Sdim - pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress); 2158218822Sdim else 2159218822Sdim { 2160218822Sdim _bfd_error_handler 2161218822Sdim (_("%B: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE (12)] because .idata$6 is missing"), 2162218822Sdim abfd); 2163218822Sdim result = FALSE; 2164218822Sdim } 216578828Sobrien } 216678828Sobrien 2167130561Sobrien h1 = coff_link_hash_lookup (coff_hash_table (info), 2168130561Sobrien "__tls_used", FALSE, FALSE, TRUE); 2169130561Sobrien if (h1 != NULL) 2170130561Sobrien { 2171218822Sdim if (h1->root.u.def.section != NULL 2172218822Sdim && h1->root.u.def.section->output_section != NULL) 2173218822Sdim pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].VirtualAddress = 2174218822Sdim (h1->root.u.def.value 2175218822Sdim + h1->root.u.def.section->output_section->vma 2176218822Sdim + h1->root.u.def.section->output_offset 2177218822Sdim - pe_data (abfd)->pe_opthdr.ImageBase); 2178218822Sdim else 2179218822Sdim { 2180218822Sdim _bfd_error_handler 2181218822Sdim (_("%B: unable to fill in DataDictionary[9] because __tls_used is missing"), 2182218822Sdim abfd); 2183218822Sdim result = FALSE; 2184218822Sdim } 2185218822Sdim 2186218822Sdim pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x18; 2187130561Sobrien } 2188130561Sobrien 218978828Sobrien /* If we couldn't find idata$2, we either have an excessively 219078828Sobrien trivial program or are in DEEP trouble; we have to assume trivial 219178828Sobrien program.... */ 2192218822Sdim return result; 219378828Sobrien} 2194