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