1*a9fa9459Szrj /* Support for the generic parts of PE/PEI; the common executable parts.
2*a9fa9459Szrj    Copyright (C) 1995-2016 Free Software Foundation, Inc.
3*a9fa9459Szrj    Written by Cygnus Solutions.
4*a9fa9459Szrj 
5*a9fa9459Szrj    This file is part of BFD, the Binary File Descriptor library.
6*a9fa9459Szrj 
7*a9fa9459Szrj    This program is free software; you can redistribute it and/or modify
8*a9fa9459Szrj    it under the terms of the GNU General Public License as published by
9*a9fa9459Szrj    the Free Software Foundation; either version 3 of the License, or
10*a9fa9459Szrj    (at your option) any later version.
11*a9fa9459Szrj 
12*a9fa9459Szrj    This program is distributed in the hope that it will be useful,
13*a9fa9459Szrj    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*a9fa9459Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*a9fa9459Szrj    GNU General Public License for more details.
16*a9fa9459Szrj 
17*a9fa9459Szrj    You should have received a copy of the GNU General Public License
18*a9fa9459Szrj    along with this program; if not, write to the Free Software
19*a9fa9459Szrj    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20*a9fa9459Szrj    MA 02110-1301, USA.  */
21*a9fa9459Szrj 
22*a9fa9459Szrj 
23*a9fa9459Szrj /* Most of this hacked by Steve Chamberlain <sac@cygnus.com>.
24*a9fa9459Szrj 
25*a9fa9459Szrj    PE/PEI rearrangement (and code added): Donn Terry
26*a9fa9459Szrj 					  Softway Systems, Inc.  */
27*a9fa9459Szrj 
28*a9fa9459Szrj /* Hey look, some documentation [and in a place you expect to find it]!
29*a9fa9459Szrj 
30*a9fa9459Szrj    The main reference for the pei format is "Microsoft Portable Executable
31*a9fa9459Szrj    and Common Object File Format Specification 4.1".  Get it if you need to
32*a9fa9459Szrj    do some serious hacking on this code.
33*a9fa9459Szrj 
34*a9fa9459Szrj    Another reference:
35*a9fa9459Szrj    "Peering Inside the PE: A Tour of the Win32 Portable Executable
36*a9fa9459Szrj    File Format", MSJ 1994, Volume 9.
37*a9fa9459Szrj 
38*a9fa9459Szrj    The *sole* difference between the pe format and the pei format is that the
39*a9fa9459Szrj    latter has an MSDOS 2.0 .exe header on the front that prints the message
40*a9fa9459Szrj    "This app must be run under Windows." (or some such).
41*a9fa9459Szrj    (FIXME: Whether that statement is *really* true or not is unknown.
42*a9fa9459Szrj    Are there more subtle differences between pe and pei formats?
43*a9fa9459Szrj    For now assume there aren't.  If you find one, then for God sakes
44*a9fa9459Szrj    document it here!)
45*a9fa9459Szrj 
46*a9fa9459Szrj    The Microsoft docs use the word "image" instead of "executable" because
47*a9fa9459Szrj    the former can also refer to a DLL (shared library).  Confusion can arise
48*a9fa9459Szrj    because the `i' in `pei' also refers to "image".  The `pe' format can
49*a9fa9459Szrj    also create images (i.e. executables), it's just that to run on a win32
50*a9fa9459Szrj    system you need to use the pei format.
51*a9fa9459Szrj 
52*a9fa9459Szrj    FIXME: Please add more docs here so the next poor fool that has to hack
53*a9fa9459Szrj    on this code has a chance of getting something accomplished without
54*a9fa9459Szrj    wasting too much time.  */
55*a9fa9459Szrj 
56*a9fa9459Szrj /* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64
57*a9fa9459Szrj    depending on whether we're compiling for straight PE or PE+.  */
58*a9fa9459Szrj #define COFF_WITH_XX
59*a9fa9459Szrj 
60*a9fa9459Szrj #include "sysdep.h"
61*a9fa9459Szrj #include "bfd.h"
62*a9fa9459Szrj #include "libbfd.h"
63*a9fa9459Szrj #include "coff/internal.h"
64*a9fa9459Szrj #include "bfdver.h"
65*a9fa9459Szrj #include "libiberty.h"
66*a9fa9459Szrj #ifdef HAVE_WCHAR_H
67*a9fa9459Szrj #include <wchar.h>
68*a9fa9459Szrj #endif
69*a9fa9459Szrj #ifdef HAVE_WCTYPE_H
70*a9fa9459Szrj #include <wctype.h>
71*a9fa9459Szrj #endif
72*a9fa9459Szrj 
73*a9fa9459Szrj /* NOTE: it's strange to be including an architecture specific header
74*a9fa9459Szrj    in what's supposed to be general (to PE/PEI) code.  However, that's
75*a9fa9459Szrj    where the definitions are, and they don't vary per architecture
76*a9fa9459Szrj    within PE/PEI, so we get them from there.  FIXME: The lack of
77*a9fa9459Szrj    variance is an assumption which may prove to be incorrect if new
78*a9fa9459Szrj    PE/PEI targets are created.  */
79*a9fa9459Szrj #if defined COFF_WITH_pex64
80*a9fa9459Szrj # include "coff/x86_64.h"
81*a9fa9459Szrj #elif defined COFF_WITH_pep
82*a9fa9459Szrj # include "coff/ia64.h"
83*a9fa9459Szrj #else
84*a9fa9459Szrj # include "coff/i386.h"
85*a9fa9459Szrj #endif
86*a9fa9459Szrj 
87*a9fa9459Szrj #include "coff/pe.h"
88*a9fa9459Szrj #include "libcoff.h"
89*a9fa9459Szrj #include "libpei.h"
90*a9fa9459Szrj #include "safe-ctype.h"
91*a9fa9459Szrj 
92*a9fa9459Szrj #if defined COFF_WITH_pep || defined COFF_WITH_pex64
93*a9fa9459Szrj # undef AOUTSZ
94*a9fa9459Szrj # define AOUTSZ		PEPAOUTSZ
95*a9fa9459Szrj # define PEAOUTHDR	PEPAOUTHDR
96*a9fa9459Szrj #endif
97*a9fa9459Szrj 
98*a9fa9459Szrj #define HighBitSet(val)      ((val) & 0x80000000)
99*a9fa9459Szrj #define SetHighBit(val)      ((val) | 0x80000000)
100*a9fa9459Szrj #define WithoutHighBit(val)  ((val) & 0x7fffffff)
101*a9fa9459Szrj 
102*a9fa9459Szrj /* FIXME: This file has various tests of POWERPC_LE_PE.  Those tests
103*a9fa9459Szrj    worked when the code was in peicode.h, but no longer work now that
104*a9fa9459Szrj    the code is in peigen.c.  PowerPC NT is said to be dead.  If
105*a9fa9459Szrj    anybody wants to revive the code, you will have to figure out how
106*a9fa9459Szrj    to handle those issues.  */
107*a9fa9459Szrj 
108*a9fa9459Szrj void
_bfd_XXi_swap_sym_in(bfd * abfd,void * ext1,void * in1)109*a9fa9459Szrj _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1)
110*a9fa9459Szrj {
111*a9fa9459Szrj   SYMENT *ext = (SYMENT *) ext1;
112*a9fa9459Szrj   struct internal_syment *in = (struct internal_syment *) in1;
113*a9fa9459Szrj 
114*a9fa9459Szrj   if (ext->e.e_name[0] == 0)
115*a9fa9459Szrj     {
116*a9fa9459Szrj       in->_n._n_n._n_zeroes = 0;
117*a9fa9459Szrj       in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e.e.e_offset);
118*a9fa9459Szrj     }
119*a9fa9459Szrj   else
120*a9fa9459Szrj     memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN);
121*a9fa9459Szrj 
122*a9fa9459Szrj   in->n_value = H_GET_32 (abfd, ext->e_value);
123*a9fa9459Szrj   in->n_scnum = (short) H_GET_16 (abfd, ext->e_scnum);
124*a9fa9459Szrj 
125*a9fa9459Szrj   if (sizeof (ext->e_type) == 2)
126*a9fa9459Szrj     in->n_type = H_GET_16 (abfd, ext->e_type);
127*a9fa9459Szrj   else
128*a9fa9459Szrj     in->n_type = H_GET_32 (abfd, ext->e_type);
129*a9fa9459Szrj 
130*a9fa9459Szrj   in->n_sclass = H_GET_8 (abfd, ext->e_sclass);
131*a9fa9459Szrj   in->n_numaux = H_GET_8 (abfd, ext->e_numaux);
132*a9fa9459Szrj 
133*a9fa9459Szrj #ifndef STRICT_PE_FORMAT
134*a9fa9459Szrj   /* This is for Gnu-created DLLs.  */
135*a9fa9459Szrj 
136*a9fa9459Szrj   /* The section symbols for the .idata$ sections have class 0x68
137*a9fa9459Szrj      (C_SECTION), which MS documentation indicates is a section
138*a9fa9459Szrj      symbol.  Unfortunately, the value field in the symbol is simply a
139*a9fa9459Szrj      copy of the .idata section's flags rather than something useful.
140*a9fa9459Szrj      When these symbols are encountered, change the value to 0 so that
141*a9fa9459Szrj      they will be handled somewhat correctly in the bfd code.  */
142*a9fa9459Szrj   if (in->n_sclass == C_SECTION)
143*a9fa9459Szrj     {
144*a9fa9459Szrj       char namebuf[SYMNMLEN + 1];
145*a9fa9459Szrj       const char *name = NULL;
146*a9fa9459Szrj 
147*a9fa9459Szrj       in->n_value = 0x0;
148*a9fa9459Szrj 
149*a9fa9459Szrj       /* Create synthetic empty sections as needed.  DJ */
150*a9fa9459Szrj       if (in->n_scnum == 0)
151*a9fa9459Szrj 	{
152*a9fa9459Szrj 	  asection *sec;
153*a9fa9459Szrj 
154*a9fa9459Szrj 	  name = _bfd_coff_internal_syment_name (abfd, in, namebuf);
155*a9fa9459Szrj 	  if (name == NULL)
156*a9fa9459Szrj 	    {
157*a9fa9459Szrj 	      _bfd_error_handler (_("%B: unable to find name for empty section"),
158*a9fa9459Szrj 				  abfd);
159*a9fa9459Szrj 	      bfd_set_error (bfd_error_invalid_target);
160*a9fa9459Szrj 	      return;
161*a9fa9459Szrj 	    }
162*a9fa9459Szrj 
163*a9fa9459Szrj 	  sec = bfd_get_section_by_name (abfd, name);
164*a9fa9459Szrj 	  if (sec != NULL)
165*a9fa9459Szrj 	    in->n_scnum = sec->target_index;
166*a9fa9459Szrj 	}
167*a9fa9459Szrj 
168*a9fa9459Szrj       if (in->n_scnum == 0)
169*a9fa9459Szrj 	{
170*a9fa9459Szrj 	  int unused_section_number = 0;
171*a9fa9459Szrj 	  asection *sec;
172*a9fa9459Szrj 	  flagword flags;
173*a9fa9459Szrj 
174*a9fa9459Szrj 	  for (sec = abfd->sections; sec; sec = sec->next)
175*a9fa9459Szrj 	    if (unused_section_number <= sec->target_index)
176*a9fa9459Szrj 	      unused_section_number = sec->target_index + 1;
177*a9fa9459Szrj 
178*a9fa9459Szrj 	  if (name == namebuf)
179*a9fa9459Szrj 	    {
180*a9fa9459Szrj 	      name = (const char *) bfd_alloc (abfd, strlen (namebuf) + 1);
181*a9fa9459Szrj 	      if (name == NULL)
182*a9fa9459Szrj 		{
183*a9fa9459Szrj 		  _bfd_error_handler (_("%B: out of memory creating name for empty section"),
184*a9fa9459Szrj 				      abfd);
185*a9fa9459Szrj 		  return;
186*a9fa9459Szrj 		}
187*a9fa9459Szrj 	      strcpy ((char *) name, namebuf);
188*a9fa9459Szrj 	    }
189*a9fa9459Szrj 
190*a9fa9459Szrj 	  flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD;
191*a9fa9459Szrj 	  sec = bfd_make_section_anyway_with_flags (abfd, name, flags);
192*a9fa9459Szrj 	  if (sec == NULL)
193*a9fa9459Szrj 	    {
194*a9fa9459Szrj 	      _bfd_error_handler (_("%B: unable to create fake empty section"),
195*a9fa9459Szrj 				  abfd);
196*a9fa9459Szrj 	      return;
197*a9fa9459Szrj 	    }
198*a9fa9459Szrj 
199*a9fa9459Szrj 	  sec->vma = 0;
200*a9fa9459Szrj 	  sec->lma = 0;
201*a9fa9459Szrj 	  sec->size = 0;
202*a9fa9459Szrj 	  sec->filepos = 0;
203*a9fa9459Szrj 	  sec->rel_filepos = 0;
204*a9fa9459Szrj 	  sec->reloc_count = 0;
205*a9fa9459Szrj 	  sec->line_filepos = 0;
206*a9fa9459Szrj 	  sec->lineno_count = 0;
207*a9fa9459Szrj 	  sec->userdata = NULL;
208*a9fa9459Szrj 	  sec->next = NULL;
209*a9fa9459Szrj 	  sec->alignment_power = 2;
210*a9fa9459Szrj 
211*a9fa9459Szrj 	  sec->target_index = unused_section_number;
212*a9fa9459Szrj 
213*a9fa9459Szrj 	  in->n_scnum = unused_section_number;
214*a9fa9459Szrj 	}
215*a9fa9459Szrj       in->n_sclass = C_STAT;
216*a9fa9459Szrj     }
217*a9fa9459Szrj #endif
218*a9fa9459Szrj 
219*a9fa9459Szrj #ifdef coff_swap_sym_in_hook
220*a9fa9459Szrj   /* This won't work in peigen.c, but since it's for PPC PE, it's not
221*a9fa9459Szrj      worth fixing.  */
222*a9fa9459Szrj   coff_swap_sym_in_hook (abfd, ext1, in1);
223*a9fa9459Szrj #endif
224*a9fa9459Szrj }
225*a9fa9459Szrj 
226*a9fa9459Szrj static bfd_boolean
abs_finder(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * data)227*a9fa9459Szrj abs_finder (bfd * abfd ATTRIBUTE_UNUSED, asection * sec, void * data)
228*a9fa9459Szrj {
229*a9fa9459Szrj   bfd_vma abs_val = * (bfd_vma *) data;
230*a9fa9459Szrj 
231*a9fa9459Szrj   return (sec->vma <= abs_val) && ((sec->vma + (1ULL << 32)) > abs_val);
232*a9fa9459Szrj }
233*a9fa9459Szrj 
234*a9fa9459Szrj unsigned int
_bfd_XXi_swap_sym_out(bfd * abfd,void * inp,void * extp)235*a9fa9459Szrj _bfd_XXi_swap_sym_out (bfd * abfd, void * inp, void * extp)
236*a9fa9459Szrj {
237*a9fa9459Szrj   struct internal_syment *in = (struct internal_syment *) inp;
238*a9fa9459Szrj   SYMENT *ext = (SYMENT *) extp;
239*a9fa9459Szrj 
240*a9fa9459Szrj   if (in->_n._n_name[0] == 0)
241*a9fa9459Szrj     {
242*a9fa9459Szrj       H_PUT_32 (abfd, 0, ext->e.e.e_zeroes);
243*a9fa9459Szrj       H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e.e.e_offset);
244*a9fa9459Szrj     }
245*a9fa9459Szrj   else
246*a9fa9459Szrj     memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN);
247*a9fa9459Szrj 
248*a9fa9459Szrj   /* The PE32 and PE32+ formats only use 4 bytes to hold the value of a
249*a9fa9459Szrj      symbol.  This is a problem on 64-bit targets where we can generate
250*a9fa9459Szrj      absolute symbols with values >= 1^32.  We try to work around this
251*a9fa9459Szrj      problem by finding a section whose base address is sufficient to
252*a9fa9459Szrj      reduce the absolute value to < 1^32, and then transforming the
253*a9fa9459Szrj      symbol into a section relative symbol.  This of course is a hack.  */
254*a9fa9459Szrj   if (sizeof (in->n_value) > 4
255*a9fa9459Szrj       /* The strange computation of the shift amount is here in order to
256*a9fa9459Szrj 	 avoid a compile time warning about the comparison always being
257*a9fa9459Szrj 	 false.  It does not matter if this test fails to work as expected
258*a9fa9459Szrj 	 as the worst that can happen is that some absolute symbols are
259*a9fa9459Szrj 	 needlessly converted into section relative symbols.  */
260*a9fa9459Szrj       && in->n_value > ((1ULL << (sizeof (in->n_value) > 4 ? 32 : 31)) - 1)
261*a9fa9459Szrj       && in->n_scnum == N_ABS)
262*a9fa9459Szrj     {
263*a9fa9459Szrj       asection * sec;
264*a9fa9459Szrj 
265*a9fa9459Szrj       sec = bfd_sections_find_if (abfd, abs_finder, & in->n_value);
266*a9fa9459Szrj       if (sec)
267*a9fa9459Szrj 	{
268*a9fa9459Szrj 	  in->n_value -= sec->vma;
269*a9fa9459Szrj 	  in->n_scnum = sec->target_index;
270*a9fa9459Szrj 	}
271*a9fa9459Szrj       /* else: FIXME: The value is outside the range of any section.  This
272*a9fa9459Szrj 	 happens for __image_base__ and __ImageBase and maybe some other
273*a9fa9459Szrj 	 symbols as well.  We should find a way to handle these values.  */
274*a9fa9459Szrj     }
275*a9fa9459Szrj 
276*a9fa9459Szrj   H_PUT_32 (abfd, in->n_value, ext->e_value);
277*a9fa9459Szrj   H_PUT_16 (abfd, in->n_scnum, ext->e_scnum);
278*a9fa9459Szrj 
279*a9fa9459Szrj   if (sizeof (ext->e_type) == 2)
280*a9fa9459Szrj     H_PUT_16 (abfd, in->n_type, ext->e_type);
281*a9fa9459Szrj   else
282*a9fa9459Szrj     H_PUT_32 (abfd, in->n_type, ext->e_type);
283*a9fa9459Szrj 
284*a9fa9459Szrj   H_PUT_8 (abfd, in->n_sclass, ext->e_sclass);
285*a9fa9459Szrj   H_PUT_8 (abfd, in->n_numaux, ext->e_numaux);
286*a9fa9459Szrj 
287*a9fa9459Szrj   return SYMESZ;
288*a9fa9459Szrj }
289*a9fa9459Szrj 
290*a9fa9459Szrj void
_bfd_XXi_swap_aux_in(bfd * abfd,void * ext1,int type,int in_class,int indx ATTRIBUTE_UNUSED,int numaux ATTRIBUTE_UNUSED,void * in1)291*a9fa9459Szrj _bfd_XXi_swap_aux_in (bfd *	abfd,
292*a9fa9459Szrj 		      void *	ext1,
293*a9fa9459Szrj 		      int       type,
294*a9fa9459Szrj 		      int       in_class,
295*a9fa9459Szrj 		      int	indx ATTRIBUTE_UNUSED,
296*a9fa9459Szrj 		      int	numaux ATTRIBUTE_UNUSED,
297*a9fa9459Szrj 		      void * 	in1)
298*a9fa9459Szrj {
299*a9fa9459Szrj   AUXENT *ext = (AUXENT *) ext1;
300*a9fa9459Szrj   union internal_auxent *in = (union internal_auxent *) in1;
301*a9fa9459Szrj 
302*a9fa9459Szrj   /* PR 17521: Make sure that all fields in the aux structure
303*a9fa9459Szrj      are initialised.  */
304*a9fa9459Szrj   memset (in, 0, sizeof * in);
305*a9fa9459Szrj   switch (in_class)
306*a9fa9459Szrj     {
307*a9fa9459Szrj     case C_FILE:
308*a9fa9459Szrj       if (ext->x_file.x_fname[0] == 0)
309*a9fa9459Szrj 	{
310*a9fa9459Szrj 	  in->x_file.x_n.x_zeroes = 0;
311*a9fa9459Szrj 	  in->x_file.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
312*a9fa9459Szrj 	}
313*a9fa9459Szrj       else
314*a9fa9459Szrj 	memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
315*a9fa9459Szrj       return;
316*a9fa9459Szrj 
317*a9fa9459Szrj     case C_STAT:
318*a9fa9459Szrj     case C_LEAFSTAT:
319*a9fa9459Szrj     case C_HIDDEN:
320*a9fa9459Szrj       if (type == T_NULL)
321*a9fa9459Szrj 	{
322*a9fa9459Szrj 	  in->x_scn.x_scnlen = GET_SCN_SCNLEN (abfd, ext);
323*a9fa9459Szrj 	  in->x_scn.x_nreloc = GET_SCN_NRELOC (abfd, ext);
324*a9fa9459Szrj 	  in->x_scn.x_nlinno = GET_SCN_NLINNO (abfd, ext);
325*a9fa9459Szrj 	  in->x_scn.x_checksum = H_GET_32 (abfd, ext->x_scn.x_checksum);
326*a9fa9459Szrj 	  in->x_scn.x_associated = H_GET_16 (abfd, ext->x_scn.x_associated);
327*a9fa9459Szrj 	  in->x_scn.x_comdat = H_GET_8 (abfd, ext->x_scn.x_comdat);
328*a9fa9459Szrj 	  return;
329*a9fa9459Szrj 	}
330*a9fa9459Szrj       break;
331*a9fa9459Szrj     }
332*a9fa9459Szrj 
333*a9fa9459Szrj   in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx);
334*a9fa9459Szrj   in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx);
335*a9fa9459Szrj 
336*a9fa9459Szrj   if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
337*a9fa9459Szrj       || ISTAG (in_class))
338*a9fa9459Szrj     {
339*a9fa9459Szrj       in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext);
340*a9fa9459Szrj       in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext);
341*a9fa9459Szrj     }
342*a9fa9459Szrj   else
343*a9fa9459Szrj     {
344*a9fa9459Szrj       in->x_sym.x_fcnary.x_ary.x_dimen[0] =
345*a9fa9459Szrj 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
346*a9fa9459Szrj       in->x_sym.x_fcnary.x_ary.x_dimen[1] =
347*a9fa9459Szrj 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
348*a9fa9459Szrj       in->x_sym.x_fcnary.x_ary.x_dimen[2] =
349*a9fa9459Szrj 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
350*a9fa9459Szrj       in->x_sym.x_fcnary.x_ary.x_dimen[3] =
351*a9fa9459Szrj 	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
352*a9fa9459Szrj     }
353*a9fa9459Szrj 
354*a9fa9459Szrj   if (ISFCN (type))
355*a9fa9459Szrj     {
356*a9fa9459Szrj       in->x_sym.x_misc.x_fsize = H_GET_32 (abfd, ext->x_sym.x_misc.x_fsize);
357*a9fa9459Szrj     }
358*a9fa9459Szrj   else
359*a9fa9459Szrj     {
360*a9fa9459Szrj       in->x_sym.x_misc.x_lnsz.x_lnno = GET_LNSZ_LNNO (abfd, ext);
361*a9fa9459Szrj       in->x_sym.x_misc.x_lnsz.x_size = GET_LNSZ_SIZE (abfd, ext);
362*a9fa9459Szrj     }
363*a9fa9459Szrj }
364*a9fa9459Szrj 
365*a9fa9459Szrj unsigned int
_bfd_XXi_swap_aux_out(bfd * abfd,void * inp,int type,int in_class,int indx ATTRIBUTE_UNUSED,int numaux ATTRIBUTE_UNUSED,void * extp)366*a9fa9459Szrj _bfd_XXi_swap_aux_out (bfd *  abfd,
367*a9fa9459Szrj 		       void * inp,
368*a9fa9459Szrj 		       int    type,
369*a9fa9459Szrj 		       int    in_class,
370*a9fa9459Szrj 		       int    indx ATTRIBUTE_UNUSED,
371*a9fa9459Szrj 		       int    numaux ATTRIBUTE_UNUSED,
372*a9fa9459Szrj 		       void * extp)
373*a9fa9459Szrj {
374*a9fa9459Szrj   union internal_auxent *in = (union internal_auxent *) inp;
375*a9fa9459Szrj   AUXENT *ext = (AUXENT *) extp;
376*a9fa9459Szrj 
377*a9fa9459Szrj   memset (ext, 0, AUXESZ);
378*a9fa9459Szrj 
379*a9fa9459Szrj   switch (in_class)
380*a9fa9459Szrj     {
381*a9fa9459Szrj     case C_FILE:
382*a9fa9459Szrj       if (in->x_file.x_fname[0] == 0)
383*a9fa9459Szrj 	{
384*a9fa9459Szrj 	  H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes);
385*a9fa9459Szrj 	  H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset);
386*a9fa9459Szrj 	}
387*a9fa9459Szrj       else
388*a9fa9459Szrj 	memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
389*a9fa9459Szrj 
390*a9fa9459Szrj       return AUXESZ;
391*a9fa9459Szrj 
392*a9fa9459Szrj     case C_STAT:
393*a9fa9459Szrj     case C_LEAFSTAT:
394*a9fa9459Szrj     case C_HIDDEN:
395*a9fa9459Szrj       if (type == T_NULL)
396*a9fa9459Szrj 	{
397*a9fa9459Szrj 	  PUT_SCN_SCNLEN (abfd, in->x_scn.x_scnlen, ext);
398*a9fa9459Szrj 	  PUT_SCN_NRELOC (abfd, in->x_scn.x_nreloc, ext);
399*a9fa9459Szrj 	  PUT_SCN_NLINNO (abfd, in->x_scn.x_nlinno, ext);
400*a9fa9459Szrj 	  H_PUT_32 (abfd, in->x_scn.x_checksum, ext->x_scn.x_checksum);
401*a9fa9459Szrj 	  H_PUT_16 (abfd, in->x_scn.x_associated, ext->x_scn.x_associated);
402*a9fa9459Szrj 	  H_PUT_8 (abfd, in->x_scn.x_comdat, ext->x_scn.x_comdat);
403*a9fa9459Szrj 	  return AUXESZ;
404*a9fa9459Szrj 	}
405*a9fa9459Szrj       break;
406*a9fa9459Szrj     }
407*a9fa9459Szrj 
408*a9fa9459Szrj   H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx);
409*a9fa9459Szrj   H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx);
410*a9fa9459Szrj 
411*a9fa9459Szrj   if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
412*a9fa9459Szrj       || ISTAG (in_class))
413*a9fa9459Szrj     {
414*a9fa9459Szrj       PUT_FCN_LNNOPTR (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,  ext);
415*a9fa9459Szrj       PUT_FCN_ENDNDX  (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext);
416*a9fa9459Szrj     }
417*a9fa9459Szrj   else
418*a9fa9459Szrj     {
419*a9fa9459Szrj       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],
420*a9fa9459Szrj 		ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
421*a9fa9459Szrj       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],
422*a9fa9459Szrj 		ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
423*a9fa9459Szrj       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],
424*a9fa9459Szrj 		ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
425*a9fa9459Szrj       H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],
426*a9fa9459Szrj 		ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
427*a9fa9459Szrj     }
428*a9fa9459Szrj 
429*a9fa9459Szrj   if (ISFCN (type))
430*a9fa9459Szrj     H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize);
431*a9fa9459Szrj   else
432*a9fa9459Szrj     {
433*a9fa9459Szrj       PUT_LNSZ_LNNO (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext);
434*a9fa9459Szrj       PUT_LNSZ_SIZE (abfd, in->x_sym.x_misc.x_lnsz.x_size, ext);
435*a9fa9459Szrj     }
436*a9fa9459Szrj 
437*a9fa9459Szrj   return AUXESZ;
438*a9fa9459Szrj }
439*a9fa9459Szrj 
440*a9fa9459Szrj void
_bfd_XXi_swap_lineno_in(bfd * abfd,void * ext1,void * in1)441*a9fa9459Szrj _bfd_XXi_swap_lineno_in (bfd * abfd, void * ext1, void * in1)
442*a9fa9459Szrj {
443*a9fa9459Szrj   LINENO *ext = (LINENO *) ext1;
444*a9fa9459Szrj   struct internal_lineno *in = (struct internal_lineno *) in1;
445*a9fa9459Szrj 
446*a9fa9459Szrj   in->l_addr.l_symndx = H_GET_32 (abfd, ext->l_addr.l_symndx);
447*a9fa9459Szrj   in->l_lnno = GET_LINENO_LNNO (abfd, ext);
448*a9fa9459Szrj }
449*a9fa9459Szrj 
450*a9fa9459Szrj unsigned int
_bfd_XXi_swap_lineno_out(bfd * abfd,void * inp,void * outp)451*a9fa9459Szrj _bfd_XXi_swap_lineno_out (bfd * abfd, void * inp, void * outp)
452*a9fa9459Szrj {
453*a9fa9459Szrj   struct internal_lineno *in = (struct internal_lineno *) inp;
454*a9fa9459Szrj   struct external_lineno *ext = (struct external_lineno *) outp;
455*a9fa9459Szrj   H_PUT_32 (abfd, in->l_addr.l_symndx, ext->l_addr.l_symndx);
456*a9fa9459Szrj 
457*a9fa9459Szrj   PUT_LINENO_LNNO (abfd, in->l_lnno, ext);
458*a9fa9459Szrj   return LINESZ;
459*a9fa9459Szrj }
460*a9fa9459Szrj 
461*a9fa9459Szrj void
_bfd_XXi_swap_aouthdr_in(bfd * abfd,void * aouthdr_ext1,void * aouthdr_int1)462*a9fa9459Szrj _bfd_XXi_swap_aouthdr_in (bfd * abfd,
463*a9fa9459Szrj 			  void * aouthdr_ext1,
464*a9fa9459Szrj 			  void * aouthdr_int1)
465*a9fa9459Szrj {
466*a9fa9459Szrj   PEAOUTHDR * src = (PEAOUTHDR *) aouthdr_ext1;
467*a9fa9459Szrj   AOUTHDR * aouthdr_ext = (AOUTHDR *) aouthdr_ext1;
468*a9fa9459Szrj   struct internal_aouthdr *aouthdr_int
469*a9fa9459Szrj     = (struct internal_aouthdr *) aouthdr_int1;
470*a9fa9459Szrj   struct internal_extra_pe_aouthdr *a = &aouthdr_int->pe;
471*a9fa9459Szrj 
472*a9fa9459Szrj   aouthdr_int->magic = H_GET_16 (abfd, aouthdr_ext->magic);
473*a9fa9459Szrj   aouthdr_int->vstamp = H_GET_16 (abfd, aouthdr_ext->vstamp);
474*a9fa9459Szrj   aouthdr_int->tsize = GET_AOUTHDR_TSIZE (abfd, aouthdr_ext->tsize);
475*a9fa9459Szrj   aouthdr_int->dsize = GET_AOUTHDR_DSIZE (abfd, aouthdr_ext->dsize);
476*a9fa9459Szrj   aouthdr_int->bsize = GET_AOUTHDR_BSIZE (abfd, aouthdr_ext->bsize);
477*a9fa9459Szrj   aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
478*a9fa9459Szrj   aouthdr_int->text_start =
479*a9fa9459Szrj     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
480*a9fa9459Szrj 
481*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
482*a9fa9459Szrj   /* PE32+ does not have data_start member!  */
483*a9fa9459Szrj   aouthdr_int->data_start =
484*a9fa9459Szrj     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
485*a9fa9459Szrj   a->BaseOfData = aouthdr_int->data_start;
486*a9fa9459Szrj #endif
487*a9fa9459Szrj 
488*a9fa9459Szrj   a->Magic = aouthdr_int->magic;
489*a9fa9459Szrj   a->MajorLinkerVersion = H_GET_8 (abfd, aouthdr_ext->vstamp);
490*a9fa9459Szrj   a->MinorLinkerVersion = H_GET_8 (abfd, aouthdr_ext->vstamp + 1);
491*a9fa9459Szrj   a->SizeOfCode = aouthdr_int->tsize ;
492*a9fa9459Szrj   a->SizeOfInitializedData = aouthdr_int->dsize ;
493*a9fa9459Szrj   a->SizeOfUninitializedData = aouthdr_int->bsize ;
494*a9fa9459Szrj   a->AddressOfEntryPoint = aouthdr_int->entry;
495*a9fa9459Szrj   a->BaseOfCode = aouthdr_int->text_start;
496*a9fa9459Szrj   a->ImageBase = GET_OPTHDR_IMAGE_BASE (abfd, src->ImageBase);
497*a9fa9459Szrj   a->SectionAlignment = H_GET_32 (abfd, src->SectionAlignment);
498*a9fa9459Szrj   a->FileAlignment = H_GET_32 (abfd, src->FileAlignment);
499*a9fa9459Szrj   a->MajorOperatingSystemVersion =
500*a9fa9459Szrj     H_GET_16 (abfd, src->MajorOperatingSystemVersion);
501*a9fa9459Szrj   a->MinorOperatingSystemVersion =
502*a9fa9459Szrj     H_GET_16 (abfd, src->MinorOperatingSystemVersion);
503*a9fa9459Szrj   a->MajorImageVersion = H_GET_16 (abfd, src->MajorImageVersion);
504*a9fa9459Szrj   a->MinorImageVersion = H_GET_16 (abfd, src->MinorImageVersion);
505*a9fa9459Szrj   a->MajorSubsystemVersion = H_GET_16 (abfd, src->MajorSubsystemVersion);
506*a9fa9459Szrj   a->MinorSubsystemVersion = H_GET_16 (abfd, src->MinorSubsystemVersion);
507*a9fa9459Szrj   a->Reserved1 = H_GET_32 (abfd, src->Reserved1);
508*a9fa9459Szrj   a->SizeOfImage = H_GET_32 (abfd, src->SizeOfImage);
509*a9fa9459Szrj   a->SizeOfHeaders = H_GET_32 (abfd, src->SizeOfHeaders);
510*a9fa9459Szrj   a->CheckSum = H_GET_32 (abfd, src->CheckSum);
511*a9fa9459Szrj   a->Subsystem = H_GET_16 (abfd, src->Subsystem);
512*a9fa9459Szrj   a->DllCharacteristics = H_GET_16 (abfd, src->DllCharacteristics);
513*a9fa9459Szrj   a->SizeOfStackReserve =
514*a9fa9459Szrj     GET_OPTHDR_SIZE_OF_STACK_RESERVE (abfd, src->SizeOfStackReserve);
515*a9fa9459Szrj   a->SizeOfStackCommit =
516*a9fa9459Szrj     GET_OPTHDR_SIZE_OF_STACK_COMMIT (abfd, src->SizeOfStackCommit);
517*a9fa9459Szrj   a->SizeOfHeapReserve =
518*a9fa9459Szrj     GET_OPTHDR_SIZE_OF_HEAP_RESERVE (abfd, src->SizeOfHeapReserve);
519*a9fa9459Szrj   a->SizeOfHeapCommit =
520*a9fa9459Szrj     GET_OPTHDR_SIZE_OF_HEAP_COMMIT (abfd, src->SizeOfHeapCommit);
521*a9fa9459Szrj   a->LoaderFlags = H_GET_32 (abfd, src->LoaderFlags);
522*a9fa9459Szrj   a->NumberOfRvaAndSizes = H_GET_32 (abfd, src->NumberOfRvaAndSizes);
523*a9fa9459Szrj 
524*a9fa9459Szrj   {
525*a9fa9459Szrj     int idx;
526*a9fa9459Szrj 
527*a9fa9459Szrj     /* PR 17512: Corrupt PE binaries can cause seg-faults.  */
528*a9fa9459Szrj     if (a->NumberOfRvaAndSizes > IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
529*a9fa9459Szrj       {
530*a9fa9459Szrj 	(*_bfd_error_handler)
531*a9fa9459Szrj 	  (_("%B: aout header specifies an invalid number of data-directory entries: %d"),
532*a9fa9459Szrj 	   abfd, a->NumberOfRvaAndSizes);
533*a9fa9459Szrj 	bfd_set_error (bfd_error_bad_value);
534*a9fa9459Szrj 
535*a9fa9459Szrj 	/* Paranoia: If the number is corrupt, then assume that the
536*a9fa9459Szrj 	   actual entries themselves might be corrupt as well.  */
537*a9fa9459Szrj 	a->NumberOfRvaAndSizes = 0;
538*a9fa9459Szrj       }
539*a9fa9459Szrj 
540*a9fa9459Szrj     for (idx = 0; idx < a->NumberOfRvaAndSizes; idx++)
541*a9fa9459Szrj       {
542*a9fa9459Szrj         /* If data directory is empty, rva also should be 0.  */
543*a9fa9459Szrj 	int size =
544*a9fa9459Szrj 	  H_GET_32 (abfd, src->DataDirectory[idx][1]);
545*a9fa9459Szrj 
546*a9fa9459Szrj 	a->DataDirectory[idx].Size = size;
547*a9fa9459Szrj 
548*a9fa9459Szrj 	if (size)
549*a9fa9459Szrj 	  a->DataDirectory[idx].VirtualAddress =
550*a9fa9459Szrj 	    H_GET_32 (abfd, src->DataDirectory[idx][0]);
551*a9fa9459Szrj 	else
552*a9fa9459Szrj 	  a->DataDirectory[idx].VirtualAddress = 0;
553*a9fa9459Szrj       }
554*a9fa9459Szrj 
555*a9fa9459Szrj     while (idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
556*a9fa9459Szrj       {
557*a9fa9459Szrj 	a->DataDirectory[idx].Size = 0;
558*a9fa9459Szrj 	a->DataDirectory[idx].VirtualAddress = 0;
559*a9fa9459Szrj 	idx ++;
560*a9fa9459Szrj       }
561*a9fa9459Szrj   }
562*a9fa9459Szrj 
563*a9fa9459Szrj   if (aouthdr_int->entry)
564*a9fa9459Szrj     {
565*a9fa9459Szrj       aouthdr_int->entry += a->ImageBase;
566*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
567*a9fa9459Szrj       aouthdr_int->entry &= 0xffffffff;
568*a9fa9459Szrj #endif
569*a9fa9459Szrj     }
570*a9fa9459Szrj 
571*a9fa9459Szrj   if (aouthdr_int->tsize)
572*a9fa9459Szrj     {
573*a9fa9459Szrj       aouthdr_int->text_start += a->ImageBase;
574*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
575*a9fa9459Szrj       aouthdr_int->text_start &= 0xffffffff;
576*a9fa9459Szrj #endif
577*a9fa9459Szrj     }
578*a9fa9459Szrj 
579*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
580*a9fa9459Szrj   /* PE32+ does not have data_start member!  */
581*a9fa9459Szrj   if (aouthdr_int->dsize)
582*a9fa9459Szrj     {
583*a9fa9459Szrj       aouthdr_int->data_start += a->ImageBase;
584*a9fa9459Szrj       aouthdr_int->data_start &= 0xffffffff;
585*a9fa9459Szrj     }
586*a9fa9459Szrj #endif
587*a9fa9459Szrj 
588*a9fa9459Szrj #ifdef POWERPC_LE_PE
589*a9fa9459Szrj   /* These three fields are normally set up by ppc_relocate_section.
590*a9fa9459Szrj      In the case of reading a file in, we can pick them up from the
591*a9fa9459Szrj      DataDirectory.  */
592*a9fa9459Szrj   first_thunk_address = a->DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress;
593*a9fa9459Szrj   thunk_size = a->DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size;
594*a9fa9459Szrj   import_table_size = a->DataDirectory[PE_IMPORT_TABLE].Size;
595*a9fa9459Szrj #endif
596*a9fa9459Szrj }
597*a9fa9459Szrj 
598*a9fa9459Szrj /* A support function for below.  */
599*a9fa9459Szrj 
600*a9fa9459Szrj static void
add_data_entry(bfd * abfd,struct internal_extra_pe_aouthdr * aout,int idx,char * name,bfd_vma base)601*a9fa9459Szrj add_data_entry (bfd * abfd,
602*a9fa9459Szrj 		struct internal_extra_pe_aouthdr *aout,
603*a9fa9459Szrj 		int idx,
604*a9fa9459Szrj 		char *name,
605*a9fa9459Szrj 		bfd_vma base)
606*a9fa9459Szrj {
607*a9fa9459Szrj   asection *sec = bfd_get_section_by_name (abfd, name);
608*a9fa9459Szrj 
609*a9fa9459Szrj   /* Add import directory information if it exists.  */
610*a9fa9459Szrj   if ((sec != NULL)
611*a9fa9459Szrj       && (coff_section_data (abfd, sec) != NULL)
612*a9fa9459Szrj       && (pei_section_data (abfd, sec) != NULL))
613*a9fa9459Szrj     {
614*a9fa9459Szrj       /* If data directory is empty, rva also should be 0.  */
615*a9fa9459Szrj       int size = pei_section_data (abfd, sec)->virt_size;
616*a9fa9459Szrj       aout->DataDirectory[idx].Size = size;
617*a9fa9459Szrj 
618*a9fa9459Szrj       if (size)
619*a9fa9459Szrj 	{
620*a9fa9459Szrj 	  aout->DataDirectory[idx].VirtualAddress =
621*a9fa9459Szrj 	    (sec->vma - base) & 0xffffffff;
622*a9fa9459Szrj 	  sec->flags |= SEC_DATA;
623*a9fa9459Szrj 	}
624*a9fa9459Szrj     }
625*a9fa9459Szrj }
626*a9fa9459Szrj 
627*a9fa9459Szrj unsigned int
_bfd_XXi_swap_aouthdr_out(bfd * abfd,void * in,void * out)628*a9fa9459Szrj _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
629*a9fa9459Szrj {
630*a9fa9459Szrj   struct internal_aouthdr *aouthdr_in = (struct internal_aouthdr *) in;
631*a9fa9459Szrj   pe_data_type *pe = pe_data (abfd);
632*a9fa9459Szrj   struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
633*a9fa9459Szrj   PEAOUTHDR *aouthdr_out = (PEAOUTHDR *) out;
634*a9fa9459Szrj   bfd_vma sa, fa, ib;
635*a9fa9459Szrj   IMAGE_DATA_DIRECTORY idata2, idata5, tls;
636*a9fa9459Szrj 
637*a9fa9459Szrj   sa = extra->SectionAlignment;
638*a9fa9459Szrj   fa = extra->FileAlignment;
639*a9fa9459Szrj   ib = extra->ImageBase;
640*a9fa9459Szrj 
641*a9fa9459Szrj   idata2 = pe->pe_opthdr.DataDirectory[PE_IMPORT_TABLE];
642*a9fa9459Szrj   idata5 = pe->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE];
643*a9fa9459Szrj   tls = pe->pe_opthdr.DataDirectory[PE_TLS_TABLE];
644*a9fa9459Szrj 
645*a9fa9459Szrj   if (aouthdr_in->tsize)
646*a9fa9459Szrj     {
647*a9fa9459Szrj       aouthdr_in->text_start -= ib;
648*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
649*a9fa9459Szrj       aouthdr_in->text_start &= 0xffffffff;
650*a9fa9459Szrj #endif
651*a9fa9459Szrj     }
652*a9fa9459Szrj 
653*a9fa9459Szrj   if (aouthdr_in->dsize)
654*a9fa9459Szrj     {
655*a9fa9459Szrj       aouthdr_in->data_start -= ib;
656*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
657*a9fa9459Szrj       aouthdr_in->data_start &= 0xffffffff;
658*a9fa9459Szrj #endif
659*a9fa9459Szrj     }
660*a9fa9459Szrj 
661*a9fa9459Szrj   if (aouthdr_in->entry)
662*a9fa9459Szrj     {
663*a9fa9459Szrj       aouthdr_in->entry -= ib;
664*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
665*a9fa9459Szrj       aouthdr_in->entry &= 0xffffffff;
666*a9fa9459Szrj #endif
667*a9fa9459Szrj     }
668*a9fa9459Szrj 
669*a9fa9459Szrj #define FA(x) (((x) + fa -1 ) & (- fa))
670*a9fa9459Szrj #define SA(x) (((x) + sa -1 ) & (- sa))
671*a9fa9459Szrj 
672*a9fa9459Szrj   /* We like to have the sizes aligned.  */
673*a9fa9459Szrj   aouthdr_in->bsize = FA (aouthdr_in->bsize);
674*a9fa9459Szrj 
675*a9fa9459Szrj   extra->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
676*a9fa9459Szrj 
677*a9fa9459Szrj   add_data_entry (abfd, extra, 0, ".edata", ib);
678*a9fa9459Szrj   add_data_entry (abfd, extra, 2, ".rsrc", ib);
679*a9fa9459Szrj   add_data_entry (abfd, extra, 3, ".pdata", ib);
680*a9fa9459Szrj 
681*a9fa9459Szrj   /* In theory we do not need to call add_data_entry for .idata$2 or
682*a9fa9459Szrj      .idata$5.  It will be done in bfd_coff_final_link where all the
683*a9fa9459Szrj      required information is available.  If however, we are not going
684*a9fa9459Szrj      to perform a final link, eg because we have been invoked by objcopy
685*a9fa9459Szrj      or strip, then we need to make sure that these Data Directory
686*a9fa9459Szrj      entries are initialised properly.
687*a9fa9459Szrj 
688*a9fa9459Szrj      So - we copy the input values into the output values, and then, if
689*a9fa9459Szrj      a final link is going to be performed, it can overwrite them.  */
690*a9fa9459Szrj   extra->DataDirectory[PE_IMPORT_TABLE]  = idata2;
691*a9fa9459Szrj   extra->DataDirectory[PE_IMPORT_ADDRESS_TABLE] = idata5;
692*a9fa9459Szrj   extra->DataDirectory[PE_TLS_TABLE] = tls;
693*a9fa9459Szrj 
694*a9fa9459Szrj   if (extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress == 0)
695*a9fa9459Szrj     /* Until other .idata fixes are made (pending patch), the entry for
696*a9fa9459Szrj        .idata is needed for backwards compatibility.  FIXME.  */
697*a9fa9459Szrj     add_data_entry (abfd, extra, 1, ".idata", ib);
698*a9fa9459Szrj 
699*a9fa9459Szrj   /* For some reason, the virtual size (which is what's set by
700*a9fa9459Szrj      add_data_entry) for .reloc is not the same as the size recorded
701*a9fa9459Szrj      in this slot by MSVC; it doesn't seem to cause problems (so far),
702*a9fa9459Szrj      but since it's the best we've got, use it.  It does do the right
703*a9fa9459Szrj      thing for .pdata.  */
704*a9fa9459Szrj   if (pe->has_reloc_section)
705*a9fa9459Szrj     add_data_entry (abfd, extra, 5, ".reloc", ib);
706*a9fa9459Szrj 
707*a9fa9459Szrj   {
708*a9fa9459Szrj     asection *sec;
709*a9fa9459Szrj     bfd_vma hsize = 0;
710*a9fa9459Szrj     bfd_vma dsize = 0;
711*a9fa9459Szrj     bfd_vma isize = 0;
712*a9fa9459Szrj     bfd_vma tsize = 0;
713*a9fa9459Szrj 
714*a9fa9459Szrj     for (sec = abfd->sections; sec; sec = sec->next)
715*a9fa9459Szrj       {
716*a9fa9459Szrj 	int rounded = FA (sec->size);
717*a9fa9459Szrj 
718*a9fa9459Szrj 	/* The first non-zero section filepos is the header size.
719*a9fa9459Szrj 	   Sections without contents will have a filepos of 0.  */
720*a9fa9459Szrj 	if (hsize == 0)
721*a9fa9459Szrj 	  hsize = sec->filepos;
722*a9fa9459Szrj 	if (sec->flags & SEC_DATA)
723*a9fa9459Szrj 	  dsize += rounded;
724*a9fa9459Szrj 	if (sec->flags & SEC_CODE)
725*a9fa9459Szrj 	  tsize += rounded;
726*a9fa9459Szrj 	/* The image size is the total VIRTUAL size (which is what is
727*a9fa9459Szrj 	   in the virt_size field).  Files have been seen (from MSVC
728*a9fa9459Szrj 	   5.0 link.exe) where the file size of the .data segment is
729*a9fa9459Szrj 	   quite small compared to the virtual size.  Without this
730*a9fa9459Szrj 	   fix, strip munges the file.
731*a9fa9459Szrj 
732*a9fa9459Szrj 	   FIXME: We need to handle holes between sections, which may
733*a9fa9459Szrj 	   happpen when we covert from another format.  We just use
734*a9fa9459Szrj 	   the virtual address and virtual size of the last section
735*a9fa9459Szrj 	   for the image size.  */
736*a9fa9459Szrj 	if (coff_section_data (abfd, sec) != NULL
737*a9fa9459Szrj 	    && pei_section_data (abfd, sec) != NULL)
738*a9fa9459Szrj 	  isize = (sec->vma - extra->ImageBase
739*a9fa9459Szrj 		   + SA (FA (pei_section_data (abfd, sec)->virt_size)));
740*a9fa9459Szrj       }
741*a9fa9459Szrj 
742*a9fa9459Szrj     aouthdr_in->dsize = dsize;
743*a9fa9459Szrj     aouthdr_in->tsize = tsize;
744*a9fa9459Szrj     extra->SizeOfHeaders = hsize;
745*a9fa9459Szrj     extra->SizeOfImage = isize;
746*a9fa9459Szrj   }
747*a9fa9459Szrj 
748*a9fa9459Szrj   H_PUT_16 (abfd, aouthdr_in->magic, aouthdr_out->standard.magic);
749*a9fa9459Szrj 
750*a9fa9459Szrj /* e.g. 219510000 is linker version 2.19  */
751*a9fa9459Szrj #define LINKER_VERSION ((short) (BFD_VERSION / 1000000))
752*a9fa9459Szrj 
753*a9fa9459Szrj   /* This piece of magic sets the "linker version" field to
754*a9fa9459Szrj      LINKER_VERSION.  */
755*a9fa9459Szrj   H_PUT_16 (abfd, (LINKER_VERSION / 100 + (LINKER_VERSION % 100) * 256),
756*a9fa9459Szrj 	    aouthdr_out->standard.vstamp);
757*a9fa9459Szrj 
758*a9fa9459Szrj   PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, aouthdr_out->standard.tsize);
759*a9fa9459Szrj   PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, aouthdr_out->standard.dsize);
760*a9fa9459Szrj   PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, aouthdr_out->standard.bsize);
761*a9fa9459Szrj   PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, aouthdr_out->standard.entry);
762*a9fa9459Szrj   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
763*a9fa9459Szrj 			  aouthdr_out->standard.text_start);
764*a9fa9459Szrj 
765*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
766*a9fa9459Szrj   /* PE32+ does not have data_start member!  */
767*a9fa9459Szrj   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
768*a9fa9459Szrj 			  aouthdr_out->standard.data_start);
769*a9fa9459Szrj #endif
770*a9fa9459Szrj 
771*a9fa9459Szrj   PUT_OPTHDR_IMAGE_BASE (abfd, extra->ImageBase, aouthdr_out->ImageBase);
772*a9fa9459Szrj   H_PUT_32 (abfd, extra->SectionAlignment, aouthdr_out->SectionAlignment);
773*a9fa9459Szrj   H_PUT_32 (abfd, extra->FileAlignment, aouthdr_out->FileAlignment);
774*a9fa9459Szrj   H_PUT_16 (abfd, extra->MajorOperatingSystemVersion,
775*a9fa9459Szrj 	    aouthdr_out->MajorOperatingSystemVersion);
776*a9fa9459Szrj   H_PUT_16 (abfd, extra->MinorOperatingSystemVersion,
777*a9fa9459Szrj 	    aouthdr_out->MinorOperatingSystemVersion);
778*a9fa9459Szrj   H_PUT_16 (abfd, extra->MajorImageVersion, aouthdr_out->MajorImageVersion);
779*a9fa9459Szrj   H_PUT_16 (abfd, extra->MinorImageVersion, aouthdr_out->MinorImageVersion);
780*a9fa9459Szrj   H_PUT_16 (abfd, extra->MajorSubsystemVersion,
781*a9fa9459Szrj 	    aouthdr_out->MajorSubsystemVersion);
782*a9fa9459Szrj   H_PUT_16 (abfd, extra->MinorSubsystemVersion,
783*a9fa9459Szrj 	    aouthdr_out->MinorSubsystemVersion);
784*a9fa9459Szrj   H_PUT_32 (abfd, extra->Reserved1, aouthdr_out->Reserved1);
785*a9fa9459Szrj   H_PUT_32 (abfd, extra->SizeOfImage, aouthdr_out->SizeOfImage);
786*a9fa9459Szrj   H_PUT_32 (abfd, extra->SizeOfHeaders, aouthdr_out->SizeOfHeaders);
787*a9fa9459Szrj   H_PUT_32 (abfd, extra->CheckSum, aouthdr_out->CheckSum);
788*a9fa9459Szrj   H_PUT_16 (abfd, extra->Subsystem, aouthdr_out->Subsystem);
789*a9fa9459Szrj   H_PUT_16 (abfd, extra->DllCharacteristics, aouthdr_out->DllCharacteristics);
790*a9fa9459Szrj   PUT_OPTHDR_SIZE_OF_STACK_RESERVE (abfd, extra->SizeOfStackReserve,
791*a9fa9459Szrj 				    aouthdr_out->SizeOfStackReserve);
792*a9fa9459Szrj   PUT_OPTHDR_SIZE_OF_STACK_COMMIT (abfd, extra->SizeOfStackCommit,
793*a9fa9459Szrj 				   aouthdr_out->SizeOfStackCommit);
794*a9fa9459Szrj   PUT_OPTHDR_SIZE_OF_HEAP_RESERVE (abfd, extra->SizeOfHeapReserve,
795*a9fa9459Szrj 				   aouthdr_out->SizeOfHeapReserve);
796*a9fa9459Szrj   PUT_OPTHDR_SIZE_OF_HEAP_COMMIT (abfd, extra->SizeOfHeapCommit,
797*a9fa9459Szrj 				  aouthdr_out->SizeOfHeapCommit);
798*a9fa9459Szrj   H_PUT_32 (abfd, extra->LoaderFlags, aouthdr_out->LoaderFlags);
799*a9fa9459Szrj   H_PUT_32 (abfd, extra->NumberOfRvaAndSizes,
800*a9fa9459Szrj 	    aouthdr_out->NumberOfRvaAndSizes);
801*a9fa9459Szrj   {
802*a9fa9459Szrj     int idx;
803*a9fa9459Szrj 
804*a9fa9459Szrj     for (idx = 0; idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; idx++)
805*a9fa9459Szrj       {
806*a9fa9459Szrj 	H_PUT_32 (abfd, extra->DataDirectory[idx].VirtualAddress,
807*a9fa9459Szrj 		  aouthdr_out->DataDirectory[idx][0]);
808*a9fa9459Szrj 	H_PUT_32 (abfd, extra->DataDirectory[idx].Size,
809*a9fa9459Szrj 		  aouthdr_out->DataDirectory[idx][1]);
810*a9fa9459Szrj       }
811*a9fa9459Szrj   }
812*a9fa9459Szrj 
813*a9fa9459Szrj   return AOUTSZ;
814*a9fa9459Szrj }
815*a9fa9459Szrj 
816*a9fa9459Szrj unsigned int
_bfd_XXi_only_swap_filehdr_out(bfd * abfd,void * in,void * out)817*a9fa9459Szrj _bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out)
818*a9fa9459Szrj {
819*a9fa9459Szrj   int idx;
820*a9fa9459Szrj   struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in;
821*a9fa9459Szrj   struct external_PEI_filehdr *filehdr_out = (struct external_PEI_filehdr *) out;
822*a9fa9459Szrj 
823*a9fa9459Szrj   if (pe_data (abfd)->has_reloc_section
824*a9fa9459Szrj       || pe_data (abfd)->dont_strip_reloc)
825*a9fa9459Szrj     filehdr_in->f_flags &= ~F_RELFLG;
826*a9fa9459Szrj 
827*a9fa9459Szrj   if (pe_data (abfd)->dll)
828*a9fa9459Szrj     filehdr_in->f_flags |= F_DLL;
829*a9fa9459Szrj 
830*a9fa9459Szrj   filehdr_in->pe.e_magic    = DOSMAGIC;
831*a9fa9459Szrj   filehdr_in->pe.e_cblp     = 0x90;
832*a9fa9459Szrj   filehdr_in->pe.e_cp       = 0x3;
833*a9fa9459Szrj   filehdr_in->pe.e_crlc     = 0x0;
834*a9fa9459Szrj   filehdr_in->pe.e_cparhdr  = 0x4;
835*a9fa9459Szrj   filehdr_in->pe.e_minalloc = 0x0;
836*a9fa9459Szrj   filehdr_in->pe.e_maxalloc = 0xffff;
837*a9fa9459Szrj   filehdr_in->pe.e_ss       = 0x0;
838*a9fa9459Szrj   filehdr_in->pe.e_sp       = 0xb8;
839*a9fa9459Szrj   filehdr_in->pe.e_csum     = 0x0;
840*a9fa9459Szrj   filehdr_in->pe.e_ip       = 0x0;
841*a9fa9459Szrj   filehdr_in->pe.e_cs       = 0x0;
842*a9fa9459Szrj   filehdr_in->pe.e_lfarlc   = 0x40;
843*a9fa9459Szrj   filehdr_in->pe.e_ovno     = 0x0;
844*a9fa9459Szrj 
845*a9fa9459Szrj   for (idx = 0; idx < 4; idx++)
846*a9fa9459Szrj     filehdr_in->pe.e_res[idx] = 0x0;
847*a9fa9459Szrj 
848*a9fa9459Szrj   filehdr_in->pe.e_oemid   = 0x0;
849*a9fa9459Szrj   filehdr_in->pe.e_oeminfo = 0x0;
850*a9fa9459Szrj 
851*a9fa9459Szrj   for (idx = 0; idx < 10; idx++)
852*a9fa9459Szrj     filehdr_in->pe.e_res2[idx] = 0x0;
853*a9fa9459Szrj 
854*a9fa9459Szrj   filehdr_in->pe.e_lfanew = 0x80;
855*a9fa9459Szrj 
856*a9fa9459Szrj   /* This next collection of data are mostly just characters.  It
857*a9fa9459Szrj      appears to be constant within the headers put on NT exes.  */
858*a9fa9459Szrj   filehdr_in->pe.dos_message[0]  = 0x0eba1f0e;
859*a9fa9459Szrj   filehdr_in->pe.dos_message[1]  = 0xcd09b400;
860*a9fa9459Szrj   filehdr_in->pe.dos_message[2]  = 0x4c01b821;
861*a9fa9459Szrj   filehdr_in->pe.dos_message[3]  = 0x685421cd;
862*a9fa9459Szrj   filehdr_in->pe.dos_message[4]  = 0x70207369;
863*a9fa9459Szrj   filehdr_in->pe.dos_message[5]  = 0x72676f72;
864*a9fa9459Szrj   filehdr_in->pe.dos_message[6]  = 0x63206d61;
865*a9fa9459Szrj   filehdr_in->pe.dos_message[7]  = 0x6f6e6e61;
866*a9fa9459Szrj   filehdr_in->pe.dos_message[8]  = 0x65622074;
867*a9fa9459Szrj   filehdr_in->pe.dos_message[9]  = 0x6e757220;
868*a9fa9459Szrj   filehdr_in->pe.dos_message[10] = 0x206e6920;
869*a9fa9459Szrj   filehdr_in->pe.dos_message[11] = 0x20534f44;
870*a9fa9459Szrj   filehdr_in->pe.dos_message[12] = 0x65646f6d;
871*a9fa9459Szrj   filehdr_in->pe.dos_message[13] = 0x0a0d0d2e;
872*a9fa9459Szrj   filehdr_in->pe.dos_message[14] = 0x24;
873*a9fa9459Szrj   filehdr_in->pe.dos_message[15] = 0x0;
874*a9fa9459Szrj   filehdr_in->pe.nt_signature = NT_SIGNATURE;
875*a9fa9459Szrj 
876*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic);
877*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns);
878*a9fa9459Szrj 
879*a9fa9459Szrj   /* Only use a real timestamp if the option was chosen.  */
880*a9fa9459Szrj   if ((pe_data (abfd)->insert_timestamp))
881*a9fa9459Szrj     H_PUT_32 (abfd, time (0), filehdr_out->f_timdat);
882*a9fa9459Szrj 
883*a9fa9459Szrj   PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr,
884*a9fa9459Szrj 		      filehdr_out->f_symptr);
885*a9fa9459Szrj   H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms);
886*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr);
887*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->f_flags, filehdr_out->f_flags);
888*a9fa9459Szrj 
889*a9fa9459Szrj   /* Put in extra dos header stuff.  This data remains essentially
890*a9fa9459Szrj      constant, it just has to be tacked on to the beginning of all exes
891*a9fa9459Szrj      for NT.  */
892*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_magic, filehdr_out->e_magic);
893*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_cblp, filehdr_out->e_cblp);
894*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_cp, filehdr_out->e_cp);
895*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_crlc, filehdr_out->e_crlc);
896*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_cparhdr, filehdr_out->e_cparhdr);
897*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_minalloc, filehdr_out->e_minalloc);
898*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_maxalloc, filehdr_out->e_maxalloc);
899*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_ss, filehdr_out->e_ss);
900*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_sp, filehdr_out->e_sp);
901*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_csum, filehdr_out->e_csum);
902*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_ip, filehdr_out->e_ip);
903*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_cs, filehdr_out->e_cs);
904*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_lfarlc, filehdr_out->e_lfarlc);
905*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_ovno, filehdr_out->e_ovno);
906*a9fa9459Szrj 
907*a9fa9459Szrj   for (idx = 0; idx < 4; idx++)
908*a9fa9459Szrj     H_PUT_16 (abfd, filehdr_in->pe.e_res[idx], filehdr_out->e_res[idx]);
909*a9fa9459Szrj 
910*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_oemid, filehdr_out->e_oemid);
911*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->pe.e_oeminfo, filehdr_out->e_oeminfo);
912*a9fa9459Szrj 
913*a9fa9459Szrj   for (idx = 0; idx < 10; idx++)
914*a9fa9459Szrj     H_PUT_16 (abfd, filehdr_in->pe.e_res2[idx], filehdr_out->e_res2[idx]);
915*a9fa9459Szrj 
916*a9fa9459Szrj   H_PUT_32 (abfd, filehdr_in->pe.e_lfanew, filehdr_out->e_lfanew);
917*a9fa9459Szrj 
918*a9fa9459Szrj   for (idx = 0; idx < 16; idx++)
919*a9fa9459Szrj     H_PUT_32 (abfd, filehdr_in->pe.dos_message[idx],
920*a9fa9459Szrj 	      filehdr_out->dos_message[idx]);
921*a9fa9459Szrj 
922*a9fa9459Szrj   /* Also put in the NT signature.  */
923*a9fa9459Szrj   H_PUT_32 (abfd, filehdr_in->pe.nt_signature, filehdr_out->nt_signature);
924*a9fa9459Szrj 
925*a9fa9459Szrj   return FILHSZ;
926*a9fa9459Szrj }
927*a9fa9459Szrj 
928*a9fa9459Szrj unsigned int
_bfd_XX_only_swap_filehdr_out(bfd * abfd,void * in,void * out)929*a9fa9459Szrj _bfd_XX_only_swap_filehdr_out (bfd * abfd, void * in, void * out)
930*a9fa9459Szrj {
931*a9fa9459Szrj   struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in;
932*a9fa9459Szrj   FILHDR *filehdr_out = (FILHDR *) out;
933*a9fa9459Szrj 
934*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic);
935*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns);
936*a9fa9459Szrj   H_PUT_32 (abfd, filehdr_in->f_timdat, filehdr_out->f_timdat);
937*a9fa9459Szrj   PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, filehdr_out->f_symptr);
938*a9fa9459Szrj   H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms);
939*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr);
940*a9fa9459Szrj   H_PUT_16 (abfd, filehdr_in->f_flags, filehdr_out->f_flags);
941*a9fa9459Szrj 
942*a9fa9459Szrj   return FILHSZ;
943*a9fa9459Szrj }
944*a9fa9459Szrj 
945*a9fa9459Szrj unsigned int
_bfd_XXi_swap_scnhdr_out(bfd * abfd,void * in,void * out)946*a9fa9459Szrj _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
947*a9fa9459Szrj {
948*a9fa9459Szrj   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
949*a9fa9459Szrj   SCNHDR *scnhdr_ext = (SCNHDR *) out;
950*a9fa9459Szrj   unsigned int ret = SCNHSZ;
951*a9fa9459Szrj   bfd_vma ps;
952*a9fa9459Szrj   bfd_vma ss;
953*a9fa9459Szrj 
954*a9fa9459Szrj   memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
955*a9fa9459Szrj 
956*a9fa9459Szrj   PUT_SCNHDR_VADDR (abfd,
957*a9fa9459Szrj 		    ((scnhdr_int->s_vaddr
958*a9fa9459Szrj 		      - pe_data (abfd)->pe_opthdr.ImageBase)
959*a9fa9459Szrj 		     & 0xffffffff),
960*a9fa9459Szrj 		    scnhdr_ext->s_vaddr);
961*a9fa9459Szrj 
962*a9fa9459Szrj   /* NT wants the size data to be rounded up to the next
963*a9fa9459Szrj      NT_FILE_ALIGNMENT, but zero if it has no content (as in .bss,
964*a9fa9459Szrj      sometimes).  */
965*a9fa9459Szrj   if ((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0)
966*a9fa9459Szrj     {
967*a9fa9459Szrj       if (bfd_pei_p (abfd))
968*a9fa9459Szrj 	{
969*a9fa9459Szrj 	  ps = scnhdr_int->s_size;
970*a9fa9459Szrj 	  ss = 0;
971*a9fa9459Szrj 	}
972*a9fa9459Szrj       else
973*a9fa9459Szrj        {
974*a9fa9459Szrj          ps = 0;
975*a9fa9459Szrj          ss = scnhdr_int->s_size;
976*a9fa9459Szrj        }
977*a9fa9459Szrj     }
978*a9fa9459Szrj   else
979*a9fa9459Szrj     {
980*a9fa9459Szrj       if (bfd_pei_p (abfd))
981*a9fa9459Szrj 	ps = scnhdr_int->s_paddr;
982*a9fa9459Szrj       else
983*a9fa9459Szrj 	ps = 0;
984*a9fa9459Szrj 
985*a9fa9459Szrj       ss = scnhdr_int->s_size;
986*a9fa9459Szrj     }
987*a9fa9459Szrj 
988*a9fa9459Szrj   PUT_SCNHDR_SIZE (abfd, ss,
989*a9fa9459Szrj 		   scnhdr_ext->s_size);
990*a9fa9459Szrj 
991*a9fa9459Szrj   /* s_paddr in PE is really the virtual size.  */
992*a9fa9459Szrj   PUT_SCNHDR_PADDR (abfd, ps, scnhdr_ext->s_paddr);
993*a9fa9459Szrj 
994*a9fa9459Szrj   PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr,
995*a9fa9459Szrj 		     scnhdr_ext->s_scnptr);
996*a9fa9459Szrj   PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr,
997*a9fa9459Szrj 		     scnhdr_ext->s_relptr);
998*a9fa9459Szrj   PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr,
999*a9fa9459Szrj 		      scnhdr_ext->s_lnnoptr);
1000*a9fa9459Szrj 
1001*a9fa9459Szrj   {
1002*a9fa9459Szrj     /* Extra flags must be set when dealing with PE.  All sections should also
1003*a9fa9459Szrj        have the IMAGE_SCN_MEM_READ (0x40000000) flag set.  In addition, the
1004*a9fa9459Szrj        .text section must have IMAGE_SCN_MEM_EXECUTE (0x20000000) and the data
1005*a9fa9459Szrj        sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set
1006*a9fa9459Szrj        (this is especially important when dealing with the .idata section since
1007*a9fa9459Szrj        the addresses for routines from .dlls must be overwritten).  If .reloc
1008*a9fa9459Szrj        section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE
1009*a9fa9459Szrj        (0x02000000).  Also, the resource data should also be read and
1010*a9fa9459Szrj        writable.  */
1011*a9fa9459Szrj 
1012*a9fa9459Szrj     /* FIXME: Alignment is also encoded in this field, at least on PPC and
1013*a9fa9459Szrj        ARM-WINCE.  Although - how do we get the original alignment field
1014*a9fa9459Szrj        back ?  */
1015*a9fa9459Szrj 
1016*a9fa9459Szrj     typedef struct
1017*a9fa9459Szrj     {
1018*a9fa9459Szrj       const char * 	section_name;
1019*a9fa9459Szrj       unsigned long	must_have;
1020*a9fa9459Szrj     }
1021*a9fa9459Szrj     pe_required_section_flags;
1022*a9fa9459Szrj 
1023*a9fa9459Szrj     pe_required_section_flags known_sections [] =
1024*a9fa9459Szrj       {
1025*a9fa9459Szrj 	{ ".arch",  IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_ALIGN_8BYTES },
1026*a9fa9459Szrj 	{ ".bss",   IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE },
1027*a9fa9459Szrj 	{ ".data",  IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE },
1028*a9fa9459Szrj 	{ ".edata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
1029*a9fa9459Szrj 	{ ".idata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE },
1030*a9fa9459Szrj 	{ ".pdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
1031*a9fa9459Szrj 	{ ".rdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
1032*a9fa9459Szrj 	{ ".reloc", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE },
1033*a9fa9459Szrj 	{ ".rsrc",  IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE },
1034*a9fa9459Szrj 	{ ".text" , IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE },
1035*a9fa9459Szrj 	{ ".tls",   IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE },
1036*a9fa9459Szrj 	{ ".xdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
1037*a9fa9459Szrj 	{ NULL, 0}
1038*a9fa9459Szrj       };
1039*a9fa9459Szrj 
1040*a9fa9459Szrj     pe_required_section_flags * p;
1041*a9fa9459Szrj 
1042*a9fa9459Szrj     /* We have defaulted to adding the IMAGE_SCN_MEM_WRITE flag, but now
1043*a9fa9459Szrj        we know exactly what this specific section wants so we remove it
1044*a9fa9459Szrj        and then allow the must_have field to add it back in if necessary.
1045*a9fa9459Szrj        However, we don't remove IMAGE_SCN_MEM_WRITE flag from .text if the
1046*a9fa9459Szrj        default WP_TEXT file flag has been cleared.  WP_TEXT may be cleared
1047*a9fa9459Szrj        by ld --enable-auto-import (if auto-import is actually needed),
1048*a9fa9459Szrj        by ld --omagic, or by obcopy --writable-text.  */
1049*a9fa9459Szrj 
1050*a9fa9459Szrj     for (p = known_sections; p->section_name; p++)
1051*a9fa9459Szrj       if (strcmp (scnhdr_int->s_name, p->section_name) == 0)
1052*a9fa9459Szrj 	{
1053*a9fa9459Szrj 	  if (strcmp (scnhdr_int->s_name, ".text")
1054*a9fa9459Szrj 	      || (bfd_get_file_flags (abfd) & WP_TEXT))
1055*a9fa9459Szrj 	    scnhdr_int->s_flags &= ~IMAGE_SCN_MEM_WRITE;
1056*a9fa9459Szrj 	  scnhdr_int->s_flags |= p->must_have;
1057*a9fa9459Szrj 	  break;
1058*a9fa9459Szrj 	}
1059*a9fa9459Szrj 
1060*a9fa9459Szrj     H_PUT_32 (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
1061*a9fa9459Szrj   }
1062*a9fa9459Szrj 
1063*a9fa9459Szrj   if (coff_data (abfd)->link_info
1064*a9fa9459Szrj       && ! bfd_link_relocatable (coff_data (abfd)->link_info)
1065*a9fa9459Szrj       && ! bfd_link_pic (coff_data (abfd)->link_info)
1066*a9fa9459Szrj       && strcmp (scnhdr_int->s_name, ".text") == 0)
1067*a9fa9459Szrj     {
1068*a9fa9459Szrj       /* By inference from looking at MS output, the 32 bit field
1069*a9fa9459Szrj 	 which is the combination of the number_of_relocs and
1070*a9fa9459Szrj 	 number_of_linenos is used for the line number count in
1071*a9fa9459Szrj 	 executables.  A 16-bit field won't do for cc1.  The MS
1072*a9fa9459Szrj 	 document says that the number of relocs is zero for
1073*a9fa9459Szrj 	 executables, but the 17-th bit has been observed to be there.
1074*a9fa9459Szrj 	 Overflow is not an issue: a 4G-line program will overflow a
1075*a9fa9459Szrj 	 bunch of other fields long before this!  */
1076*a9fa9459Szrj       H_PUT_16 (abfd, (scnhdr_int->s_nlnno & 0xffff), scnhdr_ext->s_nlnno);
1077*a9fa9459Szrj       H_PUT_16 (abfd, (scnhdr_int->s_nlnno >> 16), scnhdr_ext->s_nreloc);
1078*a9fa9459Szrj     }
1079*a9fa9459Szrj   else
1080*a9fa9459Szrj     {
1081*a9fa9459Szrj       if (scnhdr_int->s_nlnno <= 0xffff)
1082*a9fa9459Szrj 	H_PUT_16 (abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno);
1083*a9fa9459Szrj       else
1084*a9fa9459Szrj 	{
1085*a9fa9459Szrj 	  (*_bfd_error_handler) (_("%s: line number overflow: 0x%lx > 0xffff"),
1086*a9fa9459Szrj 				 bfd_get_filename (abfd),
1087*a9fa9459Szrj 				 scnhdr_int->s_nlnno);
1088*a9fa9459Szrj 	  bfd_set_error (bfd_error_file_truncated);
1089*a9fa9459Szrj 	  H_PUT_16 (abfd, 0xffff, scnhdr_ext->s_nlnno);
1090*a9fa9459Szrj 	  ret = 0;
1091*a9fa9459Szrj 	}
1092*a9fa9459Szrj 
1093*a9fa9459Szrj       /* Although we could encode 0xffff relocs here, we do not, to be
1094*a9fa9459Szrj          consistent with other parts of bfd. Also it lets us warn, as
1095*a9fa9459Szrj          we should never see 0xffff here w/o having the overflow flag
1096*a9fa9459Szrj          set.  */
1097*a9fa9459Szrj       if (scnhdr_int->s_nreloc < 0xffff)
1098*a9fa9459Szrj 	H_PUT_16 (abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc);
1099*a9fa9459Szrj       else
1100*a9fa9459Szrj 	{
1101*a9fa9459Szrj 	  /* PE can deal with large #s of relocs, but not here.  */
1102*a9fa9459Szrj 	  H_PUT_16 (abfd, 0xffff, scnhdr_ext->s_nreloc);
1103*a9fa9459Szrj 	  scnhdr_int->s_flags |= IMAGE_SCN_LNK_NRELOC_OVFL;
1104*a9fa9459Szrj 	  H_PUT_32 (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
1105*a9fa9459Szrj 	}
1106*a9fa9459Szrj     }
1107*a9fa9459Szrj   return ret;
1108*a9fa9459Szrj }
1109*a9fa9459Szrj 
1110*a9fa9459Szrj void
_bfd_XXi_swap_debugdir_in(bfd * abfd,void * ext1,void * in1)1111*a9fa9459Szrj _bfd_XXi_swap_debugdir_in (bfd * abfd, void * ext1, void * in1)
1112*a9fa9459Szrj {
1113*a9fa9459Szrj   struct external_IMAGE_DEBUG_DIRECTORY *ext = (struct external_IMAGE_DEBUG_DIRECTORY *) ext1;
1114*a9fa9459Szrj   struct internal_IMAGE_DEBUG_DIRECTORY *in = (struct internal_IMAGE_DEBUG_DIRECTORY *) in1;
1115*a9fa9459Szrj 
1116*a9fa9459Szrj   in->Characteristics = H_GET_32(abfd, ext->Characteristics);
1117*a9fa9459Szrj   in->TimeDateStamp = H_GET_32(abfd, ext->TimeDateStamp);
1118*a9fa9459Szrj   in->MajorVersion = H_GET_16(abfd, ext->MajorVersion);
1119*a9fa9459Szrj   in->MinorVersion = H_GET_16(abfd, ext->MinorVersion);
1120*a9fa9459Szrj   in->Type = H_GET_32(abfd, ext->Type);
1121*a9fa9459Szrj   in->SizeOfData = H_GET_32(abfd, ext->SizeOfData);
1122*a9fa9459Szrj   in->AddressOfRawData = H_GET_32(abfd, ext->AddressOfRawData);
1123*a9fa9459Szrj   in->PointerToRawData = H_GET_32(abfd, ext->PointerToRawData);
1124*a9fa9459Szrj }
1125*a9fa9459Szrj 
1126*a9fa9459Szrj unsigned int
_bfd_XXi_swap_debugdir_out(bfd * abfd,void * inp,void * extp)1127*a9fa9459Szrj _bfd_XXi_swap_debugdir_out (bfd * abfd, void * inp, void * extp)
1128*a9fa9459Szrj {
1129*a9fa9459Szrj   struct external_IMAGE_DEBUG_DIRECTORY *ext = (struct external_IMAGE_DEBUG_DIRECTORY *) extp;
1130*a9fa9459Szrj   struct internal_IMAGE_DEBUG_DIRECTORY *in = (struct internal_IMAGE_DEBUG_DIRECTORY *) inp;
1131*a9fa9459Szrj 
1132*a9fa9459Szrj   H_PUT_32(abfd, in->Characteristics, ext->Characteristics);
1133*a9fa9459Szrj   H_PUT_32(abfd, in->TimeDateStamp, ext->TimeDateStamp);
1134*a9fa9459Szrj   H_PUT_16(abfd, in->MajorVersion, ext->MajorVersion);
1135*a9fa9459Szrj   H_PUT_16(abfd, in->MinorVersion, ext->MinorVersion);
1136*a9fa9459Szrj   H_PUT_32(abfd, in->Type, ext->Type);
1137*a9fa9459Szrj   H_PUT_32(abfd, in->SizeOfData, ext->SizeOfData);
1138*a9fa9459Szrj   H_PUT_32(abfd, in->AddressOfRawData, ext->AddressOfRawData);
1139*a9fa9459Szrj   H_PUT_32(abfd, in->PointerToRawData, ext->PointerToRawData);
1140*a9fa9459Szrj 
1141*a9fa9459Szrj   return sizeof (struct external_IMAGE_DEBUG_DIRECTORY);
1142*a9fa9459Szrj }
1143*a9fa9459Szrj 
1144*a9fa9459Szrj CODEVIEW_INFO *
_bfd_XXi_slurp_codeview_record(bfd * abfd,file_ptr where,unsigned long length,CODEVIEW_INFO * cvinfo)1145*a9fa9459Szrj _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo)
1146*a9fa9459Szrj {
1147*a9fa9459Szrj   char buffer[256+1];
1148*a9fa9459Szrj 
1149*a9fa9459Szrj   if (bfd_seek (abfd, where, SEEK_SET) != 0)
1150*a9fa9459Szrj     return NULL;
1151*a9fa9459Szrj 
1152*a9fa9459Szrj   if (bfd_bread (buffer, 256, abfd) < 4)
1153*a9fa9459Szrj     return NULL;
1154*a9fa9459Szrj 
1155*a9fa9459Szrj   /* Ensure null termination of filename.  */
1156*a9fa9459Szrj   buffer[256] = '\0';
1157*a9fa9459Szrj 
1158*a9fa9459Szrj   cvinfo->CVSignature = H_GET_32 (abfd, buffer);
1159*a9fa9459Szrj   cvinfo->Age = 0;
1160*a9fa9459Szrj 
1161*a9fa9459Szrj   if ((cvinfo->CVSignature == CVINFO_PDB70_CVSIGNATURE)
1162*a9fa9459Szrj       && (length > sizeof (CV_INFO_PDB70)))
1163*a9fa9459Szrj     {
1164*a9fa9459Szrj       CV_INFO_PDB70 *cvinfo70 = (CV_INFO_PDB70 *)(buffer);
1165*a9fa9459Szrj 
1166*a9fa9459Szrj       cvinfo->Age = H_GET_32(abfd, cvinfo70->Age);
1167*a9fa9459Szrj 
1168*a9fa9459Szrj       /* A GUID consists of 4,2,2 byte values in little-endian order, followed
1169*a9fa9459Szrj          by 8 single bytes.  Byte swap them so we can conveniently treat the GUID
1170*a9fa9459Szrj          as 16 bytes in big-endian order.  */
1171*a9fa9459Szrj       bfd_putb32 (bfd_getl32 (cvinfo70->Signature), cvinfo->Signature);
1172*a9fa9459Szrj       bfd_putb16 (bfd_getl16 (&(cvinfo70->Signature[4])), &(cvinfo->Signature[4]));
1173*a9fa9459Szrj       bfd_putb16 (bfd_getl16 (&(cvinfo70->Signature[6])), &(cvinfo->Signature[6]));
1174*a9fa9459Szrj       memcpy (&(cvinfo->Signature[8]), &(cvinfo70->Signature[8]), 8);
1175*a9fa9459Szrj 
1176*a9fa9459Szrj       cvinfo->SignatureLength = CV_INFO_SIGNATURE_LENGTH;
1177*a9fa9459Szrj       // cvinfo->PdbFileName = cvinfo70->PdbFileName;
1178*a9fa9459Szrj 
1179*a9fa9459Szrj       return cvinfo;
1180*a9fa9459Szrj     }
1181*a9fa9459Szrj   else if ((cvinfo->CVSignature == CVINFO_PDB20_CVSIGNATURE)
1182*a9fa9459Szrj            && (length > sizeof (CV_INFO_PDB20)))
1183*a9fa9459Szrj     {
1184*a9fa9459Szrj       CV_INFO_PDB20 *cvinfo20 = (CV_INFO_PDB20 *)(buffer);
1185*a9fa9459Szrj       cvinfo->Age = H_GET_32(abfd, cvinfo20->Age);
1186*a9fa9459Szrj       memcpy (cvinfo->Signature, cvinfo20->Signature, 4);
1187*a9fa9459Szrj       cvinfo->SignatureLength = 4;
1188*a9fa9459Szrj       // cvinfo->PdbFileName = cvinfo20->PdbFileName;
1189*a9fa9459Szrj 
1190*a9fa9459Szrj       return cvinfo;
1191*a9fa9459Szrj     }
1192*a9fa9459Szrj 
1193*a9fa9459Szrj   return NULL;
1194*a9fa9459Szrj }
1195*a9fa9459Szrj 
1196*a9fa9459Szrj unsigned int
_bfd_XXi_write_codeview_record(bfd * abfd,file_ptr where,CODEVIEW_INFO * cvinfo)1197*a9fa9459Szrj _bfd_XXi_write_codeview_record (bfd * abfd, file_ptr where, CODEVIEW_INFO *cvinfo)
1198*a9fa9459Szrj {
1199*a9fa9459Szrj   const bfd_size_type size = sizeof (CV_INFO_PDB70) + 1;
1200*a9fa9459Szrj   bfd_size_type written;
1201*a9fa9459Szrj   CV_INFO_PDB70 *cvinfo70;
1202*a9fa9459Szrj   char * buffer;
1203*a9fa9459Szrj 
1204*a9fa9459Szrj   if (bfd_seek (abfd, where, SEEK_SET) != 0)
1205*a9fa9459Szrj     return 0;
1206*a9fa9459Szrj 
1207*a9fa9459Szrj   buffer = xmalloc (size);
1208*a9fa9459Szrj   cvinfo70 = (CV_INFO_PDB70 *) buffer;
1209*a9fa9459Szrj   H_PUT_32 (abfd, CVINFO_PDB70_CVSIGNATURE, cvinfo70->CvSignature);
1210*a9fa9459Szrj 
1211*a9fa9459Szrj   /* Byte swap the GUID from 16 bytes in big-endian order to 4,2,2 byte values
1212*a9fa9459Szrj      in little-endian order, followed by 8 single bytes.  */
1213*a9fa9459Szrj   bfd_putl32 (bfd_getb32 (cvinfo->Signature), cvinfo70->Signature);
1214*a9fa9459Szrj   bfd_putl16 (bfd_getb16 (&(cvinfo->Signature[4])), &(cvinfo70->Signature[4]));
1215*a9fa9459Szrj   bfd_putl16 (bfd_getb16 (&(cvinfo->Signature[6])), &(cvinfo70->Signature[6]));
1216*a9fa9459Szrj   memcpy (&(cvinfo70->Signature[8]), &(cvinfo->Signature[8]), 8);
1217*a9fa9459Szrj 
1218*a9fa9459Szrj   H_PUT_32 (abfd, cvinfo->Age, cvinfo70->Age);
1219*a9fa9459Szrj   cvinfo70->PdbFileName[0] = '\0';
1220*a9fa9459Szrj 
1221*a9fa9459Szrj   written = bfd_bwrite (buffer, size, abfd);
1222*a9fa9459Szrj 
1223*a9fa9459Szrj   free (buffer);
1224*a9fa9459Szrj 
1225*a9fa9459Szrj   return written == size ? size : 0;
1226*a9fa9459Szrj }
1227*a9fa9459Szrj 
1228*a9fa9459Szrj static char * dir_names[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] =
1229*a9fa9459Szrj {
1230*a9fa9459Szrj   N_("Export Directory [.edata (or where ever we found it)]"),
1231*a9fa9459Szrj   N_("Import Directory [parts of .idata]"),
1232*a9fa9459Szrj   N_("Resource Directory [.rsrc]"),
1233*a9fa9459Szrj   N_("Exception Directory [.pdata]"),
1234*a9fa9459Szrj   N_("Security Directory"),
1235*a9fa9459Szrj   N_("Base Relocation Directory [.reloc]"),
1236*a9fa9459Szrj   N_("Debug Directory"),
1237*a9fa9459Szrj   N_("Description Directory"),
1238*a9fa9459Szrj   N_("Special Directory"),
1239*a9fa9459Szrj   N_("Thread Storage Directory [.tls]"),
1240*a9fa9459Szrj   N_("Load Configuration Directory"),
1241*a9fa9459Szrj   N_("Bound Import Directory"),
1242*a9fa9459Szrj   N_("Import Address Table Directory"),
1243*a9fa9459Szrj   N_("Delay Import Directory"),
1244*a9fa9459Szrj   N_("CLR Runtime Header"),
1245*a9fa9459Szrj   N_("Reserved")
1246*a9fa9459Szrj };
1247*a9fa9459Szrj 
1248*a9fa9459Szrj #ifdef POWERPC_LE_PE
1249*a9fa9459Szrj /* The code for the PPC really falls in the "architecture dependent"
1250*a9fa9459Szrj    category.  However, it's not clear that anyone will ever care, so
1251*a9fa9459Szrj    we're ignoring the issue for now; if/when PPC matters, some of this
1252*a9fa9459Szrj    may need to go into peicode.h, or arguments passed to enable the
1253*a9fa9459Szrj    PPC- specific code.  */
1254*a9fa9459Szrj #endif
1255*a9fa9459Szrj 
1256*a9fa9459Szrj static bfd_boolean
pe_print_idata(bfd * abfd,void * vfile)1257*a9fa9459Szrj pe_print_idata (bfd * abfd, void * vfile)
1258*a9fa9459Szrj {
1259*a9fa9459Szrj   FILE *file = (FILE *) vfile;
1260*a9fa9459Szrj   bfd_byte *data;
1261*a9fa9459Szrj   asection *section;
1262*a9fa9459Szrj   bfd_signed_vma adj;
1263*a9fa9459Szrj 
1264*a9fa9459Szrj #ifdef POWERPC_LE_PE
1265*a9fa9459Szrj   asection *rel_section = bfd_get_section_by_name (abfd, ".reldata");
1266*a9fa9459Szrj #endif
1267*a9fa9459Szrj 
1268*a9fa9459Szrj   bfd_size_type datasize = 0;
1269*a9fa9459Szrj   bfd_size_type dataoff;
1270*a9fa9459Szrj   bfd_size_type i;
1271*a9fa9459Szrj   int onaline = 20;
1272*a9fa9459Szrj 
1273*a9fa9459Szrj   pe_data_type *pe = pe_data (abfd);
1274*a9fa9459Szrj   struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
1275*a9fa9459Szrj 
1276*a9fa9459Szrj   bfd_vma addr;
1277*a9fa9459Szrj 
1278*a9fa9459Szrj   addr = extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress;
1279*a9fa9459Szrj 
1280*a9fa9459Szrj   if (addr == 0 && extra->DataDirectory[PE_IMPORT_TABLE].Size == 0)
1281*a9fa9459Szrj     {
1282*a9fa9459Szrj       /* Maybe the extra header isn't there.  Look for the section.  */
1283*a9fa9459Szrj       section = bfd_get_section_by_name (abfd, ".idata");
1284*a9fa9459Szrj       if (section == NULL)
1285*a9fa9459Szrj 	return TRUE;
1286*a9fa9459Szrj 
1287*a9fa9459Szrj       addr = section->vma;
1288*a9fa9459Szrj       datasize = section->size;
1289*a9fa9459Szrj       if (datasize == 0)
1290*a9fa9459Szrj 	return TRUE;
1291*a9fa9459Szrj     }
1292*a9fa9459Szrj   else
1293*a9fa9459Szrj     {
1294*a9fa9459Szrj       addr += extra->ImageBase;
1295*a9fa9459Szrj       for (section = abfd->sections; section != NULL; section = section->next)
1296*a9fa9459Szrj 	{
1297*a9fa9459Szrj 	  datasize = section->size;
1298*a9fa9459Szrj 	  if (addr >= section->vma && addr < section->vma + datasize)
1299*a9fa9459Szrj 	    break;
1300*a9fa9459Szrj 	}
1301*a9fa9459Szrj 
1302*a9fa9459Szrj       if (section == NULL)
1303*a9fa9459Szrj 	{
1304*a9fa9459Szrj 	  fprintf (file,
1305*a9fa9459Szrj 		   _("\nThere is an import table, but the section containing it could not be found\n"));
1306*a9fa9459Szrj 	  return TRUE;
1307*a9fa9459Szrj 	}
1308*a9fa9459Szrj       else if (!(section->flags & SEC_HAS_CONTENTS))
1309*a9fa9459Szrj         {
1310*a9fa9459Szrj 	  fprintf (file,
1311*a9fa9459Szrj 		   _("\nThere is an import table in %s, but that section has no contents\n"),
1312*a9fa9459Szrj 		   section->name);
1313*a9fa9459Szrj 	  return TRUE;
1314*a9fa9459Szrj         }
1315*a9fa9459Szrj     }
1316*a9fa9459Szrj 
1317*a9fa9459Szrj   fprintf (file, _("\nThere is an import table in %s at 0x%lx\n"),
1318*a9fa9459Szrj 	   section->name, (unsigned long) addr);
1319*a9fa9459Szrj 
1320*a9fa9459Szrj   dataoff = addr - section->vma;
1321*a9fa9459Szrj 
1322*a9fa9459Szrj #ifdef POWERPC_LE_PE
1323*a9fa9459Szrj   if (rel_section != 0 && rel_section->size != 0)
1324*a9fa9459Szrj     {
1325*a9fa9459Szrj       /* The toc address can be found by taking the starting address,
1326*a9fa9459Szrj 	 which on the PPC locates a function descriptor. The
1327*a9fa9459Szrj 	 descriptor consists of the function code starting address
1328*a9fa9459Szrj 	 followed by the address of the toc. The starting address we
1329*a9fa9459Szrj 	 get from the bfd, and the descriptor is supposed to be in the
1330*a9fa9459Szrj 	 .reldata section.  */
1331*a9fa9459Szrj 
1332*a9fa9459Szrj       bfd_vma loadable_toc_address;
1333*a9fa9459Szrj       bfd_vma toc_address;
1334*a9fa9459Szrj       bfd_vma start_address;
1335*a9fa9459Szrj       bfd_byte *data;
1336*a9fa9459Szrj       bfd_vma offset;
1337*a9fa9459Szrj 
1338*a9fa9459Szrj       if (!bfd_malloc_and_get_section (abfd, rel_section, &data))
1339*a9fa9459Szrj 	{
1340*a9fa9459Szrj 	  if (data != NULL)
1341*a9fa9459Szrj 	    free (data);
1342*a9fa9459Szrj 	  return FALSE;
1343*a9fa9459Szrj 	}
1344*a9fa9459Szrj 
1345*a9fa9459Szrj       offset = abfd->start_address - rel_section->vma;
1346*a9fa9459Szrj 
1347*a9fa9459Szrj       if (offset >= rel_section->size || offset + 8 > rel_section->size)
1348*a9fa9459Szrj         {
1349*a9fa9459Szrj           if (data != NULL)
1350*a9fa9459Szrj             free (data);
1351*a9fa9459Szrj           return FALSE;
1352*a9fa9459Szrj         }
1353*a9fa9459Szrj 
1354*a9fa9459Szrj       start_address = bfd_get_32 (abfd, data + offset);
1355*a9fa9459Szrj       loadable_toc_address = bfd_get_32 (abfd, data + offset + 4);
1356*a9fa9459Szrj       toc_address = loadable_toc_address - 32768;
1357*a9fa9459Szrj 
1358*a9fa9459Szrj       fprintf (file,
1359*a9fa9459Szrj 	       _("\nFunction descriptor located at the start address: %04lx\n"),
1360*a9fa9459Szrj 	       (unsigned long int) (abfd->start_address));
1361*a9fa9459Szrj       fprintf (file,
1362*a9fa9459Szrj 	       _("\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n"),
1363*a9fa9459Szrj 	       start_address, loadable_toc_address, toc_address);
1364*a9fa9459Szrj       if (data != NULL)
1365*a9fa9459Szrj 	free (data);
1366*a9fa9459Szrj     }
1367*a9fa9459Szrj   else
1368*a9fa9459Szrj     {
1369*a9fa9459Szrj       fprintf (file,
1370*a9fa9459Szrj 	       _("\nNo reldata section! Function descriptor not decoded.\n"));
1371*a9fa9459Szrj     }
1372*a9fa9459Szrj #endif
1373*a9fa9459Szrj 
1374*a9fa9459Szrj   fprintf (file,
1375*a9fa9459Szrj 	   _("\nThe Import Tables (interpreted %s section contents)\n"),
1376*a9fa9459Szrj 	   section->name);
1377*a9fa9459Szrj   fprintf (file,
1378*a9fa9459Szrj 	   _("\
1379*a9fa9459Szrj  vma:            Hint    Time      Forward  DLL       First\n\
1380*a9fa9459Szrj                  Table   Stamp     Chain    Name      Thunk\n"));
1381*a9fa9459Szrj 
1382*a9fa9459Szrj   /* Read the whole section.  Some of the fields might be before dataoff.  */
1383*a9fa9459Szrj   if (!bfd_malloc_and_get_section (abfd, section, &data))
1384*a9fa9459Szrj     {
1385*a9fa9459Szrj       if (data != NULL)
1386*a9fa9459Szrj 	free (data);
1387*a9fa9459Szrj       return FALSE;
1388*a9fa9459Szrj     }
1389*a9fa9459Szrj 
1390*a9fa9459Szrj   adj = section->vma - extra->ImageBase;
1391*a9fa9459Szrj 
1392*a9fa9459Szrj   /* Print all image import descriptors.  */
1393*a9fa9459Szrj   for (i = dataoff; i + onaline <= datasize; i += onaline)
1394*a9fa9459Szrj     {
1395*a9fa9459Szrj       bfd_vma hint_addr;
1396*a9fa9459Szrj       bfd_vma time_stamp;
1397*a9fa9459Szrj       bfd_vma forward_chain;
1398*a9fa9459Szrj       bfd_vma dll_name;
1399*a9fa9459Szrj       bfd_vma first_thunk;
1400*a9fa9459Szrj       int idx = 0;
1401*a9fa9459Szrj       bfd_size_type j;
1402*a9fa9459Szrj       char *dll;
1403*a9fa9459Szrj 
1404*a9fa9459Szrj       /* Print (i + extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress).  */
1405*a9fa9459Szrj       fprintf (file, " %08lx\t", (unsigned long) (i + adj));
1406*a9fa9459Szrj       hint_addr = bfd_get_32 (abfd, data + i);
1407*a9fa9459Szrj       time_stamp = bfd_get_32 (abfd, data + i + 4);
1408*a9fa9459Szrj       forward_chain = bfd_get_32 (abfd, data + i + 8);
1409*a9fa9459Szrj       dll_name = bfd_get_32 (abfd, data + i + 12);
1410*a9fa9459Szrj       first_thunk = bfd_get_32 (abfd, data + i + 16);
1411*a9fa9459Szrj 
1412*a9fa9459Szrj       fprintf (file, "%08lx %08lx %08lx %08lx %08lx\n",
1413*a9fa9459Szrj 	       (unsigned long) hint_addr,
1414*a9fa9459Szrj 	       (unsigned long) time_stamp,
1415*a9fa9459Szrj 	       (unsigned long) forward_chain,
1416*a9fa9459Szrj 	       (unsigned long) dll_name,
1417*a9fa9459Szrj 	       (unsigned long) first_thunk);
1418*a9fa9459Szrj 
1419*a9fa9459Szrj       if (hint_addr == 0 && first_thunk == 0)
1420*a9fa9459Szrj 	break;
1421*a9fa9459Szrj 
1422*a9fa9459Szrj       if (dll_name - adj >= section->size)
1423*a9fa9459Szrj         break;
1424*a9fa9459Szrj 
1425*a9fa9459Szrj       dll = (char *) data + dll_name - adj;
1426*a9fa9459Szrj       /* PR 17512 file: 078-12277-0.004.  */
1427*a9fa9459Szrj       bfd_size_type maxlen = (char *)(data + datasize) - dll - 1;
1428*a9fa9459Szrj       fprintf (file, _("\n\tDLL Name: %.*s\n"), (int) maxlen, dll);
1429*a9fa9459Szrj 
1430*a9fa9459Szrj       if (hint_addr != 0)
1431*a9fa9459Szrj 	{
1432*a9fa9459Szrj 	  bfd_byte *ft_data;
1433*a9fa9459Szrj 	  asection *ft_section;
1434*a9fa9459Szrj 	  bfd_vma ft_addr;
1435*a9fa9459Szrj 	  bfd_size_type ft_datasize;
1436*a9fa9459Szrj 	  int ft_idx;
1437*a9fa9459Szrj 	  int ft_allocated;
1438*a9fa9459Szrj 
1439*a9fa9459Szrj 	  fprintf (file, _("\tvma:  Hint/Ord Member-Name Bound-To\n"));
1440*a9fa9459Szrj 
1441*a9fa9459Szrj 	  idx = hint_addr - adj;
1442*a9fa9459Szrj 
1443*a9fa9459Szrj 	  ft_addr = first_thunk + extra->ImageBase;
1444*a9fa9459Szrj 	  ft_idx = first_thunk - adj;
1445*a9fa9459Szrj 	  ft_data = data + ft_idx;
1446*a9fa9459Szrj 	  ft_datasize = datasize - ft_idx;
1447*a9fa9459Szrj 	  ft_allocated = 0;
1448*a9fa9459Szrj 
1449*a9fa9459Szrj 	  if (first_thunk != hint_addr)
1450*a9fa9459Szrj 	    {
1451*a9fa9459Szrj 	      /* Find the section which contains the first thunk.  */
1452*a9fa9459Szrj 	      for (ft_section = abfd->sections;
1453*a9fa9459Szrj 		   ft_section != NULL;
1454*a9fa9459Szrj 		   ft_section = ft_section->next)
1455*a9fa9459Szrj 		{
1456*a9fa9459Szrj 		  if (ft_addr >= ft_section->vma
1457*a9fa9459Szrj 		      && ft_addr < ft_section->vma + ft_section->size)
1458*a9fa9459Szrj 		    break;
1459*a9fa9459Szrj 		}
1460*a9fa9459Szrj 
1461*a9fa9459Szrj 	      if (ft_section == NULL)
1462*a9fa9459Szrj 		{
1463*a9fa9459Szrj 		  fprintf (file,
1464*a9fa9459Szrj 		       _("\nThere is a first thunk, but the section containing it could not be found\n"));
1465*a9fa9459Szrj 		  continue;
1466*a9fa9459Szrj 		}
1467*a9fa9459Szrj 
1468*a9fa9459Szrj 	      /* Now check to see if this section is the same as our current
1469*a9fa9459Szrj 		 section.  If it is not then we will have to load its data in.  */
1470*a9fa9459Szrj 	      if (ft_section != section)
1471*a9fa9459Szrj 		{
1472*a9fa9459Szrj 		  ft_idx = first_thunk - (ft_section->vma - extra->ImageBase);
1473*a9fa9459Szrj 		  ft_datasize = ft_section->size - ft_idx;
1474*a9fa9459Szrj 		  ft_data = (bfd_byte *) bfd_malloc (ft_datasize);
1475*a9fa9459Szrj 		  if (ft_data == NULL)
1476*a9fa9459Szrj 		    continue;
1477*a9fa9459Szrj 
1478*a9fa9459Szrj 		  /* Read ft_datasize bytes starting at offset ft_idx.  */
1479*a9fa9459Szrj 		  if (!bfd_get_section_contents (abfd, ft_section, ft_data,
1480*a9fa9459Szrj 						 (bfd_vma) ft_idx, ft_datasize))
1481*a9fa9459Szrj 		    {
1482*a9fa9459Szrj 		      free (ft_data);
1483*a9fa9459Szrj 		      continue;
1484*a9fa9459Szrj 		    }
1485*a9fa9459Szrj 		  ft_allocated = 1;
1486*a9fa9459Szrj 		}
1487*a9fa9459Szrj 	    }
1488*a9fa9459Szrj 
1489*a9fa9459Szrj 	  /* Print HintName vector entries.  */
1490*a9fa9459Szrj #ifdef COFF_WITH_pex64
1491*a9fa9459Szrj 	  for (j = 0; idx + j + 8 <= datasize; j += 8)
1492*a9fa9459Szrj 	    {
1493*a9fa9459Szrj 	      bfd_size_type amt;
1494*a9fa9459Szrj 	      unsigned long member = bfd_get_32 (abfd, data + idx + j);
1495*a9fa9459Szrj 	      unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4);
1496*a9fa9459Szrj 
1497*a9fa9459Szrj 	      if (!member && !member_high)
1498*a9fa9459Szrj 		break;
1499*a9fa9459Szrj 
1500*a9fa9459Szrj 	      amt = member - adj;
1501*a9fa9459Szrj 
1502*a9fa9459Szrj 	      if (HighBitSet (member_high))
1503*a9fa9459Szrj 		fprintf (file, "\t%lx%08lx\t %4lx%08lx  <none>",
1504*a9fa9459Szrj 			 member_high, member,
1505*a9fa9459Szrj 			 WithoutHighBit (member_high), member);
1506*a9fa9459Szrj 	      /* PR binutils/17512: Handle corrupt PE data.  */
1507*a9fa9459Szrj 	      else if (amt + 2 >= datasize)
1508*a9fa9459Szrj 		fprintf (file, _("\t<corrupt: 0x%04lx>"), member);
1509*a9fa9459Szrj 	      else
1510*a9fa9459Szrj 		{
1511*a9fa9459Szrj 		  int ordinal;
1512*a9fa9459Szrj 		  char *member_name;
1513*a9fa9459Szrj 
1514*a9fa9459Szrj 		  ordinal = bfd_get_16 (abfd, data + amt);
1515*a9fa9459Szrj 		  member_name = (char *) data + amt + 2;
1516*a9fa9459Szrj 		  fprintf (file, "\t%04lx\t %4d  %.*s",member, ordinal,
1517*a9fa9459Szrj 			   (int) (datasize - (amt + 2)), member_name);
1518*a9fa9459Szrj 		}
1519*a9fa9459Szrj 
1520*a9fa9459Szrj 	      /* If the time stamp is not zero, the import address
1521*a9fa9459Szrj 		 table holds actual addresses.  */
1522*a9fa9459Szrj 	      if (time_stamp != 0
1523*a9fa9459Szrj 		  && first_thunk != 0
1524*a9fa9459Szrj 		  && first_thunk != hint_addr
1525*a9fa9459Szrj 		  && j + 4 <= ft_datasize)
1526*a9fa9459Szrj 		fprintf (file, "\t%04lx",
1527*a9fa9459Szrj 			 (unsigned long) bfd_get_32 (abfd, ft_data + j));
1528*a9fa9459Szrj 	      fprintf (file, "\n");
1529*a9fa9459Szrj 	    }
1530*a9fa9459Szrj #else
1531*a9fa9459Szrj 	  for (j = 0; idx + j + 4 <= datasize; j += 4)
1532*a9fa9459Szrj 	    {
1533*a9fa9459Szrj 	      bfd_size_type amt;
1534*a9fa9459Szrj 	      unsigned long member = bfd_get_32 (abfd, data + idx + j);
1535*a9fa9459Szrj 
1536*a9fa9459Szrj 	      /* Print single IMAGE_IMPORT_BY_NAME vector.  */
1537*a9fa9459Szrj 	      if (member == 0)
1538*a9fa9459Szrj 		break;
1539*a9fa9459Szrj 
1540*a9fa9459Szrj 	      amt = member - adj;
1541*a9fa9459Szrj 	      if (HighBitSet (member))
1542*a9fa9459Szrj 		fprintf (file, "\t%04lx\t %4lu  <none>",
1543*a9fa9459Szrj 			 member, WithoutHighBit (member));
1544*a9fa9459Szrj 	      /* PR binutils/17512: Handle corrupt PE data.  */
1545*a9fa9459Szrj 	      else if (amt + 2 >= datasize)
1546*a9fa9459Szrj 		fprintf (file, _("\t<corrupt: 0x%04lx>"), member);
1547*a9fa9459Szrj 	      else
1548*a9fa9459Szrj 		{
1549*a9fa9459Szrj 		  int ordinal;
1550*a9fa9459Szrj 		  char *member_name;
1551*a9fa9459Szrj 
1552*a9fa9459Szrj 		  ordinal = bfd_get_16 (abfd, data + amt);
1553*a9fa9459Szrj 		  member_name = (char *) data + amt + 2;
1554*a9fa9459Szrj 		  fprintf (file, "\t%04lx\t %4d  %.*s",
1555*a9fa9459Szrj 			   member, ordinal,
1556*a9fa9459Szrj 			   (int) (datasize - (amt + 2)), member_name);
1557*a9fa9459Szrj 		}
1558*a9fa9459Szrj 
1559*a9fa9459Szrj 	      /* If the time stamp is not zero, the import address
1560*a9fa9459Szrj 		 table holds actual addresses.  */
1561*a9fa9459Szrj 	      if (time_stamp != 0
1562*a9fa9459Szrj 		  && first_thunk != 0
1563*a9fa9459Szrj 		  && first_thunk != hint_addr
1564*a9fa9459Szrj 		  && j + 4 <= ft_datasize)
1565*a9fa9459Szrj 		fprintf (file, "\t%04lx",
1566*a9fa9459Szrj 			 (unsigned long) bfd_get_32 (abfd, ft_data + j));
1567*a9fa9459Szrj 
1568*a9fa9459Szrj 	      fprintf (file, "\n");
1569*a9fa9459Szrj 	    }
1570*a9fa9459Szrj #endif
1571*a9fa9459Szrj 	  if (ft_allocated)
1572*a9fa9459Szrj 	    free (ft_data);
1573*a9fa9459Szrj 	}
1574*a9fa9459Szrj 
1575*a9fa9459Szrj       fprintf (file, "\n");
1576*a9fa9459Szrj     }
1577*a9fa9459Szrj 
1578*a9fa9459Szrj   free (data);
1579*a9fa9459Szrj 
1580*a9fa9459Szrj   return TRUE;
1581*a9fa9459Szrj }
1582*a9fa9459Szrj 
1583*a9fa9459Szrj static bfd_boolean
pe_print_edata(bfd * abfd,void * vfile)1584*a9fa9459Szrj pe_print_edata (bfd * abfd, void * vfile)
1585*a9fa9459Szrj {
1586*a9fa9459Szrj   FILE *file = (FILE *) vfile;
1587*a9fa9459Szrj   bfd_byte *data;
1588*a9fa9459Szrj   asection *section;
1589*a9fa9459Szrj   bfd_size_type datasize = 0;
1590*a9fa9459Szrj   bfd_size_type dataoff;
1591*a9fa9459Szrj   bfd_size_type i;
1592*a9fa9459Szrj   bfd_vma       adj;
1593*a9fa9459Szrj   struct EDT_type
1594*a9fa9459Szrj   {
1595*a9fa9459Szrj     long export_flags;          /* Reserved - should be zero.  */
1596*a9fa9459Szrj     long time_stamp;
1597*a9fa9459Szrj     short major_ver;
1598*a9fa9459Szrj     short minor_ver;
1599*a9fa9459Szrj     bfd_vma name;               /* RVA - relative to image base.  */
1600*a9fa9459Szrj     long base;                  /* Ordinal base.  */
1601*a9fa9459Szrj     unsigned long num_functions;/* Number in the export address table.  */
1602*a9fa9459Szrj     unsigned long num_names;    /* Number in the name pointer table.  */
1603*a9fa9459Szrj     bfd_vma eat_addr;		/* RVA to the export address table.  */
1604*a9fa9459Szrj     bfd_vma npt_addr;		/* RVA to the Export Name Pointer Table.  */
1605*a9fa9459Szrj     bfd_vma ot_addr;		/* RVA to the Ordinal Table.  */
1606*a9fa9459Szrj   } edt;
1607*a9fa9459Szrj 
1608*a9fa9459Szrj   pe_data_type *pe = pe_data (abfd);
1609*a9fa9459Szrj   struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
1610*a9fa9459Szrj 
1611*a9fa9459Szrj   bfd_vma addr;
1612*a9fa9459Szrj 
1613*a9fa9459Szrj   addr = extra->DataDirectory[PE_EXPORT_TABLE].VirtualAddress;
1614*a9fa9459Szrj 
1615*a9fa9459Szrj   if (addr == 0 && extra->DataDirectory[PE_EXPORT_TABLE].Size == 0)
1616*a9fa9459Szrj     {
1617*a9fa9459Szrj       /* Maybe the extra header isn't there.  Look for the section.  */
1618*a9fa9459Szrj       section = bfd_get_section_by_name (abfd, ".edata");
1619*a9fa9459Szrj       if (section == NULL)
1620*a9fa9459Szrj 	return TRUE;
1621*a9fa9459Szrj 
1622*a9fa9459Szrj       addr = section->vma;
1623*a9fa9459Szrj       dataoff = 0;
1624*a9fa9459Szrj       datasize = section->size;
1625*a9fa9459Szrj       if (datasize == 0)
1626*a9fa9459Szrj 	return TRUE;
1627*a9fa9459Szrj     }
1628*a9fa9459Szrj   else
1629*a9fa9459Szrj     {
1630*a9fa9459Szrj       addr += extra->ImageBase;
1631*a9fa9459Szrj 
1632*a9fa9459Szrj       for (section = abfd->sections; section != NULL; section = section->next)
1633*a9fa9459Szrj 	if (addr >= section->vma && addr < section->vma + section->size)
1634*a9fa9459Szrj 	  break;
1635*a9fa9459Szrj 
1636*a9fa9459Szrj       if (section == NULL)
1637*a9fa9459Szrj 	{
1638*a9fa9459Szrj 	  fprintf (file,
1639*a9fa9459Szrj 		   _("\nThere is an export table, but the section containing it could not be found\n"));
1640*a9fa9459Szrj 	  return TRUE;
1641*a9fa9459Szrj 	}
1642*a9fa9459Szrj       else if (!(section->flags & SEC_HAS_CONTENTS))
1643*a9fa9459Szrj         {
1644*a9fa9459Szrj 	  fprintf (file,
1645*a9fa9459Szrj 		   _("\nThere is an export table in %s, but that section has no contents\n"),
1646*a9fa9459Szrj 		   section->name);
1647*a9fa9459Szrj 	  return TRUE;
1648*a9fa9459Szrj         }
1649*a9fa9459Szrj 
1650*a9fa9459Szrj       dataoff = addr - section->vma;
1651*a9fa9459Szrj       datasize = extra->DataDirectory[PE_EXPORT_TABLE].Size;
1652*a9fa9459Szrj       if (datasize > section->size - dataoff)
1653*a9fa9459Szrj 	{
1654*a9fa9459Szrj 	  fprintf (file,
1655*a9fa9459Szrj 		   _("\nThere is an export table in %s, but it does not fit into that section\n"),
1656*a9fa9459Szrj 		   section->name);
1657*a9fa9459Szrj 	  return TRUE;
1658*a9fa9459Szrj 	}
1659*a9fa9459Szrj     }
1660*a9fa9459Szrj 
1661*a9fa9459Szrj   /* PR 17512: Handle corrupt PE binaries.  */
1662*a9fa9459Szrj   if (datasize < 36)
1663*a9fa9459Szrj     {
1664*a9fa9459Szrj       fprintf (file,
1665*a9fa9459Szrj 	       _("\nThere is an export table in %s, but it is too small (%d)\n"),
1666*a9fa9459Szrj 	       section->name, (int) datasize);
1667*a9fa9459Szrj       return TRUE;
1668*a9fa9459Szrj     }
1669*a9fa9459Szrj 
1670*a9fa9459Szrj   fprintf (file, _("\nThere is an export table in %s at 0x%lx\n"),
1671*a9fa9459Szrj 	   section->name, (unsigned long) addr);
1672*a9fa9459Szrj 
1673*a9fa9459Szrj   data = (bfd_byte *) bfd_malloc (datasize);
1674*a9fa9459Szrj   if (data == NULL)
1675*a9fa9459Szrj     return FALSE;
1676*a9fa9459Szrj 
1677*a9fa9459Szrj   if (! bfd_get_section_contents (abfd, section, data,
1678*a9fa9459Szrj 				  (file_ptr) dataoff, datasize))
1679*a9fa9459Szrj     return FALSE;
1680*a9fa9459Szrj 
1681*a9fa9459Szrj   /* Go get Export Directory Table.  */
1682*a9fa9459Szrj   edt.export_flags   = bfd_get_32 (abfd, data +  0);
1683*a9fa9459Szrj   edt.time_stamp     = bfd_get_32 (abfd, data +  4);
1684*a9fa9459Szrj   edt.major_ver      = bfd_get_16 (abfd, data +  8);
1685*a9fa9459Szrj   edt.minor_ver      = bfd_get_16 (abfd, data + 10);
1686*a9fa9459Szrj   edt.name           = bfd_get_32 (abfd, data + 12);
1687*a9fa9459Szrj   edt.base           = bfd_get_32 (abfd, data + 16);
1688*a9fa9459Szrj   edt.num_functions  = bfd_get_32 (abfd, data + 20);
1689*a9fa9459Szrj   edt.num_names      = bfd_get_32 (abfd, data + 24);
1690*a9fa9459Szrj   edt.eat_addr       = bfd_get_32 (abfd, data + 28);
1691*a9fa9459Szrj   edt.npt_addr       = bfd_get_32 (abfd, data + 32);
1692*a9fa9459Szrj   edt.ot_addr        = bfd_get_32 (abfd, data + 36);
1693*a9fa9459Szrj 
1694*a9fa9459Szrj   adj = section->vma - extra->ImageBase + dataoff;
1695*a9fa9459Szrj 
1696*a9fa9459Szrj   /* Dump the EDT first.  */
1697*a9fa9459Szrj   fprintf (file,
1698*a9fa9459Szrj 	   _("\nThe Export Tables (interpreted %s section contents)\n\n"),
1699*a9fa9459Szrj 	   section->name);
1700*a9fa9459Szrj 
1701*a9fa9459Szrj   fprintf (file,
1702*a9fa9459Szrj 	   _("Export Flags \t\t\t%lx\n"), (unsigned long) edt.export_flags);
1703*a9fa9459Szrj 
1704*a9fa9459Szrj   fprintf (file,
1705*a9fa9459Szrj 	   _("Time/Date stamp \t\t%lx\n"), (unsigned long) edt.time_stamp);
1706*a9fa9459Szrj 
1707*a9fa9459Szrj   fprintf (file,
1708*a9fa9459Szrj 	   _("Major/Minor \t\t\t%d/%d\n"), edt.major_ver, edt.minor_ver);
1709*a9fa9459Szrj 
1710*a9fa9459Szrj   fprintf (file,
1711*a9fa9459Szrj 	   _("Name \t\t\t\t"));
1712*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, edt.name);
1713*a9fa9459Szrj 
1714*a9fa9459Szrj   if ((edt.name >= adj) && (edt.name < adj + datasize))
1715*a9fa9459Szrj     fprintf (file, " %.*s\n",
1716*a9fa9459Szrj 	     (int) (datasize - (edt.name - adj)),
1717*a9fa9459Szrj 	     data + edt.name - adj);
1718*a9fa9459Szrj   else
1719*a9fa9459Szrj     fprintf (file, "(outside .edata section)\n");
1720*a9fa9459Szrj 
1721*a9fa9459Szrj   fprintf (file,
1722*a9fa9459Szrj 	   _("Ordinal Base \t\t\t%ld\n"), edt.base);
1723*a9fa9459Szrj 
1724*a9fa9459Szrj   fprintf (file,
1725*a9fa9459Szrj 	   _("Number in:\n"));
1726*a9fa9459Szrj 
1727*a9fa9459Szrj   fprintf (file,
1728*a9fa9459Szrj 	   _("\tExport Address Table \t\t%08lx\n"),
1729*a9fa9459Szrj 	   edt.num_functions);
1730*a9fa9459Szrj 
1731*a9fa9459Szrj   fprintf (file,
1732*a9fa9459Szrj 	   _("\t[Name Pointer/Ordinal] Table\t%08lx\n"), edt.num_names);
1733*a9fa9459Szrj 
1734*a9fa9459Szrj   fprintf (file,
1735*a9fa9459Szrj 	   _("Table Addresses\n"));
1736*a9fa9459Szrj 
1737*a9fa9459Szrj   fprintf (file,
1738*a9fa9459Szrj 	   _("\tExport Address Table \t\t"));
1739*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, edt.eat_addr);
1740*a9fa9459Szrj   fprintf (file, "\n");
1741*a9fa9459Szrj 
1742*a9fa9459Szrj   fprintf (file,
1743*a9fa9459Szrj 	   _("\tName Pointer Table \t\t"));
1744*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, edt.npt_addr);
1745*a9fa9459Szrj   fprintf (file, "\n");
1746*a9fa9459Szrj 
1747*a9fa9459Szrj   fprintf (file,
1748*a9fa9459Szrj 	   _("\tOrdinal Table \t\t\t"));
1749*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, edt.ot_addr);
1750*a9fa9459Szrj   fprintf (file, "\n");
1751*a9fa9459Szrj 
1752*a9fa9459Szrj   /* The next table to find is the Export Address Table. It's basically
1753*a9fa9459Szrj      a list of pointers that either locate a function in this dll, or
1754*a9fa9459Szrj      forward the call to another dll. Something like:
1755*a9fa9459Szrj       typedef union
1756*a9fa9459Szrj       {
1757*a9fa9459Szrj         long export_rva;
1758*a9fa9459Szrj         long forwarder_rva;
1759*a9fa9459Szrj       } export_address_table_entry;  */
1760*a9fa9459Szrj 
1761*a9fa9459Szrj   fprintf (file,
1762*a9fa9459Szrj 	  _("\nExport Address Table -- Ordinal Base %ld\n"),
1763*a9fa9459Szrj 	  edt.base);
1764*a9fa9459Szrj 
1765*a9fa9459Szrj   /* PR 17512: Handle corrupt PE binaries.  */
1766*a9fa9459Szrj   if (edt.eat_addr + (edt.num_functions * 4) - adj >= datasize
1767*a9fa9459Szrj       /* PR 17512: file: 092b1829 */
1768*a9fa9459Szrj       || (edt.num_functions * 4) < edt.num_functions
1769*a9fa9459Szrj       /* PR 17512 file: 140-165018-0.004.  */
1770*a9fa9459Szrj       || data + edt.eat_addr - adj < data)
1771*a9fa9459Szrj     fprintf (file, _("\tInvalid Export Address Table rva (0x%lx) or entry count (0x%lx)\n"),
1772*a9fa9459Szrj 	     (long) edt.eat_addr,
1773*a9fa9459Szrj 	     (long) edt.num_functions);
1774*a9fa9459Szrj   else for (i = 0; i < edt.num_functions; ++i)
1775*a9fa9459Szrj     {
1776*a9fa9459Szrj       bfd_vma eat_member = bfd_get_32 (abfd,
1777*a9fa9459Szrj 				       data + edt.eat_addr + (i * 4) - adj);
1778*a9fa9459Szrj       if (eat_member == 0)
1779*a9fa9459Szrj 	continue;
1780*a9fa9459Szrj 
1781*a9fa9459Szrj       if (eat_member - adj <= datasize)
1782*a9fa9459Szrj 	{
1783*a9fa9459Szrj 	  /* This rva is to a name (forwarding function) in our section.  */
1784*a9fa9459Szrj 	  /* Should locate a function descriptor.  */
1785*a9fa9459Szrj 	  fprintf (file,
1786*a9fa9459Szrj 		   "\t[%4ld] +base[%4ld] %04lx %s -- %.*s\n",
1787*a9fa9459Szrj 		   (long) i,
1788*a9fa9459Szrj 		   (long) (i + edt.base),
1789*a9fa9459Szrj 		   (unsigned long) eat_member,
1790*a9fa9459Szrj 		   _("Forwarder RVA"),
1791*a9fa9459Szrj 		   (int)(datasize - (eat_member - adj)),
1792*a9fa9459Szrj 		   data + eat_member - adj);
1793*a9fa9459Szrj 	}
1794*a9fa9459Szrj       else
1795*a9fa9459Szrj 	{
1796*a9fa9459Szrj 	  /* Should locate a function descriptor in the reldata section.  */
1797*a9fa9459Szrj 	  fprintf (file,
1798*a9fa9459Szrj 		   "\t[%4ld] +base[%4ld] %04lx %s\n",
1799*a9fa9459Szrj 		   (long) i,
1800*a9fa9459Szrj 		   (long) (i + edt.base),
1801*a9fa9459Szrj 		   (unsigned long) eat_member,
1802*a9fa9459Szrj 		   _("Export RVA"));
1803*a9fa9459Szrj 	}
1804*a9fa9459Szrj     }
1805*a9fa9459Szrj 
1806*a9fa9459Szrj   /* The Export Name Pointer Table is paired with the Export Ordinal Table.  */
1807*a9fa9459Szrj   /* Dump them in parallel for clarity.  */
1808*a9fa9459Szrj   fprintf (file,
1809*a9fa9459Szrj 	   _("\n[Ordinal/Name Pointer] Table\n"));
1810*a9fa9459Szrj 
1811*a9fa9459Szrj   /* PR 17512: Handle corrupt PE binaries.  */
1812*a9fa9459Szrj   if (edt.npt_addr + (edt.num_names * 4) - adj >= datasize
1813*a9fa9459Szrj       /* PR 17512: file: bb68816e.  */
1814*a9fa9459Szrj       || edt.num_names * 4 < edt.num_names
1815*a9fa9459Szrj       || (data + edt.npt_addr - adj) < data)
1816*a9fa9459Szrj     fprintf (file, _("\tInvalid Name Pointer Table rva (0x%lx) or entry count (0x%lx)\n"),
1817*a9fa9459Szrj 	     (long) edt.npt_addr,
1818*a9fa9459Szrj 	     (long) edt.num_names);
1819*a9fa9459Szrj   /* PR 17512: file: 140-147171-0.004.  */
1820*a9fa9459Szrj   else if (edt.ot_addr + (edt.num_names * 2) - adj >= datasize
1821*a9fa9459Szrj 	   || data + edt.ot_addr - adj < data)
1822*a9fa9459Szrj     fprintf (file, _("\tInvalid Ordinal Table rva (0x%lx) or entry count (0x%lx)\n"),
1823*a9fa9459Szrj 	     (long) edt.ot_addr,
1824*a9fa9459Szrj 	     (long) edt.num_names);
1825*a9fa9459Szrj   else for (i = 0; i < edt.num_names; ++i)
1826*a9fa9459Szrj     {
1827*a9fa9459Szrj       bfd_vma  name_ptr;
1828*a9fa9459Szrj       bfd_vma  ord;
1829*a9fa9459Szrj 
1830*a9fa9459Szrj       ord = bfd_get_16 (abfd, data + edt.ot_addr + (i * 2) - adj);
1831*a9fa9459Szrj       name_ptr = bfd_get_32 (abfd, data + edt.npt_addr + (i * 4) - adj);
1832*a9fa9459Szrj 
1833*a9fa9459Szrj       if ((name_ptr - adj) >= datasize)
1834*a9fa9459Szrj 	{
1835*a9fa9459Szrj 	  fprintf (file, _("\t[%4ld] <corrupt offset: %lx>\n"),
1836*a9fa9459Szrj 		   (long) ord, (long) name_ptr);
1837*a9fa9459Szrj 	}
1838*a9fa9459Szrj       else
1839*a9fa9459Szrj 	{
1840*a9fa9459Szrj 	  char * name = (char *) data + name_ptr - adj;
1841*a9fa9459Szrj 
1842*a9fa9459Szrj 	  fprintf (file, "\t[%4ld] %.*s\n", (long) ord,
1843*a9fa9459Szrj 		   (int)((char *)(data + datasize) - name), name);
1844*a9fa9459Szrj 	}
1845*a9fa9459Szrj     }
1846*a9fa9459Szrj 
1847*a9fa9459Szrj   free (data);
1848*a9fa9459Szrj 
1849*a9fa9459Szrj   return TRUE;
1850*a9fa9459Szrj }
1851*a9fa9459Szrj 
1852*a9fa9459Szrj /* This really is architecture dependent.  On IA-64, a .pdata entry
1853*a9fa9459Szrj    consists of three dwords containing relative virtual addresses that
1854*a9fa9459Szrj    specify the start and end address of the code range the entry
1855*a9fa9459Szrj    covers and the address of the corresponding unwind info data.
1856*a9fa9459Szrj 
1857*a9fa9459Szrj    On ARM and SH-4, a compressed PDATA structure is used :
1858*a9fa9459Szrj    _IMAGE_CE_RUNTIME_FUNCTION_ENTRY, whereas MIPS is documented to use
1859*a9fa9459Szrj    _IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY.
1860*a9fa9459Szrj    See http://msdn2.microsoft.com/en-us/library/ms253988(VS.80).aspx .
1861*a9fa9459Szrj 
1862*a9fa9459Szrj    This is the version for uncompressed data.  */
1863*a9fa9459Szrj 
1864*a9fa9459Szrj static bfd_boolean
pe_print_pdata(bfd * abfd,void * vfile)1865*a9fa9459Szrj pe_print_pdata (bfd * abfd, void * vfile)
1866*a9fa9459Szrj {
1867*a9fa9459Szrj #if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
1868*a9fa9459Szrj # define PDATA_ROW_SIZE	(3 * 8)
1869*a9fa9459Szrj #else
1870*a9fa9459Szrj # define PDATA_ROW_SIZE	(5 * 4)
1871*a9fa9459Szrj #endif
1872*a9fa9459Szrj   FILE *file = (FILE *) vfile;
1873*a9fa9459Szrj   bfd_byte *data = 0;
1874*a9fa9459Szrj   asection *section = bfd_get_section_by_name (abfd, ".pdata");
1875*a9fa9459Szrj   bfd_size_type datasize = 0;
1876*a9fa9459Szrj   bfd_size_type i;
1877*a9fa9459Szrj   bfd_size_type start, stop;
1878*a9fa9459Szrj   int onaline = PDATA_ROW_SIZE;
1879*a9fa9459Szrj 
1880*a9fa9459Szrj   if (section == NULL
1881*a9fa9459Szrj       || coff_section_data (abfd, section) == NULL
1882*a9fa9459Szrj       || pei_section_data (abfd, section) == NULL)
1883*a9fa9459Szrj     return TRUE;
1884*a9fa9459Szrj 
1885*a9fa9459Szrj   stop = pei_section_data (abfd, section)->virt_size;
1886*a9fa9459Szrj   if ((stop % onaline) != 0)
1887*a9fa9459Szrj     fprintf (file,
1888*a9fa9459Szrj 	     _("Warning, .pdata section size (%ld) is not a multiple of %d\n"),
1889*a9fa9459Szrj 	     (long) stop, onaline);
1890*a9fa9459Szrj 
1891*a9fa9459Szrj   fprintf (file,
1892*a9fa9459Szrj 	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
1893*a9fa9459Szrj #if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
1894*a9fa9459Szrj   fprintf (file,
1895*a9fa9459Szrj 	   _(" vma:\t\t\tBegin Address    End Address      Unwind Info\n"));
1896*a9fa9459Szrj #else
1897*a9fa9459Szrj   fprintf (file, _("\
1898*a9fa9459Szrj  vma:\t\tBegin    End      EH       EH       PrologEnd  Exception\n\
1899*a9fa9459Szrj      \t\tAddress  Address  Handler  Data     Address    Mask\n"));
1900*a9fa9459Szrj #endif
1901*a9fa9459Szrj 
1902*a9fa9459Szrj   datasize = section->size;
1903*a9fa9459Szrj   if (datasize == 0)
1904*a9fa9459Szrj     return TRUE;
1905*a9fa9459Szrj 
1906*a9fa9459Szrj   /* PR 17512: file: 002-193900-0.004.  */
1907*a9fa9459Szrj   if (datasize < stop)
1908*a9fa9459Szrj     {
1909*a9fa9459Szrj       fprintf (file, _("Virtual size of .pdata section (%ld) larger than real size (%ld)\n"),
1910*a9fa9459Szrj 	       (long) stop, (long) datasize);
1911*a9fa9459Szrj       return FALSE;
1912*a9fa9459Szrj     }
1913*a9fa9459Szrj 
1914*a9fa9459Szrj   if (! bfd_malloc_and_get_section (abfd, section, &data))
1915*a9fa9459Szrj     {
1916*a9fa9459Szrj       if (data != NULL)
1917*a9fa9459Szrj 	free (data);
1918*a9fa9459Szrj       return FALSE;
1919*a9fa9459Szrj     }
1920*a9fa9459Szrj 
1921*a9fa9459Szrj   start = 0;
1922*a9fa9459Szrj 
1923*a9fa9459Szrj   for (i = start; i < stop; i += onaline)
1924*a9fa9459Szrj     {
1925*a9fa9459Szrj       bfd_vma begin_addr;
1926*a9fa9459Szrj       bfd_vma end_addr;
1927*a9fa9459Szrj       bfd_vma eh_handler;
1928*a9fa9459Szrj       bfd_vma eh_data;
1929*a9fa9459Szrj       bfd_vma prolog_end_addr;
1930*a9fa9459Szrj #if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
1931*a9fa9459Szrj       int em_data;
1932*a9fa9459Szrj #endif
1933*a9fa9459Szrj 
1934*a9fa9459Szrj       if (i + PDATA_ROW_SIZE > stop)
1935*a9fa9459Szrj 	break;
1936*a9fa9459Szrj 
1937*a9fa9459Szrj       begin_addr      = GET_PDATA_ENTRY (abfd, data + i     );
1938*a9fa9459Szrj       end_addr        = GET_PDATA_ENTRY (abfd, data + i +  4);
1939*a9fa9459Szrj       eh_handler      = GET_PDATA_ENTRY (abfd, data + i +  8);
1940*a9fa9459Szrj       eh_data         = GET_PDATA_ENTRY (abfd, data + i + 12);
1941*a9fa9459Szrj       prolog_end_addr = GET_PDATA_ENTRY (abfd, data + i + 16);
1942*a9fa9459Szrj 
1943*a9fa9459Szrj       if (begin_addr == 0 && end_addr == 0 && eh_handler == 0
1944*a9fa9459Szrj 	  && eh_data == 0 && prolog_end_addr == 0)
1945*a9fa9459Szrj 	/* We are probably into the padding of the section now.  */
1946*a9fa9459Szrj 	break;
1947*a9fa9459Szrj 
1948*a9fa9459Szrj #if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
1949*a9fa9459Szrj       em_data = ((eh_handler & 0x1) << 2) | (prolog_end_addr & 0x3);
1950*a9fa9459Szrj #endif
1951*a9fa9459Szrj       eh_handler &= ~(bfd_vma) 0x3;
1952*a9fa9459Szrj       prolog_end_addr &= ~(bfd_vma) 0x3;
1953*a9fa9459Szrj 
1954*a9fa9459Szrj       fputc (' ', file);
1955*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, i + section->vma); fputc ('\t', file);
1956*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, begin_addr); fputc (' ', file);
1957*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, end_addr); fputc (' ', file);
1958*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, eh_handler);
1959*a9fa9459Szrj #if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
1960*a9fa9459Szrj       fputc (' ', file);
1961*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, eh_data); fputc (' ', file);
1962*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, prolog_end_addr);
1963*a9fa9459Szrj       fprintf (file, "   %x", em_data);
1964*a9fa9459Szrj #endif
1965*a9fa9459Szrj 
1966*a9fa9459Szrj #ifdef POWERPC_LE_PE
1967*a9fa9459Szrj       if (eh_handler == 0 && eh_data != 0)
1968*a9fa9459Szrj 	{
1969*a9fa9459Szrj 	  /* Special bits here, although the meaning may be a little
1970*a9fa9459Szrj 	     mysterious. The only one I know for sure is 0x03
1971*a9fa9459Szrj 	     Code Significance
1972*a9fa9459Szrj 	     0x00 None
1973*a9fa9459Szrj 	     0x01 Register Save Millicode
1974*a9fa9459Szrj 	     0x02 Register Restore Millicode
1975*a9fa9459Szrj 	     0x03 Glue Code Sequence.  */
1976*a9fa9459Szrj 	  switch (eh_data)
1977*a9fa9459Szrj 	    {
1978*a9fa9459Szrj 	    case 0x01:
1979*a9fa9459Szrj 	      fprintf (file, _(" Register save millicode"));
1980*a9fa9459Szrj 	      break;
1981*a9fa9459Szrj 	    case 0x02:
1982*a9fa9459Szrj 	      fprintf (file, _(" Register restore millicode"));
1983*a9fa9459Szrj 	      break;
1984*a9fa9459Szrj 	    case 0x03:
1985*a9fa9459Szrj 	      fprintf (file, _(" Glue code sequence"));
1986*a9fa9459Szrj 	      break;
1987*a9fa9459Szrj 	    default:
1988*a9fa9459Szrj 	      break;
1989*a9fa9459Szrj 	    }
1990*a9fa9459Szrj 	}
1991*a9fa9459Szrj #endif
1992*a9fa9459Szrj       fprintf (file, "\n");
1993*a9fa9459Szrj     }
1994*a9fa9459Szrj 
1995*a9fa9459Szrj   free (data);
1996*a9fa9459Szrj 
1997*a9fa9459Szrj   return TRUE;
1998*a9fa9459Szrj #undef PDATA_ROW_SIZE
1999*a9fa9459Szrj }
2000*a9fa9459Szrj 
2001*a9fa9459Szrj typedef struct sym_cache
2002*a9fa9459Szrj {
2003*a9fa9459Szrj   int        symcount;
2004*a9fa9459Szrj   asymbol ** syms;
2005*a9fa9459Szrj } sym_cache;
2006*a9fa9459Szrj 
2007*a9fa9459Szrj static asymbol **
slurp_symtab(bfd * abfd,sym_cache * psc)2008*a9fa9459Szrj slurp_symtab (bfd *abfd, sym_cache *psc)
2009*a9fa9459Szrj {
2010*a9fa9459Szrj   asymbol ** sy = NULL;
2011*a9fa9459Szrj   long storage;
2012*a9fa9459Szrj 
2013*a9fa9459Szrj   if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
2014*a9fa9459Szrj     {
2015*a9fa9459Szrj       psc->symcount = 0;
2016*a9fa9459Szrj       return NULL;
2017*a9fa9459Szrj     }
2018*a9fa9459Szrj 
2019*a9fa9459Szrj   storage = bfd_get_symtab_upper_bound (abfd);
2020*a9fa9459Szrj   if (storage < 0)
2021*a9fa9459Szrj     return NULL;
2022*a9fa9459Szrj   if (storage)
2023*a9fa9459Szrj     {
2024*a9fa9459Szrj       sy = (asymbol **) bfd_malloc (storage);
2025*a9fa9459Szrj       if (sy == NULL)
2026*a9fa9459Szrj 	return NULL;
2027*a9fa9459Szrj     }
2028*a9fa9459Szrj 
2029*a9fa9459Szrj   psc->symcount = bfd_canonicalize_symtab (abfd, sy);
2030*a9fa9459Szrj   if (psc->symcount < 0)
2031*a9fa9459Szrj     return NULL;
2032*a9fa9459Szrj   return sy;
2033*a9fa9459Szrj }
2034*a9fa9459Szrj 
2035*a9fa9459Szrj static const char *
my_symbol_for_address(bfd * abfd,bfd_vma func,sym_cache * psc)2036*a9fa9459Szrj my_symbol_for_address (bfd *abfd, bfd_vma func, sym_cache *psc)
2037*a9fa9459Szrj {
2038*a9fa9459Szrj   int i;
2039*a9fa9459Szrj 
2040*a9fa9459Szrj   if (psc->syms == 0)
2041*a9fa9459Szrj     psc->syms = slurp_symtab (abfd, psc);
2042*a9fa9459Szrj 
2043*a9fa9459Szrj   for (i = 0; i < psc->symcount; i++)
2044*a9fa9459Szrj     {
2045*a9fa9459Szrj       if (psc->syms[i]->section->vma + psc->syms[i]->value == func)
2046*a9fa9459Szrj 	return psc->syms[i]->name;
2047*a9fa9459Szrj     }
2048*a9fa9459Szrj 
2049*a9fa9459Szrj   return NULL;
2050*a9fa9459Szrj }
2051*a9fa9459Szrj 
2052*a9fa9459Szrj static void
cleanup_syms(sym_cache * psc)2053*a9fa9459Szrj cleanup_syms (sym_cache *psc)
2054*a9fa9459Szrj {
2055*a9fa9459Szrj   psc->symcount = 0;
2056*a9fa9459Szrj   free (psc->syms);
2057*a9fa9459Szrj   psc->syms = NULL;
2058*a9fa9459Szrj }
2059*a9fa9459Szrj 
2060*a9fa9459Szrj /* This is the version for "compressed" pdata.  */
2061*a9fa9459Szrj 
2062*a9fa9459Szrj bfd_boolean
_bfd_XX_print_ce_compressed_pdata(bfd * abfd,void * vfile)2063*a9fa9459Szrj _bfd_XX_print_ce_compressed_pdata (bfd * abfd, void * vfile)
2064*a9fa9459Szrj {
2065*a9fa9459Szrj # define PDATA_ROW_SIZE	(2 * 4)
2066*a9fa9459Szrj   FILE *file = (FILE *) vfile;
2067*a9fa9459Szrj   bfd_byte *data = NULL;
2068*a9fa9459Szrj   asection *section = bfd_get_section_by_name (abfd, ".pdata");
2069*a9fa9459Szrj   bfd_size_type datasize = 0;
2070*a9fa9459Szrj   bfd_size_type i;
2071*a9fa9459Szrj   bfd_size_type start, stop;
2072*a9fa9459Szrj   int onaline = PDATA_ROW_SIZE;
2073*a9fa9459Szrj   struct sym_cache cache = {0, 0} ;
2074*a9fa9459Szrj 
2075*a9fa9459Szrj   if (section == NULL
2076*a9fa9459Szrj       || coff_section_data (abfd, section) == NULL
2077*a9fa9459Szrj       || pei_section_data (abfd, section) == NULL)
2078*a9fa9459Szrj     return TRUE;
2079*a9fa9459Szrj 
2080*a9fa9459Szrj   stop = pei_section_data (abfd, section)->virt_size;
2081*a9fa9459Szrj   if ((stop % onaline) != 0)
2082*a9fa9459Szrj     fprintf (file,
2083*a9fa9459Szrj 	     _("Warning, .pdata section size (%ld) is not a multiple of %d\n"),
2084*a9fa9459Szrj 	     (long) stop, onaline);
2085*a9fa9459Szrj 
2086*a9fa9459Szrj   fprintf (file,
2087*a9fa9459Szrj 	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
2088*a9fa9459Szrj 
2089*a9fa9459Szrj   fprintf (file, _("\
2090*a9fa9459Szrj  vma:\t\tBegin    Prolog   Function Flags    Exception EH\n\
2091*a9fa9459Szrj      \t\tAddress  Length   Length   32b exc  Handler   Data\n"));
2092*a9fa9459Szrj 
2093*a9fa9459Szrj   datasize = section->size;
2094*a9fa9459Szrj   if (datasize == 0)
2095*a9fa9459Szrj     return TRUE;
2096*a9fa9459Szrj 
2097*a9fa9459Szrj   if (! bfd_malloc_and_get_section (abfd, section, &data))
2098*a9fa9459Szrj     {
2099*a9fa9459Szrj       if (data != NULL)
2100*a9fa9459Szrj 	free (data);
2101*a9fa9459Szrj       return FALSE;
2102*a9fa9459Szrj     }
2103*a9fa9459Szrj 
2104*a9fa9459Szrj   start = 0;
2105*a9fa9459Szrj 
2106*a9fa9459Szrj   for (i = start; i < stop; i += onaline)
2107*a9fa9459Szrj     {
2108*a9fa9459Szrj       bfd_vma begin_addr;
2109*a9fa9459Szrj       bfd_vma other_data;
2110*a9fa9459Szrj       bfd_vma prolog_length, function_length;
2111*a9fa9459Szrj       int flag32bit, exception_flag;
2112*a9fa9459Szrj       asection *tsection;
2113*a9fa9459Szrj 
2114*a9fa9459Szrj       if (i + PDATA_ROW_SIZE > stop)
2115*a9fa9459Szrj 	break;
2116*a9fa9459Szrj 
2117*a9fa9459Szrj       begin_addr = GET_PDATA_ENTRY (abfd, data + i     );
2118*a9fa9459Szrj       other_data = GET_PDATA_ENTRY (abfd, data + i +  4);
2119*a9fa9459Szrj 
2120*a9fa9459Szrj       if (begin_addr == 0 && other_data == 0)
2121*a9fa9459Szrj 	/* We are probably into the padding of the section now.  */
2122*a9fa9459Szrj 	break;
2123*a9fa9459Szrj 
2124*a9fa9459Szrj       prolog_length = (other_data & 0x000000FF);
2125*a9fa9459Szrj       function_length = (other_data & 0x3FFFFF00) >> 8;
2126*a9fa9459Szrj       flag32bit = (int)((other_data & 0x40000000) >> 30);
2127*a9fa9459Szrj       exception_flag = (int)((other_data & 0x80000000) >> 31);
2128*a9fa9459Szrj 
2129*a9fa9459Szrj       fputc (' ', file);
2130*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, i + section->vma); fputc ('\t', file);
2131*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, begin_addr); fputc (' ', file);
2132*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, prolog_length); fputc (' ', file);
2133*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, function_length); fputc (' ', file);
2134*a9fa9459Szrj       fprintf (file, "%2d  %2d   ", flag32bit, exception_flag);
2135*a9fa9459Szrj 
2136*a9fa9459Szrj       /* Get the exception handler's address and the data passed from the
2137*a9fa9459Szrj          .text section. This is really the data that belongs with the .pdata
2138*a9fa9459Szrj          but got "compressed" out for the ARM and SH4 architectures.  */
2139*a9fa9459Szrj       tsection = bfd_get_section_by_name (abfd, ".text");
2140*a9fa9459Szrj       if (tsection && coff_section_data (abfd, tsection)
2141*a9fa9459Szrj 	  && pei_section_data (abfd, tsection))
2142*a9fa9459Szrj 	{
2143*a9fa9459Szrj 	  bfd_vma eh_off = (begin_addr - 8) - tsection->vma;
2144*a9fa9459Szrj 	  bfd_byte *tdata;
2145*a9fa9459Szrj 
2146*a9fa9459Szrj 	  tdata = (bfd_byte *) bfd_malloc (8);
2147*a9fa9459Szrj 	  if (tdata)
2148*a9fa9459Szrj 	    {
2149*a9fa9459Szrj 	      if (bfd_get_section_contents (abfd, tsection, tdata, eh_off, 8))
2150*a9fa9459Szrj 		{
2151*a9fa9459Szrj 		  bfd_vma eh, eh_data;
2152*a9fa9459Szrj 
2153*a9fa9459Szrj 		  eh = bfd_get_32 (abfd, tdata);
2154*a9fa9459Szrj 		  eh_data = bfd_get_32 (abfd, tdata + 4);
2155*a9fa9459Szrj 		  fprintf (file, "%08x  ", (unsigned int) eh);
2156*a9fa9459Szrj 		  fprintf (file, "%08x", (unsigned int) eh_data);
2157*a9fa9459Szrj 		  if (eh != 0)
2158*a9fa9459Szrj 		    {
2159*a9fa9459Szrj 		      const char *s = my_symbol_for_address (abfd, eh, &cache);
2160*a9fa9459Szrj 
2161*a9fa9459Szrj 		      if (s)
2162*a9fa9459Szrj 			fprintf (file, " (%s) ", s);
2163*a9fa9459Szrj 		    }
2164*a9fa9459Szrj 		}
2165*a9fa9459Szrj 	      free (tdata);
2166*a9fa9459Szrj 	    }
2167*a9fa9459Szrj 	}
2168*a9fa9459Szrj 
2169*a9fa9459Szrj       fprintf (file, "\n");
2170*a9fa9459Szrj     }
2171*a9fa9459Szrj 
2172*a9fa9459Szrj   free (data);
2173*a9fa9459Szrj 
2174*a9fa9459Szrj   cleanup_syms (& cache);
2175*a9fa9459Szrj 
2176*a9fa9459Szrj   return TRUE;
2177*a9fa9459Szrj #undef PDATA_ROW_SIZE
2178*a9fa9459Szrj }
2179*a9fa9459Szrj 
2180*a9fa9459Szrj 
2181*a9fa9459Szrj #define IMAGE_REL_BASED_HIGHADJ 4
2182*a9fa9459Szrj static const char * const tbl[] =
2183*a9fa9459Szrj {
2184*a9fa9459Szrj   "ABSOLUTE",
2185*a9fa9459Szrj   "HIGH",
2186*a9fa9459Szrj   "LOW",
2187*a9fa9459Szrj   "HIGHLOW",
2188*a9fa9459Szrj   "HIGHADJ",
2189*a9fa9459Szrj   "MIPS_JMPADDR",
2190*a9fa9459Szrj   "SECTION",
2191*a9fa9459Szrj   "REL32",
2192*a9fa9459Szrj   "RESERVED1",
2193*a9fa9459Szrj   "MIPS_JMPADDR16",
2194*a9fa9459Szrj   "DIR64",
2195*a9fa9459Szrj   "HIGH3ADJ",
2196*a9fa9459Szrj   "UNKNOWN",   /* MUST be last.  */
2197*a9fa9459Szrj };
2198*a9fa9459Szrj 
2199*a9fa9459Szrj static bfd_boolean
pe_print_reloc(bfd * abfd,void * vfile)2200*a9fa9459Szrj pe_print_reloc (bfd * abfd, void * vfile)
2201*a9fa9459Szrj {
2202*a9fa9459Szrj   FILE *file = (FILE *) vfile;
2203*a9fa9459Szrj   bfd_byte *data = 0;
2204*a9fa9459Szrj   asection *section = bfd_get_section_by_name (abfd, ".reloc");
2205*a9fa9459Szrj   bfd_byte *p, *end;
2206*a9fa9459Szrj 
2207*a9fa9459Szrj   if (section == NULL || section->size == 0 || !(section->flags & SEC_HAS_CONTENTS))
2208*a9fa9459Szrj     return TRUE;
2209*a9fa9459Szrj 
2210*a9fa9459Szrj   fprintf (file,
2211*a9fa9459Szrj 	   _("\n\nPE File Base Relocations (interpreted .reloc section contents)\n"));
2212*a9fa9459Szrj 
2213*a9fa9459Szrj   if (! bfd_malloc_and_get_section (abfd, section, &data))
2214*a9fa9459Szrj     {
2215*a9fa9459Szrj       if (data != NULL)
2216*a9fa9459Szrj 	free (data);
2217*a9fa9459Szrj       return FALSE;
2218*a9fa9459Szrj     }
2219*a9fa9459Szrj 
2220*a9fa9459Szrj   p = data;
2221*a9fa9459Szrj   end = data + section->size;
2222*a9fa9459Szrj   while (p + 8 <= end)
2223*a9fa9459Szrj     {
2224*a9fa9459Szrj       int j;
2225*a9fa9459Szrj       bfd_vma virtual_address;
2226*a9fa9459Szrj       unsigned long number, size;
2227*a9fa9459Szrj       bfd_byte *chunk_end;
2228*a9fa9459Szrj 
2229*a9fa9459Szrj       /* The .reloc section is a sequence of blocks, with a header consisting
2230*a9fa9459Szrj 	 of two 32 bit quantities, followed by a number of 16 bit entries.  */
2231*a9fa9459Szrj       virtual_address = bfd_get_32 (abfd, p);
2232*a9fa9459Szrj       size = bfd_get_32 (abfd, p + 4);
2233*a9fa9459Szrj       p += 8;
2234*a9fa9459Szrj       number = (size - 8) / 2;
2235*a9fa9459Szrj 
2236*a9fa9459Szrj       if (size == 0)
2237*a9fa9459Szrj 	break;
2238*a9fa9459Szrj 
2239*a9fa9459Szrj       fprintf (file,
2240*a9fa9459Szrj 	       _("\nVirtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n"),
2241*a9fa9459Szrj 	       (unsigned long) virtual_address, size, size, number);
2242*a9fa9459Szrj 
2243*a9fa9459Szrj       chunk_end = p + size;
2244*a9fa9459Szrj       if (chunk_end > end)
2245*a9fa9459Szrj 	chunk_end = end;
2246*a9fa9459Szrj       j = 0;
2247*a9fa9459Szrj       while (p + 2 <= chunk_end)
2248*a9fa9459Szrj 	{
2249*a9fa9459Szrj 	  unsigned short e = bfd_get_16 (abfd, p);
2250*a9fa9459Szrj 	  unsigned int t = (e & 0xF000) >> 12;
2251*a9fa9459Szrj 	  int off = e & 0x0FFF;
2252*a9fa9459Szrj 
2253*a9fa9459Szrj 	  if (t >= sizeof (tbl) / sizeof (tbl[0]))
2254*a9fa9459Szrj 	    t = (sizeof (tbl) / sizeof (tbl[0])) - 1;
2255*a9fa9459Szrj 
2256*a9fa9459Szrj 	  fprintf (file,
2257*a9fa9459Szrj 		   _("\treloc %4d offset %4x [%4lx] %s"),
2258*a9fa9459Szrj 		   j, off, (unsigned long) (off + virtual_address), tbl[t]);
2259*a9fa9459Szrj 
2260*a9fa9459Szrj 	  p += 2;
2261*a9fa9459Szrj 	  j++;
2262*a9fa9459Szrj 
2263*a9fa9459Szrj 	  /* HIGHADJ takes an argument, - the next record *is* the
2264*a9fa9459Szrj 	     low 16 bits of addend.  */
2265*a9fa9459Szrj 	  if (t == IMAGE_REL_BASED_HIGHADJ && p + 2 <= chunk_end)
2266*a9fa9459Szrj 	    {
2267*a9fa9459Szrj 	      fprintf (file, " (%4x)", (unsigned int) bfd_get_16 (abfd, p));
2268*a9fa9459Szrj 	      p += 2;
2269*a9fa9459Szrj 	      j++;
2270*a9fa9459Szrj 	    }
2271*a9fa9459Szrj 
2272*a9fa9459Szrj 	  fprintf (file, "\n");
2273*a9fa9459Szrj 	}
2274*a9fa9459Szrj     }
2275*a9fa9459Szrj 
2276*a9fa9459Szrj   free (data);
2277*a9fa9459Szrj 
2278*a9fa9459Szrj   return TRUE;
2279*a9fa9459Szrj }
2280*a9fa9459Szrj 
2281*a9fa9459Szrj /* A data structure describing the regions of a .rsrc section.
2282*a9fa9459Szrj    Some fields are filled in as the section is parsed.  */
2283*a9fa9459Szrj 
2284*a9fa9459Szrj typedef struct rsrc_regions
2285*a9fa9459Szrj {
2286*a9fa9459Szrj   bfd_byte * section_start;
2287*a9fa9459Szrj   bfd_byte * section_end;
2288*a9fa9459Szrj   bfd_byte * strings_start;
2289*a9fa9459Szrj   bfd_byte * resource_start;
2290*a9fa9459Szrj } rsrc_regions;
2291*a9fa9459Szrj 
2292*a9fa9459Szrj static bfd_byte *
2293*a9fa9459Szrj rsrc_print_resource_directory (FILE * , bfd *, unsigned int, bfd_byte *,
2294*a9fa9459Szrj 			       rsrc_regions *, bfd_vma);
2295*a9fa9459Szrj 
2296*a9fa9459Szrj /* Print the resource entry at DATA, with the text indented by INDENT.
2297*a9fa9459Szrj    Recusively calls rsrc_print_resource_directory to print the contents
2298*a9fa9459Szrj    of directory entries.
2299*a9fa9459Szrj    Returns the address of the end of the data associated with the entry
2300*a9fa9459Szrj    or section_end + 1 upon failure.  */
2301*a9fa9459Szrj 
2302*a9fa9459Szrj static bfd_byte *
rsrc_print_resource_entries(FILE * file,bfd * abfd,unsigned int indent,bfd_boolean is_name,bfd_byte * data,rsrc_regions * regions,bfd_vma rva_bias)2303*a9fa9459Szrj rsrc_print_resource_entries (FILE *         file,
2304*a9fa9459Szrj 			     bfd *          abfd,
2305*a9fa9459Szrj 			     unsigned int   indent,
2306*a9fa9459Szrj 			     bfd_boolean    is_name,
2307*a9fa9459Szrj 			     bfd_byte *     data,
2308*a9fa9459Szrj 			     rsrc_regions * regions,
2309*a9fa9459Szrj 			     bfd_vma        rva_bias)
2310*a9fa9459Szrj {
2311*a9fa9459Szrj   unsigned long entry, addr, size;
2312*a9fa9459Szrj   bfd_byte * leaf;
2313*a9fa9459Szrj 
2314*a9fa9459Szrj   if (data + 8 >= regions->section_end)
2315*a9fa9459Szrj     return regions->section_end + 1;
2316*a9fa9459Szrj 
2317*a9fa9459Szrj   fprintf (file, _("%03x %*.s Entry: "), (int)(data - regions->section_start), indent, " ");
2318*a9fa9459Szrj 
2319*a9fa9459Szrj   entry = (unsigned long) bfd_get_32 (abfd, data);
2320*a9fa9459Szrj   if (is_name)
2321*a9fa9459Szrj     {
2322*a9fa9459Szrj       bfd_byte * name;
2323*a9fa9459Szrj 
2324*a9fa9459Szrj       /* Note - the documentation says that this field is an RVA value
2325*a9fa9459Szrj 	 but windres appears to produce a section relative offset with
2326*a9fa9459Szrj 	 the top bit set.  Support both styles for now.  */
2327*a9fa9459Szrj       if (HighBitSet (entry))
2328*a9fa9459Szrj 	name = regions->section_start + WithoutHighBit (entry);
2329*a9fa9459Szrj       else
2330*a9fa9459Szrj 	name = regions->section_start + entry - rva_bias;
2331*a9fa9459Szrj 
2332*a9fa9459Szrj       if (name + 2 < regions->section_end && name > regions->section_start)
2333*a9fa9459Szrj 	{
2334*a9fa9459Szrj 	  unsigned int len;
2335*a9fa9459Szrj 
2336*a9fa9459Szrj 	  if (regions->strings_start == NULL)
2337*a9fa9459Szrj 	    regions->strings_start = name;
2338*a9fa9459Szrj 
2339*a9fa9459Szrj 	  len = bfd_get_16 (abfd, name);
2340*a9fa9459Szrj 
2341*a9fa9459Szrj 	  fprintf (file, _("name: [val: %08lx len %d]: "), entry, len);
2342*a9fa9459Szrj 
2343*a9fa9459Szrj 	  if (name + 2 + len * 2 < regions->section_end)
2344*a9fa9459Szrj 	    {
2345*a9fa9459Szrj 	      /* This strange loop is to cope with multibyte characters.  */
2346*a9fa9459Szrj 	      while (len --)
2347*a9fa9459Szrj 		{
2348*a9fa9459Szrj 		  char c;
2349*a9fa9459Szrj 
2350*a9fa9459Szrj 		  name += 2;
2351*a9fa9459Szrj 		  c = * name;
2352*a9fa9459Szrj 		  /* Avoid printing control characters.  */
2353*a9fa9459Szrj 		  if (c > 0 && c < 32)
2354*a9fa9459Szrj 		    fprintf (file, "^%c", c + 64);
2355*a9fa9459Szrj 		  else
2356*a9fa9459Szrj 		    fprintf (file, "%.1s", name);
2357*a9fa9459Szrj 		}
2358*a9fa9459Szrj 	    }
2359*a9fa9459Szrj 	  else
2360*a9fa9459Szrj 	    {
2361*a9fa9459Szrj 	      fprintf (file, _("<corrupt string length: %#x>\n"), len);
2362*a9fa9459Szrj 	      /* PR binutils/17512: Do not try to continue decoding a
2363*a9fa9459Szrj 		 corrupted resource section.  It is likely to end up with
2364*a9fa9459Szrj 		 reams of extraneous output.  FIXME: We could probably
2365*a9fa9459Szrj 		 continue if we disable the printing of strings...  */
2366*a9fa9459Szrj 	      return regions->section_end + 1;
2367*a9fa9459Szrj 	    }
2368*a9fa9459Szrj 	}
2369*a9fa9459Szrj       else
2370*a9fa9459Szrj 	{
2371*a9fa9459Szrj 	  fprintf (file, _("<corrupt string offset: %#lx>\n"), entry);
2372*a9fa9459Szrj 	  return regions->section_end + 1;
2373*a9fa9459Szrj 	}
2374*a9fa9459Szrj     }
2375*a9fa9459Szrj   else
2376*a9fa9459Szrj     fprintf (file, _("ID: %#08lx"), entry);
2377*a9fa9459Szrj 
2378*a9fa9459Szrj   entry = (long) bfd_get_32 (abfd, data + 4);
2379*a9fa9459Szrj   fprintf (file, _(", Value: %#08lx\n"), entry);
2380*a9fa9459Szrj 
2381*a9fa9459Szrj   if (HighBitSet  (entry))
2382*a9fa9459Szrj     {
2383*a9fa9459Szrj       data = regions->section_start + WithoutHighBit (entry);
2384*a9fa9459Szrj       if (data <= regions->section_start || data > regions->section_end)
2385*a9fa9459Szrj 	return regions->section_end + 1;
2386*a9fa9459Szrj 
2387*a9fa9459Szrj       /* FIXME: PR binutils/17512: A corrupt file could contain a loop
2388*a9fa9459Szrj 	 in the resource table.  We need some way to detect this.  */
2389*a9fa9459Szrj       return rsrc_print_resource_directory (file, abfd, indent + 1, data,
2390*a9fa9459Szrj 					    regions, rva_bias);
2391*a9fa9459Szrj     }
2392*a9fa9459Szrj 
2393*a9fa9459Szrj   leaf = regions->section_start + entry;
2394*a9fa9459Szrj 
2395*a9fa9459Szrj   if (leaf + 16 >= regions->section_end
2396*a9fa9459Szrj       /* PR 17512: file: 055dff7e.  */
2397*a9fa9459Szrj       || leaf < regions->section_start)
2398*a9fa9459Szrj     return regions->section_end + 1;
2399*a9fa9459Szrj 
2400*a9fa9459Szrj   fprintf (file, _("%03x %*.s  Leaf: Addr: %#08lx, Size: %#08lx, Codepage: %d\n"),
2401*a9fa9459Szrj 	   (int) (entry), indent, " ",
2402*a9fa9459Szrj 	   addr = (long) bfd_get_32 (abfd, leaf),
2403*a9fa9459Szrj 	   size = (long) bfd_get_32 (abfd, leaf + 4),
2404*a9fa9459Szrj 	   (int) bfd_get_32 (abfd, leaf + 8));
2405*a9fa9459Szrj 
2406*a9fa9459Szrj   /* Check that the reserved entry is 0.  */
2407*a9fa9459Szrj   if (bfd_get_32 (abfd, leaf + 12) != 0
2408*a9fa9459Szrj       /* And that the data address/size is valid too.  */
2409*a9fa9459Szrj       || (regions->section_start + (addr - rva_bias) + size > regions->section_end))
2410*a9fa9459Szrj     return regions->section_end + 1;
2411*a9fa9459Szrj 
2412*a9fa9459Szrj   if (regions->resource_start == NULL)
2413*a9fa9459Szrj     regions->resource_start = regions->section_start + (addr - rva_bias);
2414*a9fa9459Szrj 
2415*a9fa9459Szrj   return regions->section_start + (addr - rva_bias) + size;
2416*a9fa9459Szrj }
2417*a9fa9459Szrj 
2418*a9fa9459Szrj #define max(a,b) ((a) > (b) ? (a) : (b))
2419*a9fa9459Szrj #define min(a,b) ((a) < (b) ? (a) : (b))
2420*a9fa9459Szrj 
2421*a9fa9459Szrj static bfd_byte *
rsrc_print_resource_directory(FILE * file,bfd * abfd,unsigned int indent,bfd_byte * data,rsrc_regions * regions,bfd_vma rva_bias)2422*a9fa9459Szrj rsrc_print_resource_directory (FILE *         file,
2423*a9fa9459Szrj 			       bfd *          abfd,
2424*a9fa9459Szrj 			       unsigned int   indent,
2425*a9fa9459Szrj 			       bfd_byte *     data,
2426*a9fa9459Szrj 			       rsrc_regions * regions,
2427*a9fa9459Szrj 			       bfd_vma        rva_bias)
2428*a9fa9459Szrj {
2429*a9fa9459Szrj   unsigned int num_names, num_ids;
2430*a9fa9459Szrj   bfd_byte * highest_data = data;
2431*a9fa9459Szrj 
2432*a9fa9459Szrj   if (data + 16 >= regions->section_end)
2433*a9fa9459Szrj     return regions->section_end + 1;
2434*a9fa9459Szrj 
2435*a9fa9459Szrj   fprintf (file, "%03x %*.s ", (int)(data - regions->section_start), indent, " ");
2436*a9fa9459Szrj   switch (indent)
2437*a9fa9459Szrj     {
2438*a9fa9459Szrj     case 0: fprintf (file, "Type"); break;
2439*a9fa9459Szrj     case 2: fprintf (file, "Name"); break;
2440*a9fa9459Szrj     case 4: fprintf (file, "Language"); break;
2441*a9fa9459Szrj     default:
2442*a9fa9459Szrj       fprintf (file, _("<unknown directory type: %d>\n"), indent);
2443*a9fa9459Szrj       /* FIXME: For now we end the printing here.  If in the
2444*a9fa9459Szrj 	 future more directory types are added to the RSRC spec
2445*a9fa9459Szrj 	 then we will need to change this.  */
2446*a9fa9459Szrj       return regions->section_end + 1;
2447*a9fa9459Szrj     }
2448*a9fa9459Szrj 
2449*a9fa9459Szrj   fprintf (file, _(" Table: Char: %d, Time: %08lx, Ver: %d/%d, Num Names: %d, IDs: %d\n"),
2450*a9fa9459Szrj 	   (int) bfd_get_32 (abfd, data),
2451*a9fa9459Szrj 	   (long) bfd_get_32 (abfd, data + 4),
2452*a9fa9459Szrj 	   (int)  bfd_get_16 (abfd, data + 8),
2453*a9fa9459Szrj 	   (int)  bfd_get_16 (abfd, data + 10),
2454*a9fa9459Szrj 	   num_names = (int) bfd_get_16 (abfd, data + 12),
2455*a9fa9459Szrj 	   num_ids =   (int) bfd_get_16 (abfd, data + 14));
2456*a9fa9459Szrj   data += 16;
2457*a9fa9459Szrj 
2458*a9fa9459Szrj   while (num_names --)
2459*a9fa9459Szrj     {
2460*a9fa9459Szrj       bfd_byte * entry_end;
2461*a9fa9459Szrj 
2462*a9fa9459Szrj       entry_end = rsrc_print_resource_entries (file, abfd, indent + 1, TRUE,
2463*a9fa9459Szrj 					       data, regions, rva_bias);
2464*a9fa9459Szrj       data += 8;
2465*a9fa9459Szrj       highest_data = max (highest_data, entry_end);
2466*a9fa9459Szrj       if (entry_end >= regions->section_end)
2467*a9fa9459Szrj 	return entry_end;
2468*a9fa9459Szrj     }
2469*a9fa9459Szrj 
2470*a9fa9459Szrj   while (num_ids --)
2471*a9fa9459Szrj     {
2472*a9fa9459Szrj       bfd_byte * entry_end;
2473*a9fa9459Szrj 
2474*a9fa9459Szrj       entry_end = rsrc_print_resource_entries (file, abfd, indent + 1, FALSE,
2475*a9fa9459Szrj 					       data, regions, rva_bias);
2476*a9fa9459Szrj       data += 8;
2477*a9fa9459Szrj       highest_data = max (highest_data, entry_end);
2478*a9fa9459Szrj       if (entry_end >= regions->section_end)
2479*a9fa9459Szrj 	return entry_end;
2480*a9fa9459Szrj     }
2481*a9fa9459Szrj 
2482*a9fa9459Szrj   return max (highest_data, data);
2483*a9fa9459Szrj }
2484*a9fa9459Szrj 
2485*a9fa9459Szrj /* Display the contents of a .rsrc section.  We do not try to
2486*a9fa9459Szrj    reproduce the resources, windres does that.  Instead we dump
2487*a9fa9459Szrj    the tables in a human readable format.  */
2488*a9fa9459Szrj 
2489*a9fa9459Szrj static bfd_boolean
rsrc_print_section(bfd * abfd,void * vfile)2490*a9fa9459Szrj rsrc_print_section (bfd * abfd, void * vfile)
2491*a9fa9459Szrj {
2492*a9fa9459Szrj   bfd_vma rva_bias;
2493*a9fa9459Szrj   pe_data_type * pe;
2494*a9fa9459Szrj   FILE * file = (FILE *) vfile;
2495*a9fa9459Szrj   bfd_size_type datasize;
2496*a9fa9459Szrj   asection * section;
2497*a9fa9459Szrj   bfd_byte * data;
2498*a9fa9459Szrj   rsrc_regions regions;
2499*a9fa9459Szrj 
2500*a9fa9459Szrj   pe = pe_data (abfd);
2501*a9fa9459Szrj   if (pe == NULL)
2502*a9fa9459Szrj     return TRUE;
2503*a9fa9459Szrj 
2504*a9fa9459Szrj   section = bfd_get_section_by_name (abfd, ".rsrc");
2505*a9fa9459Szrj   if (section == NULL)
2506*a9fa9459Szrj     return TRUE;
2507*a9fa9459Szrj   if (!(section->flags & SEC_HAS_CONTENTS))
2508*a9fa9459Szrj     return TRUE;
2509*a9fa9459Szrj 
2510*a9fa9459Szrj   datasize = section->size;
2511*a9fa9459Szrj   if (datasize == 0)
2512*a9fa9459Szrj     return TRUE;
2513*a9fa9459Szrj 
2514*a9fa9459Szrj   rva_bias = section->vma - pe->pe_opthdr.ImageBase;
2515*a9fa9459Szrj 
2516*a9fa9459Szrj   if (! bfd_malloc_and_get_section (abfd, section, & data))
2517*a9fa9459Szrj     {
2518*a9fa9459Szrj       if (data != NULL)
2519*a9fa9459Szrj 	free (data);
2520*a9fa9459Szrj       return FALSE;
2521*a9fa9459Szrj     }
2522*a9fa9459Szrj 
2523*a9fa9459Szrj   regions.section_start = data;
2524*a9fa9459Szrj   regions.section_end = data + datasize;
2525*a9fa9459Szrj   regions.strings_start = NULL;
2526*a9fa9459Szrj   regions.resource_start = NULL;
2527*a9fa9459Szrj 
2528*a9fa9459Szrj   fflush (file);
2529*a9fa9459Szrj   fprintf (file, "\nThe .rsrc Resource Directory section:\n");
2530*a9fa9459Szrj 
2531*a9fa9459Szrj   while (data < regions.section_end)
2532*a9fa9459Szrj     {
2533*a9fa9459Szrj       bfd_byte * p = data;
2534*a9fa9459Szrj 
2535*a9fa9459Szrj       data = rsrc_print_resource_directory (file, abfd, 0, data, & regions, rva_bias);
2536*a9fa9459Szrj 
2537*a9fa9459Szrj       if (data == regions.section_end + 1)
2538*a9fa9459Szrj 	fprintf (file, _("Corrupt .rsrc section detected!\n"));
2539*a9fa9459Szrj       else
2540*a9fa9459Szrj 	{
2541*a9fa9459Szrj 	  /* Align data before continuing.  */
2542*a9fa9459Szrj 	  int align = (1 << section->alignment_power) - 1;
2543*a9fa9459Szrj 
2544*a9fa9459Szrj 	  data = (bfd_byte *) (((ptrdiff_t) (data + align)) & ~ align);
2545*a9fa9459Szrj 	  rva_bias += data - p;
2546*a9fa9459Szrj 
2547*a9fa9459Szrj 	  /* For reasons that are unclear .rsrc sections are sometimes created
2548*a9fa9459Szrj 	     aligned to a 1^3 boundary even when their alignment is set at
2549*a9fa9459Szrj 	     1^2.  Catch that case here before we issue a spurious warning
2550*a9fa9459Szrj 	     message.  */
2551*a9fa9459Szrj 	  if (data == (regions.section_end - 4))
2552*a9fa9459Szrj 	    data = regions.section_end;
2553*a9fa9459Szrj 	  else if (data < regions.section_end)
2554*a9fa9459Szrj 	    {
2555*a9fa9459Szrj 	      /* If the extra data is all zeros then do not complain.
2556*a9fa9459Szrj 		 This is just padding so that the section meets the
2557*a9fa9459Szrj 		 page size requirements.  */
2558*a9fa9459Szrj 	      while (++ data < regions.section_end)
2559*a9fa9459Szrj 		if (*data != 0)
2560*a9fa9459Szrj 		  break;
2561*a9fa9459Szrj 	      if (data < regions.section_end)
2562*a9fa9459Szrj 		fprintf (file, _("\nWARNING: Extra data in .rsrc section - it will be ignored by Windows:\n"));
2563*a9fa9459Szrj 	    }
2564*a9fa9459Szrj 	}
2565*a9fa9459Szrj     }
2566*a9fa9459Szrj 
2567*a9fa9459Szrj   if (regions.strings_start != NULL)
2568*a9fa9459Szrj     fprintf (file, " String table starts at offset: %#03x\n",
2569*a9fa9459Szrj 	     (int) (regions.strings_start - regions.section_start));
2570*a9fa9459Szrj   if (regions.resource_start != NULL)
2571*a9fa9459Szrj     fprintf (file, " Resources start at offset: %#03x\n",
2572*a9fa9459Szrj 	     (int) (regions.resource_start - regions.section_start));
2573*a9fa9459Szrj 
2574*a9fa9459Szrj   free (regions.section_start);
2575*a9fa9459Szrj   return TRUE;
2576*a9fa9459Szrj }
2577*a9fa9459Szrj 
2578*a9fa9459Szrj #define IMAGE_NUMBEROF_DEBUG_TYPES 12
2579*a9fa9459Szrj 
2580*a9fa9459Szrj static char * debug_type_names[IMAGE_NUMBEROF_DEBUG_TYPES] =
2581*a9fa9459Szrj {
2582*a9fa9459Szrj   "Unknown",
2583*a9fa9459Szrj   "COFF",
2584*a9fa9459Szrj   "CodeView",
2585*a9fa9459Szrj   "FPO",
2586*a9fa9459Szrj   "Misc",
2587*a9fa9459Szrj   "Exception",
2588*a9fa9459Szrj   "Fixup",
2589*a9fa9459Szrj   "OMAP-to-SRC",
2590*a9fa9459Szrj   "OMAP-from-SRC",
2591*a9fa9459Szrj   "Borland",
2592*a9fa9459Szrj   "Reserved",
2593*a9fa9459Szrj   "CLSID",
2594*a9fa9459Szrj };
2595*a9fa9459Szrj 
2596*a9fa9459Szrj static bfd_boolean
pe_print_debugdata(bfd * abfd,void * vfile)2597*a9fa9459Szrj pe_print_debugdata (bfd * abfd, void * vfile)
2598*a9fa9459Szrj {
2599*a9fa9459Szrj   FILE *file = (FILE *) vfile;
2600*a9fa9459Szrj   pe_data_type *pe = pe_data (abfd);
2601*a9fa9459Szrj   struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
2602*a9fa9459Szrj   asection *section;
2603*a9fa9459Szrj   bfd_byte *data = 0;
2604*a9fa9459Szrj   bfd_size_type dataoff;
2605*a9fa9459Szrj   unsigned int i;
2606*a9fa9459Szrj 
2607*a9fa9459Szrj   bfd_vma addr = extra->DataDirectory[PE_DEBUG_DATA].VirtualAddress;
2608*a9fa9459Szrj   bfd_size_type size = extra->DataDirectory[PE_DEBUG_DATA].Size;
2609*a9fa9459Szrj 
2610*a9fa9459Szrj   if (size == 0)
2611*a9fa9459Szrj     return TRUE;
2612*a9fa9459Szrj 
2613*a9fa9459Szrj   addr += extra->ImageBase;
2614*a9fa9459Szrj   for (section = abfd->sections; section != NULL; section = section->next)
2615*a9fa9459Szrj     {
2616*a9fa9459Szrj       if ((addr >= section->vma) && (addr < (section->vma + section->size)))
2617*a9fa9459Szrj         break;
2618*a9fa9459Szrj     }
2619*a9fa9459Szrj 
2620*a9fa9459Szrj   if (section == NULL)
2621*a9fa9459Szrj     {
2622*a9fa9459Szrj       fprintf (file,
2623*a9fa9459Szrj                _("\nThere is a debug directory, but the section containing it could not be found\n"));
2624*a9fa9459Szrj       return TRUE;
2625*a9fa9459Szrj     }
2626*a9fa9459Szrj   else if (!(section->flags & SEC_HAS_CONTENTS))
2627*a9fa9459Szrj     {
2628*a9fa9459Szrj       fprintf (file,
2629*a9fa9459Szrj                _("\nThere is a debug directory in %s, but that section has no contents\n"),
2630*a9fa9459Szrj                section->name);
2631*a9fa9459Szrj       return TRUE;
2632*a9fa9459Szrj     }
2633*a9fa9459Szrj   else if (section->size < size)
2634*a9fa9459Szrj     {
2635*a9fa9459Szrj       fprintf (file,
2636*a9fa9459Szrj                _("\nError: section %s contains the debug data starting address but it is too small\n"),
2637*a9fa9459Szrj                section->name);
2638*a9fa9459Szrj       return FALSE;
2639*a9fa9459Szrj     }
2640*a9fa9459Szrj 
2641*a9fa9459Szrj   fprintf (file, _("\nThere is a debug directory in %s at 0x%lx\n\n"),
2642*a9fa9459Szrj 	   section->name, (unsigned long) addr);
2643*a9fa9459Szrj 
2644*a9fa9459Szrj   dataoff = addr - section->vma;
2645*a9fa9459Szrj 
2646*a9fa9459Szrj   if (size > (section->size - dataoff))
2647*a9fa9459Szrj     {
2648*a9fa9459Szrj       fprintf (file, _("The debug data size field in the data directory is too big for the section"));
2649*a9fa9459Szrj       return FALSE;
2650*a9fa9459Szrj     }
2651*a9fa9459Szrj 
2652*a9fa9459Szrj   fprintf (file,
2653*a9fa9459Szrj 	   _("Type                Size     Rva      Offset\n"));
2654*a9fa9459Szrj 
2655*a9fa9459Szrj   /* Read the whole section.  */
2656*a9fa9459Szrj   if (!bfd_malloc_and_get_section (abfd, section, &data))
2657*a9fa9459Szrj     {
2658*a9fa9459Szrj       if (data != NULL)
2659*a9fa9459Szrj 	free (data);
2660*a9fa9459Szrj       return FALSE;
2661*a9fa9459Szrj     }
2662*a9fa9459Szrj 
2663*a9fa9459Szrj   for (i = 0; i < size / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++)
2664*a9fa9459Szrj     {
2665*a9fa9459Szrj       const char *type_name;
2666*a9fa9459Szrj       struct external_IMAGE_DEBUG_DIRECTORY *ext
2667*a9fa9459Szrj 	= &((struct external_IMAGE_DEBUG_DIRECTORY *)(data + dataoff))[i];
2668*a9fa9459Szrj       struct internal_IMAGE_DEBUG_DIRECTORY idd;
2669*a9fa9459Szrj 
2670*a9fa9459Szrj       _bfd_XXi_swap_debugdir_in (abfd, ext, &idd);
2671*a9fa9459Szrj 
2672*a9fa9459Szrj       if ((idd.Type) >= IMAGE_NUMBEROF_DEBUG_TYPES)
2673*a9fa9459Szrj         type_name = debug_type_names[0];
2674*a9fa9459Szrj       else
2675*a9fa9459Szrj         type_name = debug_type_names[idd.Type];
2676*a9fa9459Szrj 
2677*a9fa9459Szrj       fprintf (file, " %2ld  %14s %08lx %08lx %08lx\n",
2678*a9fa9459Szrj 	       idd.Type, type_name, idd.SizeOfData,
2679*a9fa9459Szrj 	       idd.AddressOfRawData, idd.PointerToRawData);
2680*a9fa9459Szrj 
2681*a9fa9459Szrj       if (idd.Type == PE_IMAGE_DEBUG_TYPE_CODEVIEW)
2682*a9fa9459Szrj         {
2683*a9fa9459Szrj           char signature[CV_INFO_SIGNATURE_LENGTH * 2 + 1];
2684*a9fa9459Szrj 	  /* PR 17512: file: 065-29434-0.001:0.1
2685*a9fa9459Szrj 	     We need to use a 32-bit aligned buffer
2686*a9fa9459Szrj 	     to safely read in a codeview record.  */
2687*a9fa9459Szrj           char buffer[256 + 1] ATTRIBUTE_ALIGNED_ALIGNOF (CODEVIEW_INFO);
2688*a9fa9459Szrj 
2689*a9fa9459Szrj           CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer;
2690*a9fa9459Szrj 
2691*a9fa9459Szrj           /* The debug entry doesn't have to have to be in a section,
2692*a9fa9459Szrj 	     in which case AddressOfRawData is 0, so always use PointerToRawData.  */
2693*a9fa9459Szrj           if (!_bfd_XXi_slurp_codeview_record (abfd, (file_ptr) idd.PointerToRawData,
2694*a9fa9459Szrj 					       idd.SizeOfData, cvinfo))
2695*a9fa9459Szrj             continue;
2696*a9fa9459Szrj 
2697*a9fa9459Szrj           for (i = 0; i < cvinfo->SignatureLength; i++)
2698*a9fa9459Szrj             sprintf (&signature[i*2], "%02x", cvinfo->Signature[i] & 0xff);
2699*a9fa9459Szrj 
2700*a9fa9459Szrj           fprintf (file, "(format %c%c%c%c signature %s age %ld)\n",
2701*a9fa9459Szrj 		   buffer[0], buffer[1], buffer[2], buffer[3],
2702*a9fa9459Szrj 		   signature, cvinfo->Age);
2703*a9fa9459Szrj         }
2704*a9fa9459Szrj     }
2705*a9fa9459Szrj 
2706*a9fa9459Szrj   if (size % sizeof (struct external_IMAGE_DEBUG_DIRECTORY) != 0)
2707*a9fa9459Szrj     fprintf (file,
2708*a9fa9459Szrj             _("The debug directory size is not a multiple of the debug directory entry size\n"));
2709*a9fa9459Szrj 
2710*a9fa9459Szrj   return TRUE;
2711*a9fa9459Szrj }
2712*a9fa9459Szrj 
2713*a9fa9459Szrj /* Print out the program headers.  */
2714*a9fa9459Szrj 
2715*a9fa9459Szrj bfd_boolean
_bfd_XX_print_private_bfd_data_common(bfd * abfd,void * vfile)2716*a9fa9459Szrj _bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile)
2717*a9fa9459Szrj {
2718*a9fa9459Szrj   FILE *file = (FILE *) vfile;
2719*a9fa9459Szrj   int j;
2720*a9fa9459Szrj   pe_data_type *pe = pe_data (abfd);
2721*a9fa9459Szrj   struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr;
2722*a9fa9459Szrj   const char *subsystem_name = NULL;
2723*a9fa9459Szrj   const char *name;
2724*a9fa9459Szrj 
2725*a9fa9459Szrj   /* The MS dumpbin program reportedly ands with 0xff0f before
2726*a9fa9459Szrj      printing the characteristics field.  Not sure why.  No reason to
2727*a9fa9459Szrj      emulate it here.  */
2728*a9fa9459Szrj   fprintf (file, _("\nCharacteristics 0x%x\n"), pe->real_flags);
2729*a9fa9459Szrj #undef PF
2730*a9fa9459Szrj #define PF(x, y) if (pe->real_flags & x) { fprintf (file, "\t%s\n", y); }
2731*a9fa9459Szrj   PF (IMAGE_FILE_RELOCS_STRIPPED, "relocations stripped");
2732*a9fa9459Szrj   PF (IMAGE_FILE_EXECUTABLE_IMAGE, "executable");
2733*a9fa9459Szrj   PF (IMAGE_FILE_LINE_NUMS_STRIPPED, "line numbers stripped");
2734*a9fa9459Szrj   PF (IMAGE_FILE_LOCAL_SYMS_STRIPPED, "symbols stripped");
2735*a9fa9459Szrj   PF (IMAGE_FILE_LARGE_ADDRESS_AWARE, "large address aware");
2736*a9fa9459Szrj   PF (IMAGE_FILE_BYTES_REVERSED_LO, "little endian");
2737*a9fa9459Szrj   PF (IMAGE_FILE_32BIT_MACHINE, "32 bit words");
2738*a9fa9459Szrj   PF (IMAGE_FILE_DEBUG_STRIPPED, "debugging information removed");
2739*a9fa9459Szrj   PF (IMAGE_FILE_SYSTEM, "system file");
2740*a9fa9459Szrj   PF (IMAGE_FILE_DLL, "DLL");
2741*a9fa9459Szrj   PF (IMAGE_FILE_BYTES_REVERSED_HI, "big endian");
2742*a9fa9459Szrj #undef PF
2743*a9fa9459Szrj 
2744*a9fa9459Szrj   /* ctime implies '\n'.  */
2745*a9fa9459Szrj   {
2746*a9fa9459Szrj     time_t t = pe->coff.timestamp;
2747*a9fa9459Szrj     fprintf (file, "\nTime/Date\t\t%s", ctime (&t));
2748*a9fa9459Szrj   }
2749*a9fa9459Szrj 
2750*a9fa9459Szrj #ifndef IMAGE_NT_OPTIONAL_HDR_MAGIC
2751*a9fa9459Szrj # define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
2752*a9fa9459Szrj #endif
2753*a9fa9459Szrj #ifndef IMAGE_NT_OPTIONAL_HDR64_MAGIC
2754*a9fa9459Szrj # define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
2755*a9fa9459Szrj #endif
2756*a9fa9459Szrj #ifndef IMAGE_NT_OPTIONAL_HDRROM_MAGIC
2757*a9fa9459Szrj # define IMAGE_NT_OPTIONAL_HDRROM_MAGIC 0x107
2758*a9fa9459Szrj #endif
2759*a9fa9459Szrj 
2760*a9fa9459Szrj   switch (i->Magic)
2761*a9fa9459Szrj     {
2762*a9fa9459Szrj     case IMAGE_NT_OPTIONAL_HDR_MAGIC:
2763*a9fa9459Szrj       name = "PE32";
2764*a9fa9459Szrj       break;
2765*a9fa9459Szrj     case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
2766*a9fa9459Szrj       name = "PE32+";
2767*a9fa9459Szrj       break;
2768*a9fa9459Szrj     case IMAGE_NT_OPTIONAL_HDRROM_MAGIC:
2769*a9fa9459Szrj       name = "ROM";
2770*a9fa9459Szrj       break;
2771*a9fa9459Szrj     default:
2772*a9fa9459Szrj       name = NULL;
2773*a9fa9459Szrj       break;
2774*a9fa9459Szrj     }
2775*a9fa9459Szrj   fprintf (file, "Magic\t\t\t%04x", i->Magic);
2776*a9fa9459Szrj   if (name)
2777*a9fa9459Szrj     fprintf (file, "\t(%s)",name);
2778*a9fa9459Szrj   fprintf (file, "\nMajorLinkerVersion\t%d\n", i->MajorLinkerVersion);
2779*a9fa9459Szrj   fprintf (file, "MinorLinkerVersion\t%d\n", i->MinorLinkerVersion);
2780*a9fa9459Szrj   fprintf (file, "SizeOfCode\t\t%08lx\n", (unsigned long) i->SizeOfCode);
2781*a9fa9459Szrj   fprintf (file, "SizeOfInitializedData\t%08lx\n",
2782*a9fa9459Szrj 	   (unsigned long) i->SizeOfInitializedData);
2783*a9fa9459Szrj   fprintf (file, "SizeOfUninitializedData\t%08lx\n",
2784*a9fa9459Szrj 	   (unsigned long) i->SizeOfUninitializedData);
2785*a9fa9459Szrj   fprintf (file, "AddressOfEntryPoint\t");
2786*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->AddressOfEntryPoint);
2787*a9fa9459Szrj   fprintf (file, "\nBaseOfCode\t\t");
2788*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->BaseOfCode);
2789*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
2790*a9fa9459Szrj   /* PE32+ does not have BaseOfData member!  */
2791*a9fa9459Szrj   fprintf (file, "\nBaseOfData\t\t");
2792*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->BaseOfData);
2793*a9fa9459Szrj #endif
2794*a9fa9459Szrj 
2795*a9fa9459Szrj   fprintf (file, "\nImageBase\t\t");
2796*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->ImageBase);
2797*a9fa9459Szrj   fprintf (file, "\nSectionAlignment\t");
2798*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->SectionAlignment);
2799*a9fa9459Szrj   fprintf (file, "\nFileAlignment\t\t");
2800*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->FileAlignment);
2801*a9fa9459Szrj   fprintf (file, "\nMajorOSystemVersion\t%d\n", i->MajorOperatingSystemVersion);
2802*a9fa9459Szrj   fprintf (file, "MinorOSystemVersion\t%d\n", i->MinorOperatingSystemVersion);
2803*a9fa9459Szrj   fprintf (file, "MajorImageVersion\t%d\n", i->MajorImageVersion);
2804*a9fa9459Szrj   fprintf (file, "MinorImageVersion\t%d\n", i->MinorImageVersion);
2805*a9fa9459Szrj   fprintf (file, "MajorSubsystemVersion\t%d\n", i->MajorSubsystemVersion);
2806*a9fa9459Szrj   fprintf (file, "MinorSubsystemVersion\t%d\n", i->MinorSubsystemVersion);
2807*a9fa9459Szrj   fprintf (file, "Win32Version\t\t%08lx\n", (unsigned long) i->Reserved1);
2808*a9fa9459Szrj   fprintf (file, "SizeOfImage\t\t%08lx\n", (unsigned long) i->SizeOfImage);
2809*a9fa9459Szrj   fprintf (file, "SizeOfHeaders\t\t%08lx\n", (unsigned long) i->SizeOfHeaders);
2810*a9fa9459Szrj   fprintf (file, "CheckSum\t\t%08lx\n", (unsigned long) i->CheckSum);
2811*a9fa9459Szrj 
2812*a9fa9459Szrj   switch (i->Subsystem)
2813*a9fa9459Szrj     {
2814*a9fa9459Szrj     case IMAGE_SUBSYSTEM_UNKNOWN:
2815*a9fa9459Szrj       subsystem_name = "unspecified";
2816*a9fa9459Szrj       break;
2817*a9fa9459Szrj     case IMAGE_SUBSYSTEM_NATIVE:
2818*a9fa9459Szrj       subsystem_name = "NT native";
2819*a9fa9459Szrj       break;
2820*a9fa9459Szrj     case IMAGE_SUBSYSTEM_WINDOWS_GUI:
2821*a9fa9459Szrj       subsystem_name = "Windows GUI";
2822*a9fa9459Szrj       break;
2823*a9fa9459Szrj     case IMAGE_SUBSYSTEM_WINDOWS_CUI:
2824*a9fa9459Szrj       subsystem_name = "Windows CUI";
2825*a9fa9459Szrj       break;
2826*a9fa9459Szrj     case IMAGE_SUBSYSTEM_POSIX_CUI:
2827*a9fa9459Szrj       subsystem_name = "POSIX CUI";
2828*a9fa9459Szrj       break;
2829*a9fa9459Szrj     case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
2830*a9fa9459Szrj       subsystem_name = "Wince CUI";
2831*a9fa9459Szrj       break;
2832*a9fa9459Szrj     // These are from UEFI Platform Initialization Specification 1.1.
2833*a9fa9459Szrj     case IMAGE_SUBSYSTEM_EFI_APPLICATION:
2834*a9fa9459Szrj       subsystem_name = "EFI application";
2835*a9fa9459Szrj       break;
2836*a9fa9459Szrj     case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
2837*a9fa9459Szrj       subsystem_name = "EFI boot service driver";
2838*a9fa9459Szrj       break;
2839*a9fa9459Szrj     case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
2840*a9fa9459Szrj       subsystem_name = "EFI runtime driver";
2841*a9fa9459Szrj       break;
2842*a9fa9459Szrj     case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
2843*a9fa9459Szrj       subsystem_name = "SAL runtime driver";
2844*a9fa9459Szrj       break;
2845*a9fa9459Szrj     // This is from revision 8.0 of the MS PE/COFF spec
2846*a9fa9459Szrj     case IMAGE_SUBSYSTEM_XBOX:
2847*a9fa9459Szrj       subsystem_name = "XBOX";
2848*a9fa9459Szrj       break;
2849*a9fa9459Szrj     // Added default case for clarity - subsystem_name is NULL anyway.
2850*a9fa9459Szrj     default:
2851*a9fa9459Szrj       subsystem_name = NULL;
2852*a9fa9459Szrj     }
2853*a9fa9459Szrj 
2854*a9fa9459Szrj   fprintf (file, "Subsystem\t\t%08x", i->Subsystem);
2855*a9fa9459Szrj   if (subsystem_name)
2856*a9fa9459Szrj     fprintf (file, "\t(%s)", subsystem_name);
2857*a9fa9459Szrj   fprintf (file, "\nDllCharacteristics\t%08x\n", i->DllCharacteristics);
2858*a9fa9459Szrj   fprintf (file, "SizeOfStackReserve\t");
2859*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->SizeOfStackReserve);
2860*a9fa9459Szrj   fprintf (file, "\nSizeOfStackCommit\t");
2861*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->SizeOfStackCommit);
2862*a9fa9459Szrj   fprintf (file, "\nSizeOfHeapReserve\t");
2863*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->SizeOfHeapReserve);
2864*a9fa9459Szrj   fprintf (file, "\nSizeOfHeapCommit\t");
2865*a9fa9459Szrj   bfd_fprintf_vma (abfd, file, i->SizeOfHeapCommit);
2866*a9fa9459Szrj   fprintf (file, "\nLoaderFlags\t\t%08lx\n", (unsigned long) i->LoaderFlags);
2867*a9fa9459Szrj   fprintf (file, "NumberOfRvaAndSizes\t%08lx\n",
2868*a9fa9459Szrj 	   (unsigned long) i->NumberOfRvaAndSizes);
2869*a9fa9459Szrj 
2870*a9fa9459Szrj   fprintf (file, "\nThe Data Directory\n");
2871*a9fa9459Szrj   for (j = 0; j < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; j++)
2872*a9fa9459Szrj     {
2873*a9fa9459Szrj       fprintf (file, "Entry %1x ", j);
2874*a9fa9459Szrj       bfd_fprintf_vma (abfd, file, i->DataDirectory[j].VirtualAddress);
2875*a9fa9459Szrj       fprintf (file, " %08lx ", (unsigned long) i->DataDirectory[j].Size);
2876*a9fa9459Szrj       fprintf (file, "%s\n", dir_names[j]);
2877*a9fa9459Szrj     }
2878*a9fa9459Szrj 
2879*a9fa9459Szrj   pe_print_idata (abfd, vfile);
2880*a9fa9459Szrj   pe_print_edata (abfd, vfile);
2881*a9fa9459Szrj   if (bfd_coff_have_print_pdata (abfd))
2882*a9fa9459Szrj     bfd_coff_print_pdata (abfd, vfile);
2883*a9fa9459Szrj   else
2884*a9fa9459Szrj     pe_print_pdata (abfd, vfile);
2885*a9fa9459Szrj   pe_print_reloc (abfd, vfile);
2886*a9fa9459Szrj   pe_print_debugdata (abfd, file);
2887*a9fa9459Szrj 
2888*a9fa9459Szrj   rsrc_print_section (abfd, vfile);
2889*a9fa9459Szrj 
2890*a9fa9459Szrj   return TRUE;
2891*a9fa9459Szrj }
2892*a9fa9459Szrj 
2893*a9fa9459Szrj static bfd_boolean
is_vma_in_section(bfd * abfd ATTRIBUTE_UNUSED,asection * sect,void * obj)2894*a9fa9459Szrj is_vma_in_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj)
2895*a9fa9459Szrj {
2896*a9fa9459Szrj   bfd_vma addr = * (bfd_vma *) obj;
2897*a9fa9459Szrj   return (addr >= sect->vma) && (addr < (sect->vma + sect->size));
2898*a9fa9459Szrj }
2899*a9fa9459Szrj 
2900*a9fa9459Szrj static asection *
find_section_by_vma(bfd * abfd,bfd_vma addr)2901*a9fa9459Szrj find_section_by_vma (bfd *abfd, bfd_vma addr)
2902*a9fa9459Szrj {
2903*a9fa9459Szrj   return bfd_sections_find_if (abfd, is_vma_in_section, (void *) & addr);
2904*a9fa9459Szrj }
2905*a9fa9459Szrj 
2906*a9fa9459Szrj /* Copy any private info we understand from the input bfd
2907*a9fa9459Szrj    to the output bfd.  */
2908*a9fa9459Szrj 
2909*a9fa9459Szrj bfd_boolean
_bfd_XX_bfd_copy_private_bfd_data_common(bfd * ibfd,bfd * obfd)2910*a9fa9459Szrj _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd)
2911*a9fa9459Szrj {
2912*a9fa9459Szrj   pe_data_type *ipe, *ope;
2913*a9fa9459Szrj 
2914*a9fa9459Szrj   /* One day we may try to grok other private data.  */
2915*a9fa9459Szrj   if (ibfd->xvec->flavour != bfd_target_coff_flavour
2916*a9fa9459Szrj       || obfd->xvec->flavour != bfd_target_coff_flavour)
2917*a9fa9459Szrj     return TRUE;
2918*a9fa9459Szrj 
2919*a9fa9459Szrj   ipe = pe_data (ibfd);
2920*a9fa9459Szrj   ope = pe_data (obfd);
2921*a9fa9459Szrj 
2922*a9fa9459Szrj   /* pe_opthdr is copied in copy_object.  */
2923*a9fa9459Szrj   ope->dll = ipe->dll;
2924*a9fa9459Szrj 
2925*a9fa9459Szrj   /* Don't copy input subsystem if output is different from input.  */
2926*a9fa9459Szrj   if (obfd->xvec != ibfd->xvec)
2927*a9fa9459Szrj     ope->pe_opthdr.Subsystem = IMAGE_SUBSYSTEM_UNKNOWN;
2928*a9fa9459Szrj 
2929*a9fa9459Szrj   /* For strip: if we removed .reloc, we'll make a real mess of things
2930*a9fa9459Szrj      if we don't remove this entry as well.  */
2931*a9fa9459Szrj   if (! pe_data (obfd)->has_reloc_section)
2932*a9fa9459Szrj     {
2933*a9fa9459Szrj       pe_data (obfd)->pe_opthdr.DataDirectory[PE_BASE_RELOCATION_TABLE].VirtualAddress = 0;
2934*a9fa9459Szrj       pe_data (obfd)->pe_opthdr.DataDirectory[PE_BASE_RELOCATION_TABLE].Size = 0;
2935*a9fa9459Szrj     }
2936*a9fa9459Szrj 
2937*a9fa9459Szrj   /* For PIE, if there is .reloc, we won't add IMAGE_FILE_RELOCS_STRIPPED.
2938*a9fa9459Szrj      But there is no .reloc, we make sure that IMAGE_FILE_RELOCS_STRIPPED
2939*a9fa9459Szrj      won't be added.  */
2940*a9fa9459Szrj   if (! pe_data (ibfd)->has_reloc_section
2941*a9fa9459Szrj       && ! (pe_data (ibfd)->real_flags & IMAGE_FILE_RELOCS_STRIPPED))
2942*a9fa9459Szrj     pe_data (obfd)->dont_strip_reloc = 1;
2943*a9fa9459Szrj 
2944*a9fa9459Szrj   /* The file offsets contained in the debug directory need rewriting.  */
2945*a9fa9459Szrj   if (ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size != 0)
2946*a9fa9459Szrj     {
2947*a9fa9459Szrj       bfd_vma addr = ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].VirtualAddress
2948*a9fa9459Szrj 	+ ope->pe_opthdr.ImageBase;
2949*a9fa9459Szrj       asection *section = find_section_by_vma (obfd, addr);
2950*a9fa9459Szrj       bfd_byte *data;
2951*a9fa9459Szrj 
2952*a9fa9459Szrj       if (section && bfd_malloc_and_get_section (obfd, section, &data))
2953*a9fa9459Szrj         {
2954*a9fa9459Szrj           unsigned int i;
2955*a9fa9459Szrj           struct external_IMAGE_DEBUG_DIRECTORY *dd =
2956*a9fa9459Szrj 	    (struct external_IMAGE_DEBUG_DIRECTORY *)(data + (addr - section->vma));
2957*a9fa9459Szrj 
2958*a9fa9459Szrj 	  /* PR 17512: file: 0f15796a.  */
2959*a9fa9459Szrj 	  if (ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size + (addr - section->vma)
2960*a9fa9459Szrj 	      > bfd_get_section_size (section))
2961*a9fa9459Szrj 	    {
2962*a9fa9459Szrj 	      _bfd_error_handler (_("%B: Data Directory size (%lx) exceeds space left in section (%lx)"),
2963*a9fa9459Szrj 				  obfd, ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size,
2964*a9fa9459Szrj 				  bfd_get_section_size (section) - (addr - section->vma));
2965*a9fa9459Szrj 	      return FALSE;
2966*a9fa9459Szrj 	    }
2967*a9fa9459Szrj 
2968*a9fa9459Szrj           for (i = 0; i < ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size
2969*a9fa9459Szrj 		 / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++)
2970*a9fa9459Szrj             {
2971*a9fa9459Szrj               asection *ddsection;
2972*a9fa9459Szrj               struct external_IMAGE_DEBUG_DIRECTORY *edd = &(dd[i]);
2973*a9fa9459Szrj               struct internal_IMAGE_DEBUG_DIRECTORY idd;
2974*a9fa9459Szrj 
2975*a9fa9459Szrj               _bfd_XXi_swap_debugdir_in (obfd, edd, &idd);
2976*a9fa9459Szrj 
2977*a9fa9459Szrj               if (idd.AddressOfRawData == 0)
2978*a9fa9459Szrj                 continue; /* RVA 0 means only offset is valid, not handled yet.  */
2979*a9fa9459Szrj 
2980*a9fa9459Szrj               ddsection = find_section_by_vma (obfd, idd.AddressOfRawData + ope->pe_opthdr.ImageBase);
2981*a9fa9459Szrj               if (!ddsection)
2982*a9fa9459Szrj                 continue; /* Not in a section! */
2983*a9fa9459Szrj 
2984*a9fa9459Szrj               idd.PointerToRawData = ddsection->filepos + (idd.AddressOfRawData
2985*a9fa9459Szrj 							   + ope->pe_opthdr.ImageBase) - ddsection->vma;
2986*a9fa9459Szrj 
2987*a9fa9459Szrj               _bfd_XXi_swap_debugdir_out (obfd, &idd, edd);
2988*a9fa9459Szrj             }
2989*a9fa9459Szrj 
2990*a9fa9459Szrj           if (!bfd_set_section_contents (obfd, section, data, 0, section->size))
2991*a9fa9459Szrj 	    {
2992*a9fa9459Szrj 	      _bfd_error_handler (_("Failed to update file offsets in debug directory"));
2993*a9fa9459Szrj 	      return FALSE;
2994*a9fa9459Szrj 	    }
2995*a9fa9459Szrj         }
2996*a9fa9459Szrj       else if (section)
2997*a9fa9459Szrj 	{
2998*a9fa9459Szrj 	  _bfd_error_handler (_("%B: Failed to read debug data section"), obfd);
2999*a9fa9459Szrj 	  return FALSE;
3000*a9fa9459Szrj 	}
3001*a9fa9459Szrj     }
3002*a9fa9459Szrj 
3003*a9fa9459Szrj   return TRUE;
3004*a9fa9459Szrj }
3005*a9fa9459Szrj 
3006*a9fa9459Szrj /* Copy private section data.  */
3007*a9fa9459Szrj 
3008*a9fa9459Szrj bfd_boolean
_bfd_XX_bfd_copy_private_section_data(bfd * ibfd,asection * isec,bfd * obfd,asection * osec)3009*a9fa9459Szrj _bfd_XX_bfd_copy_private_section_data (bfd *ibfd,
3010*a9fa9459Szrj 				       asection *isec,
3011*a9fa9459Szrj 				       bfd *obfd,
3012*a9fa9459Szrj 				       asection *osec)
3013*a9fa9459Szrj {
3014*a9fa9459Szrj   if (bfd_get_flavour (ibfd) != bfd_target_coff_flavour
3015*a9fa9459Szrj       || bfd_get_flavour (obfd) != bfd_target_coff_flavour)
3016*a9fa9459Szrj     return TRUE;
3017*a9fa9459Szrj 
3018*a9fa9459Szrj   if (coff_section_data (ibfd, isec) != NULL
3019*a9fa9459Szrj       && pei_section_data (ibfd, isec) != NULL)
3020*a9fa9459Szrj     {
3021*a9fa9459Szrj       if (coff_section_data (obfd, osec) == NULL)
3022*a9fa9459Szrj 	{
3023*a9fa9459Szrj 	  bfd_size_type amt = sizeof (struct coff_section_tdata);
3024*a9fa9459Szrj 	  osec->used_by_bfd = bfd_zalloc (obfd, amt);
3025*a9fa9459Szrj 	  if (osec->used_by_bfd == NULL)
3026*a9fa9459Szrj 	    return FALSE;
3027*a9fa9459Szrj 	}
3028*a9fa9459Szrj 
3029*a9fa9459Szrj       if (pei_section_data (obfd, osec) == NULL)
3030*a9fa9459Szrj 	{
3031*a9fa9459Szrj 	  bfd_size_type amt = sizeof (struct pei_section_tdata);
3032*a9fa9459Szrj 	  coff_section_data (obfd, osec)->tdata = bfd_zalloc (obfd, amt);
3033*a9fa9459Szrj 	  if (coff_section_data (obfd, osec)->tdata == NULL)
3034*a9fa9459Szrj 	    return FALSE;
3035*a9fa9459Szrj 	}
3036*a9fa9459Szrj 
3037*a9fa9459Szrj       pei_section_data (obfd, osec)->virt_size =
3038*a9fa9459Szrj 	pei_section_data (ibfd, isec)->virt_size;
3039*a9fa9459Szrj       pei_section_data (obfd, osec)->pe_flags =
3040*a9fa9459Szrj 	pei_section_data (ibfd, isec)->pe_flags;
3041*a9fa9459Szrj     }
3042*a9fa9459Szrj 
3043*a9fa9459Szrj   return TRUE;
3044*a9fa9459Szrj }
3045*a9fa9459Szrj 
3046*a9fa9459Szrj void
_bfd_XX_get_symbol_info(bfd * abfd,asymbol * symbol,symbol_info * ret)3047*a9fa9459Szrj _bfd_XX_get_symbol_info (bfd * abfd, asymbol *symbol, symbol_info *ret)
3048*a9fa9459Szrj {
3049*a9fa9459Szrj   coff_get_symbol_info (abfd, symbol, ret);
3050*a9fa9459Szrj }
3051*a9fa9459Szrj 
3052*a9fa9459Szrj #if !defined(COFF_WITH_pep) && defined(COFF_WITH_pex64)
3053*a9fa9459Szrj static int
sort_x64_pdata(const void * l,const void * r)3054*a9fa9459Szrj sort_x64_pdata (const void *l, const void *r)
3055*a9fa9459Szrj {
3056*a9fa9459Szrj   const char *lp = (const char *) l;
3057*a9fa9459Szrj   const char *rp = (const char *) r;
3058*a9fa9459Szrj   bfd_vma vl, vr;
3059*a9fa9459Szrj   vl = bfd_getl32 (lp); vr = bfd_getl32 (rp);
3060*a9fa9459Szrj   if (vl != vr)
3061*a9fa9459Szrj     return (vl < vr ? -1 : 1);
3062*a9fa9459Szrj   /* We compare just begin address.  */
3063*a9fa9459Szrj   return 0;
3064*a9fa9459Szrj }
3065*a9fa9459Szrj #endif
3066*a9fa9459Szrj 
3067*a9fa9459Szrj /* Functions to process a .rsrc section.  */
3068*a9fa9459Szrj 
3069*a9fa9459Szrj static unsigned int sizeof_leaves;
3070*a9fa9459Szrj static unsigned int sizeof_strings;
3071*a9fa9459Szrj static unsigned int sizeof_tables_and_entries;
3072*a9fa9459Szrj 
3073*a9fa9459Szrj static bfd_byte *
3074*a9fa9459Szrj rsrc_count_directory (bfd *, bfd_byte *, bfd_byte *, bfd_byte *, bfd_vma);
3075*a9fa9459Szrj 
3076*a9fa9459Szrj static bfd_byte *
rsrc_count_entries(bfd * abfd,bfd_boolean is_name,bfd_byte * datastart,bfd_byte * data,bfd_byte * dataend,bfd_vma rva_bias)3077*a9fa9459Szrj rsrc_count_entries (bfd *          abfd,
3078*a9fa9459Szrj 		    bfd_boolean    is_name,
3079*a9fa9459Szrj 		    bfd_byte *     datastart,
3080*a9fa9459Szrj 		    bfd_byte *     data,
3081*a9fa9459Szrj 		    bfd_byte *     dataend,
3082*a9fa9459Szrj 		    bfd_vma        rva_bias)
3083*a9fa9459Szrj {
3084*a9fa9459Szrj   unsigned long entry, addr, size;
3085*a9fa9459Szrj 
3086*a9fa9459Szrj   if (data + 8 >= dataend)
3087*a9fa9459Szrj     return dataend + 1;
3088*a9fa9459Szrj 
3089*a9fa9459Szrj   if (is_name)
3090*a9fa9459Szrj     {
3091*a9fa9459Szrj       bfd_byte * name;
3092*a9fa9459Szrj 
3093*a9fa9459Szrj       entry = (long) bfd_get_32 (abfd, data);
3094*a9fa9459Szrj 
3095*a9fa9459Szrj       if (HighBitSet (entry))
3096*a9fa9459Szrj 	name = datastart + WithoutHighBit (entry);
3097*a9fa9459Szrj       else
3098*a9fa9459Szrj 	name = datastart + entry - rva_bias;
3099*a9fa9459Szrj 
3100*a9fa9459Szrj       if (name + 2 >= dataend || name < datastart)
3101*a9fa9459Szrj 	return dataend + 1;
3102*a9fa9459Szrj 
3103*a9fa9459Szrj       unsigned int len = bfd_get_16 (abfd, name);
3104*a9fa9459Szrj       if (len == 0 || len > 256)
3105*a9fa9459Szrj 	return dataend + 1;
3106*a9fa9459Szrj     }
3107*a9fa9459Szrj 
3108*a9fa9459Szrj   entry = (long) bfd_get_32 (abfd, data + 4);
3109*a9fa9459Szrj 
3110*a9fa9459Szrj   if (HighBitSet (entry))
3111*a9fa9459Szrj     {
3112*a9fa9459Szrj       data = datastart + WithoutHighBit (entry);
3113*a9fa9459Szrj 
3114*a9fa9459Szrj       if (data <= datastart || data >= dataend)
3115*a9fa9459Szrj 	return dataend + 1;
3116*a9fa9459Szrj 
3117*a9fa9459Szrj       return rsrc_count_directory (abfd, datastart, data, dataend, rva_bias);
3118*a9fa9459Szrj     }
3119*a9fa9459Szrj 
3120*a9fa9459Szrj   if (datastart + entry + 16 >= dataend)
3121*a9fa9459Szrj     return dataend + 1;
3122*a9fa9459Szrj 
3123*a9fa9459Szrj   addr = (long) bfd_get_32 (abfd, datastart + entry);
3124*a9fa9459Szrj   size = (long) bfd_get_32 (abfd, datastart + entry + 4);
3125*a9fa9459Szrj 
3126*a9fa9459Szrj   return datastart + addr - rva_bias + size;
3127*a9fa9459Szrj }
3128*a9fa9459Szrj 
3129*a9fa9459Szrj static bfd_byte *
rsrc_count_directory(bfd * abfd,bfd_byte * datastart,bfd_byte * data,bfd_byte * dataend,bfd_vma rva_bias)3130*a9fa9459Szrj rsrc_count_directory (bfd *          abfd,
3131*a9fa9459Szrj 		      bfd_byte *     datastart,
3132*a9fa9459Szrj 		      bfd_byte *     data,
3133*a9fa9459Szrj 		      bfd_byte *     dataend,
3134*a9fa9459Szrj 		      bfd_vma        rva_bias)
3135*a9fa9459Szrj {
3136*a9fa9459Szrj   unsigned int  num_entries, num_ids;
3137*a9fa9459Szrj   bfd_byte *    highest_data = data;
3138*a9fa9459Szrj 
3139*a9fa9459Szrj   if (data + 16 >= dataend)
3140*a9fa9459Szrj     return dataend + 1;
3141*a9fa9459Szrj 
3142*a9fa9459Szrj   num_entries  = (int) bfd_get_16 (abfd, data + 12);
3143*a9fa9459Szrj   num_ids      = (int) bfd_get_16 (abfd, data + 14);
3144*a9fa9459Szrj 
3145*a9fa9459Szrj   num_entries += num_ids;
3146*a9fa9459Szrj 
3147*a9fa9459Szrj   data += 16;
3148*a9fa9459Szrj 
3149*a9fa9459Szrj   while (num_entries --)
3150*a9fa9459Szrj     {
3151*a9fa9459Szrj       bfd_byte * entry_end;
3152*a9fa9459Szrj 
3153*a9fa9459Szrj       entry_end = rsrc_count_entries (abfd, num_entries >= num_ids,
3154*a9fa9459Szrj 				      datastart, data, dataend, rva_bias);
3155*a9fa9459Szrj       data += 8;
3156*a9fa9459Szrj       highest_data = max (highest_data, entry_end);
3157*a9fa9459Szrj       if (entry_end >= dataend)
3158*a9fa9459Szrj 	break;
3159*a9fa9459Szrj     }
3160*a9fa9459Szrj 
3161*a9fa9459Szrj   return max (highest_data, data);
3162*a9fa9459Szrj }
3163*a9fa9459Szrj 
3164*a9fa9459Szrj typedef struct rsrc_dir_chain
3165*a9fa9459Szrj {
3166*a9fa9459Szrj   unsigned int         num_entries;
3167*a9fa9459Szrj   struct rsrc_entry *  first_entry;
3168*a9fa9459Szrj   struct rsrc_entry *  last_entry;
3169*a9fa9459Szrj } rsrc_dir_chain;
3170*a9fa9459Szrj 
3171*a9fa9459Szrj typedef struct rsrc_directory
3172*a9fa9459Szrj {
3173*a9fa9459Szrj   unsigned int characteristics;
3174*a9fa9459Szrj   unsigned int time;
3175*a9fa9459Szrj   unsigned int major;
3176*a9fa9459Szrj   unsigned int minor;
3177*a9fa9459Szrj 
3178*a9fa9459Szrj   rsrc_dir_chain names;
3179*a9fa9459Szrj   rsrc_dir_chain ids;
3180*a9fa9459Szrj 
3181*a9fa9459Szrj   struct rsrc_entry * entry;
3182*a9fa9459Szrj } rsrc_directory;
3183*a9fa9459Szrj 
3184*a9fa9459Szrj typedef struct rsrc_string
3185*a9fa9459Szrj {
3186*a9fa9459Szrj   unsigned int  len;
3187*a9fa9459Szrj   bfd_byte *    string;
3188*a9fa9459Szrj } rsrc_string;
3189*a9fa9459Szrj 
3190*a9fa9459Szrj typedef struct rsrc_leaf
3191*a9fa9459Szrj {
3192*a9fa9459Szrj   unsigned int  size;
3193*a9fa9459Szrj   unsigned int  codepage;
3194*a9fa9459Szrj   bfd_byte *    data;
3195*a9fa9459Szrj } rsrc_leaf;
3196*a9fa9459Szrj 
3197*a9fa9459Szrj typedef struct rsrc_entry
3198*a9fa9459Szrj {
3199*a9fa9459Szrj   bfd_boolean is_name;
3200*a9fa9459Szrj   union
3201*a9fa9459Szrj   {
3202*a9fa9459Szrj     unsigned int          id;
3203*a9fa9459Szrj     struct rsrc_string    name;
3204*a9fa9459Szrj   } name_id;
3205*a9fa9459Szrj 
3206*a9fa9459Szrj   bfd_boolean is_dir;
3207*a9fa9459Szrj   union
3208*a9fa9459Szrj   {
3209*a9fa9459Szrj     struct rsrc_directory * directory;
3210*a9fa9459Szrj     struct rsrc_leaf *      leaf;
3211*a9fa9459Szrj   } value;
3212*a9fa9459Szrj 
3213*a9fa9459Szrj   struct rsrc_entry *     next_entry;
3214*a9fa9459Szrj   struct rsrc_directory * parent;
3215*a9fa9459Szrj } rsrc_entry;
3216*a9fa9459Szrj 
3217*a9fa9459Szrj static bfd_byte *
3218*a9fa9459Szrj rsrc_parse_directory (bfd *, rsrc_directory *, bfd_byte *,
3219*a9fa9459Szrj 		      bfd_byte *, bfd_byte *, bfd_vma, rsrc_entry *);
3220*a9fa9459Szrj 
3221*a9fa9459Szrj static bfd_byte *
rsrc_parse_entry(bfd * abfd,bfd_boolean is_name,rsrc_entry * entry,bfd_byte * datastart,bfd_byte * data,bfd_byte * dataend,bfd_vma rva_bias,rsrc_directory * parent)3222*a9fa9459Szrj rsrc_parse_entry (bfd *            abfd,
3223*a9fa9459Szrj 		  bfd_boolean      is_name,
3224*a9fa9459Szrj 		  rsrc_entry *     entry,
3225*a9fa9459Szrj 		  bfd_byte *       datastart,
3226*a9fa9459Szrj 		  bfd_byte *       data,
3227*a9fa9459Szrj 		  bfd_byte *       dataend,
3228*a9fa9459Szrj 		  bfd_vma          rva_bias,
3229*a9fa9459Szrj 		  rsrc_directory * parent)
3230*a9fa9459Szrj {
3231*a9fa9459Szrj   unsigned long val, addr, size;
3232*a9fa9459Szrj 
3233*a9fa9459Szrj   val = bfd_get_32 (abfd, data);
3234*a9fa9459Szrj 
3235*a9fa9459Szrj   entry->parent = parent;
3236*a9fa9459Szrj   entry->is_name = is_name;
3237*a9fa9459Szrj 
3238*a9fa9459Szrj   if (is_name)
3239*a9fa9459Szrj     {
3240*a9fa9459Szrj       bfd_byte * address;
3241*a9fa9459Szrj 
3242*a9fa9459Szrj       if (HighBitSet (val))
3243*a9fa9459Szrj 	{
3244*a9fa9459Szrj 	  val = WithoutHighBit (val);
3245*a9fa9459Szrj 
3246*a9fa9459Szrj 	  address = datastart + val;
3247*a9fa9459Szrj 	}
3248*a9fa9459Szrj       else
3249*a9fa9459Szrj 	{
3250*a9fa9459Szrj 	  address = datastart + val - rva_bias;
3251*a9fa9459Szrj 	}
3252*a9fa9459Szrj 
3253*a9fa9459Szrj       if (address + 3 > dataend)
3254*a9fa9459Szrj 	return dataend;
3255*a9fa9459Szrj 
3256*a9fa9459Szrj       entry->name_id.name.len    = bfd_get_16 (abfd, address);
3257*a9fa9459Szrj       entry->name_id.name.string = address + 2;
3258*a9fa9459Szrj     }
3259*a9fa9459Szrj   else
3260*a9fa9459Szrj     entry->name_id.id = val;
3261*a9fa9459Szrj 
3262*a9fa9459Szrj   val = bfd_get_32 (abfd, data + 4);
3263*a9fa9459Szrj 
3264*a9fa9459Szrj   if (HighBitSet (val))
3265*a9fa9459Szrj     {
3266*a9fa9459Szrj       entry->is_dir = TRUE;
3267*a9fa9459Szrj       entry->value.directory = bfd_malloc (sizeof * entry->value.directory);
3268*a9fa9459Szrj       if (entry->value.directory == NULL)
3269*a9fa9459Szrj 	return dataend;
3270*a9fa9459Szrj 
3271*a9fa9459Szrj       return rsrc_parse_directory (abfd, entry->value.directory,
3272*a9fa9459Szrj 				   datastart,
3273*a9fa9459Szrj 				   datastart + WithoutHighBit (val),
3274*a9fa9459Szrj 				   dataend, rva_bias, entry);
3275*a9fa9459Szrj     }
3276*a9fa9459Szrj 
3277*a9fa9459Szrj   entry->is_dir = FALSE;
3278*a9fa9459Szrj   entry->value.leaf = bfd_malloc (sizeof * entry->value.leaf);
3279*a9fa9459Szrj   if (entry->value.leaf == NULL)
3280*a9fa9459Szrj     return dataend;
3281*a9fa9459Szrj 
3282*a9fa9459Szrj   data = datastart + val;
3283*a9fa9459Szrj   if (data < datastart || data >= dataend)
3284*a9fa9459Szrj     return dataend;
3285*a9fa9459Szrj 
3286*a9fa9459Szrj   addr = bfd_get_32 (abfd, data);
3287*a9fa9459Szrj   size = entry->value.leaf->size = bfd_get_32 (abfd, data + 4);
3288*a9fa9459Szrj   entry->value.leaf->codepage = bfd_get_32 (abfd, data + 8);
3289*a9fa9459Szrj   /* FIXME: We assume that the reserved field (data + 12) is OK.  */
3290*a9fa9459Szrj 
3291*a9fa9459Szrj   entry->value.leaf->data = bfd_malloc (size);
3292*a9fa9459Szrj   if (entry->value.leaf->data == NULL)
3293*a9fa9459Szrj     return dataend;
3294*a9fa9459Szrj 
3295*a9fa9459Szrj   memcpy (entry->value.leaf->data, datastart + addr - rva_bias, size);
3296*a9fa9459Szrj   return datastart + (addr - rva_bias) + size;
3297*a9fa9459Szrj }
3298*a9fa9459Szrj 
3299*a9fa9459Szrj static bfd_byte *
rsrc_parse_entries(bfd * abfd,rsrc_dir_chain * chain,bfd_boolean is_name,bfd_byte * highest_data,bfd_byte * datastart,bfd_byte * data,bfd_byte * dataend,bfd_vma rva_bias,rsrc_directory * parent)3300*a9fa9459Szrj rsrc_parse_entries (bfd *            abfd,
3301*a9fa9459Szrj 		    rsrc_dir_chain * chain,
3302*a9fa9459Szrj 		    bfd_boolean      is_name,
3303*a9fa9459Szrj 		    bfd_byte *       highest_data,
3304*a9fa9459Szrj 		    bfd_byte *       datastart,
3305*a9fa9459Szrj 		    bfd_byte *       data,
3306*a9fa9459Szrj 		    bfd_byte *       dataend,
3307*a9fa9459Szrj 		    bfd_vma          rva_bias,
3308*a9fa9459Szrj 		    rsrc_directory * parent)
3309*a9fa9459Szrj {
3310*a9fa9459Szrj   unsigned int i;
3311*a9fa9459Szrj   rsrc_entry * entry;
3312*a9fa9459Szrj 
3313*a9fa9459Szrj   if (chain->num_entries == 0)
3314*a9fa9459Szrj     {
3315*a9fa9459Szrj       chain->first_entry = chain->last_entry = NULL;
3316*a9fa9459Szrj       return highest_data;
3317*a9fa9459Szrj     }
3318*a9fa9459Szrj 
3319*a9fa9459Szrj   entry = bfd_malloc (sizeof * entry);
3320*a9fa9459Szrj   if (entry == NULL)
3321*a9fa9459Szrj     return dataend;
3322*a9fa9459Szrj 
3323*a9fa9459Szrj   chain->first_entry = entry;
3324*a9fa9459Szrj 
3325*a9fa9459Szrj   for (i = chain->num_entries; i--;)
3326*a9fa9459Szrj     {
3327*a9fa9459Szrj       bfd_byte * entry_end;
3328*a9fa9459Szrj 
3329*a9fa9459Szrj       entry_end = rsrc_parse_entry (abfd, is_name, entry, datastart,
3330*a9fa9459Szrj 				    data, dataend, rva_bias, parent);
3331*a9fa9459Szrj       data += 8;
3332*a9fa9459Szrj       highest_data = max (entry_end, highest_data);
3333*a9fa9459Szrj       if (entry_end > dataend)
3334*a9fa9459Szrj 	return dataend;
3335*a9fa9459Szrj 
3336*a9fa9459Szrj       if (i)
3337*a9fa9459Szrj 	{
3338*a9fa9459Szrj 	  entry->next_entry = bfd_malloc (sizeof * entry);
3339*a9fa9459Szrj 	  entry = entry->next_entry;
3340*a9fa9459Szrj 	  if (entry == NULL)
3341*a9fa9459Szrj 	    return dataend;
3342*a9fa9459Szrj 	}
3343*a9fa9459Szrj       else
3344*a9fa9459Szrj 	entry->next_entry = NULL;
3345*a9fa9459Szrj     }
3346*a9fa9459Szrj 
3347*a9fa9459Szrj   chain->last_entry = entry;
3348*a9fa9459Szrj 
3349*a9fa9459Szrj   return highest_data;
3350*a9fa9459Szrj }
3351*a9fa9459Szrj 
3352*a9fa9459Szrj static bfd_byte *
rsrc_parse_directory(bfd * abfd,rsrc_directory * table,bfd_byte * datastart,bfd_byte * data,bfd_byte * dataend,bfd_vma rva_bias,rsrc_entry * entry)3353*a9fa9459Szrj rsrc_parse_directory (bfd *            abfd,
3354*a9fa9459Szrj 		      rsrc_directory * table,
3355*a9fa9459Szrj 		      bfd_byte *       datastart,
3356*a9fa9459Szrj 		      bfd_byte *       data,
3357*a9fa9459Szrj 		      bfd_byte *       dataend,
3358*a9fa9459Szrj 		      bfd_vma          rva_bias,
3359*a9fa9459Szrj 		      rsrc_entry *     entry)
3360*a9fa9459Szrj {
3361*a9fa9459Szrj   bfd_byte * highest_data = data;
3362*a9fa9459Szrj 
3363*a9fa9459Szrj   if (table == NULL)
3364*a9fa9459Szrj     return dataend;
3365*a9fa9459Szrj 
3366*a9fa9459Szrj   table->characteristics = bfd_get_32 (abfd, data);
3367*a9fa9459Szrj   table->time = bfd_get_32 (abfd, data + 4);
3368*a9fa9459Szrj   table->major = bfd_get_16 (abfd, data + 8);
3369*a9fa9459Szrj   table->minor = bfd_get_16 (abfd, data + 10);
3370*a9fa9459Szrj   table->names.num_entries = bfd_get_16 (abfd, data + 12);
3371*a9fa9459Szrj   table->ids.num_entries = bfd_get_16 (abfd, data + 14);
3372*a9fa9459Szrj   table->entry = entry;
3373*a9fa9459Szrj 
3374*a9fa9459Szrj   data += 16;
3375*a9fa9459Szrj 
3376*a9fa9459Szrj   highest_data = rsrc_parse_entries (abfd, & table->names, TRUE, data,
3377*a9fa9459Szrj 				     datastart, data, dataend, rva_bias, table);
3378*a9fa9459Szrj   data += table->names.num_entries * 8;
3379*a9fa9459Szrj 
3380*a9fa9459Szrj   highest_data = rsrc_parse_entries (abfd, & table->ids, FALSE, highest_data,
3381*a9fa9459Szrj 				     datastart, data, dataend, rva_bias, table);
3382*a9fa9459Szrj   data += table->ids.num_entries * 8;
3383*a9fa9459Szrj 
3384*a9fa9459Szrj   return max (highest_data, data);
3385*a9fa9459Szrj }
3386*a9fa9459Szrj 
3387*a9fa9459Szrj typedef struct rsrc_write_data
3388*a9fa9459Szrj {
3389*a9fa9459Szrj   bfd *      abfd;
3390*a9fa9459Szrj   bfd_byte * datastart;
3391*a9fa9459Szrj   bfd_byte * next_table;
3392*a9fa9459Szrj   bfd_byte * next_leaf;
3393*a9fa9459Szrj   bfd_byte * next_string;
3394*a9fa9459Szrj   bfd_byte * next_data;
3395*a9fa9459Szrj   bfd_vma    rva_bias;
3396*a9fa9459Szrj } rsrc_write_data;
3397*a9fa9459Szrj 
3398*a9fa9459Szrj static void
rsrc_write_string(rsrc_write_data * data,rsrc_string * string)3399*a9fa9459Szrj rsrc_write_string (rsrc_write_data * data,
3400*a9fa9459Szrj 		   rsrc_string *     string)
3401*a9fa9459Szrj {
3402*a9fa9459Szrj   bfd_put_16 (data->abfd, string->len, data->next_string);
3403*a9fa9459Szrj   memcpy (data->next_string + 2, string->string, string->len * 2);
3404*a9fa9459Szrj   data->next_string += (string->len + 1) * 2;
3405*a9fa9459Szrj }
3406*a9fa9459Szrj 
3407*a9fa9459Szrj static inline unsigned int
rsrc_compute_rva(rsrc_write_data * data,bfd_byte * addr)3408*a9fa9459Szrj rsrc_compute_rva (rsrc_write_data * data,
3409*a9fa9459Szrj 		  bfd_byte *        addr)
3410*a9fa9459Szrj {
3411*a9fa9459Szrj   return (addr - data->datastart) + data->rva_bias;
3412*a9fa9459Szrj }
3413*a9fa9459Szrj 
3414*a9fa9459Szrj static void
rsrc_write_leaf(rsrc_write_data * data,rsrc_leaf * leaf)3415*a9fa9459Szrj rsrc_write_leaf (rsrc_write_data * data,
3416*a9fa9459Szrj 		 rsrc_leaf *       leaf)
3417*a9fa9459Szrj {
3418*a9fa9459Szrj   bfd_put_32 (data->abfd, rsrc_compute_rva (data, data->next_data),
3419*a9fa9459Szrj 	      data->next_leaf);
3420*a9fa9459Szrj   bfd_put_32 (data->abfd, leaf->size,     data->next_leaf + 4);
3421*a9fa9459Szrj   bfd_put_32 (data->abfd, leaf->codepage, data->next_leaf + 8);
3422*a9fa9459Szrj   bfd_put_32 (data->abfd, 0 /*reserved*/, data->next_leaf + 12);
3423*a9fa9459Szrj   data->next_leaf += 16;
3424*a9fa9459Szrj 
3425*a9fa9459Szrj   memcpy (data->next_data, leaf->data, leaf->size);
3426*a9fa9459Szrj   /* An undocumented feature of Windows resources is that each unit
3427*a9fa9459Szrj      of raw data is 8-byte aligned...  */
3428*a9fa9459Szrj   data->next_data += ((leaf->size + 7) & ~7);
3429*a9fa9459Szrj }
3430*a9fa9459Szrj 
3431*a9fa9459Szrj static void rsrc_write_directory (rsrc_write_data *, rsrc_directory *);
3432*a9fa9459Szrj 
3433*a9fa9459Szrj static void
rsrc_write_entry(rsrc_write_data * data,bfd_byte * where,rsrc_entry * entry)3434*a9fa9459Szrj rsrc_write_entry (rsrc_write_data *  data,
3435*a9fa9459Szrj 		  bfd_byte *         where,
3436*a9fa9459Szrj 		  rsrc_entry *       entry)
3437*a9fa9459Szrj {
3438*a9fa9459Szrj   if (entry->is_name)
3439*a9fa9459Szrj     {
3440*a9fa9459Szrj       bfd_put_32 (data->abfd,
3441*a9fa9459Szrj 		  SetHighBit (data->next_string - data->datastart),
3442*a9fa9459Szrj 		  where);
3443*a9fa9459Szrj       rsrc_write_string (data, & entry->name_id.name);
3444*a9fa9459Szrj     }
3445*a9fa9459Szrj   else
3446*a9fa9459Szrj     bfd_put_32 (data->abfd, entry->name_id.id, where);
3447*a9fa9459Szrj 
3448*a9fa9459Szrj   if (entry->is_dir)
3449*a9fa9459Szrj     {
3450*a9fa9459Szrj       bfd_put_32 (data->abfd,
3451*a9fa9459Szrj 		  SetHighBit (data->next_table - data->datastart),
3452*a9fa9459Szrj 		  where + 4);
3453*a9fa9459Szrj       rsrc_write_directory (data, entry->value.directory);
3454*a9fa9459Szrj     }
3455*a9fa9459Szrj   else
3456*a9fa9459Szrj     {
3457*a9fa9459Szrj       bfd_put_32 (data->abfd, data->next_leaf - data->datastart, where + 4);
3458*a9fa9459Szrj       rsrc_write_leaf (data, entry->value.leaf);
3459*a9fa9459Szrj     }
3460*a9fa9459Szrj }
3461*a9fa9459Szrj 
3462*a9fa9459Szrj static void
rsrc_compute_region_sizes(rsrc_directory * dir)3463*a9fa9459Szrj rsrc_compute_region_sizes (rsrc_directory * dir)
3464*a9fa9459Szrj {
3465*a9fa9459Szrj   struct rsrc_entry * entry;
3466*a9fa9459Szrj 
3467*a9fa9459Szrj   if (dir == NULL)
3468*a9fa9459Szrj     return;
3469*a9fa9459Szrj 
3470*a9fa9459Szrj   sizeof_tables_and_entries += 16;
3471*a9fa9459Szrj 
3472*a9fa9459Szrj   for (entry = dir->names.first_entry; entry != NULL; entry = entry->next_entry)
3473*a9fa9459Szrj     {
3474*a9fa9459Szrj       sizeof_tables_and_entries += 8;
3475*a9fa9459Szrj 
3476*a9fa9459Szrj       sizeof_strings += (entry->name_id.name.len + 1) * 2;
3477*a9fa9459Szrj 
3478*a9fa9459Szrj       if (entry->is_dir)
3479*a9fa9459Szrj 	rsrc_compute_region_sizes (entry->value.directory);
3480*a9fa9459Szrj       else
3481*a9fa9459Szrj 	sizeof_leaves += 16;
3482*a9fa9459Szrj     }
3483*a9fa9459Szrj 
3484*a9fa9459Szrj   for (entry = dir->ids.first_entry; entry != NULL; entry = entry->next_entry)
3485*a9fa9459Szrj     {
3486*a9fa9459Szrj       sizeof_tables_and_entries += 8;
3487*a9fa9459Szrj 
3488*a9fa9459Szrj       if (entry->is_dir)
3489*a9fa9459Szrj 	rsrc_compute_region_sizes (entry->value.directory);
3490*a9fa9459Szrj       else
3491*a9fa9459Szrj 	sizeof_leaves += 16;
3492*a9fa9459Szrj     }
3493*a9fa9459Szrj }
3494*a9fa9459Szrj 
3495*a9fa9459Szrj static void
rsrc_write_directory(rsrc_write_data * data,rsrc_directory * dir)3496*a9fa9459Szrj rsrc_write_directory (rsrc_write_data * data,
3497*a9fa9459Szrj 		      rsrc_directory *  dir)
3498*a9fa9459Szrj {
3499*a9fa9459Szrj   rsrc_entry * entry;
3500*a9fa9459Szrj   unsigned int i;
3501*a9fa9459Szrj   bfd_byte * next_entry;
3502*a9fa9459Szrj   bfd_byte * nt;
3503*a9fa9459Szrj 
3504*a9fa9459Szrj   bfd_put_32 (data->abfd, dir->characteristics, data->next_table);
3505*a9fa9459Szrj   bfd_put_32 (data->abfd, 0 /*dir->time*/, data->next_table + 4);
3506*a9fa9459Szrj   bfd_put_16 (data->abfd, dir->major, data->next_table + 8);
3507*a9fa9459Szrj   bfd_put_16 (data->abfd, dir->minor, data->next_table + 10);
3508*a9fa9459Szrj   bfd_put_16 (data->abfd, dir->names.num_entries, data->next_table + 12);
3509*a9fa9459Szrj   bfd_put_16 (data->abfd, dir->ids.num_entries, data->next_table + 14);
3510*a9fa9459Szrj 
3511*a9fa9459Szrj   /* Compute where the entries and the next table will be placed.  */
3512*a9fa9459Szrj   next_entry = data->next_table + 16;
3513*a9fa9459Szrj   data->next_table = next_entry + (dir->names.num_entries * 8)
3514*a9fa9459Szrj     + (dir->ids.num_entries * 8);
3515*a9fa9459Szrj   nt = data->next_table;
3516*a9fa9459Szrj 
3517*a9fa9459Szrj   /* Write the entries.  */
3518*a9fa9459Szrj   for (i = dir->names.num_entries, entry = dir->names.first_entry;
3519*a9fa9459Szrj        i > 0 && entry != NULL;
3520*a9fa9459Szrj        i--, entry = entry->next_entry)
3521*a9fa9459Szrj     {
3522*a9fa9459Szrj       BFD_ASSERT (entry->is_name);
3523*a9fa9459Szrj       rsrc_write_entry (data, next_entry, entry);
3524*a9fa9459Szrj       next_entry += 8;
3525*a9fa9459Szrj     }
3526*a9fa9459Szrj   BFD_ASSERT (i == 0);
3527*a9fa9459Szrj   BFD_ASSERT (entry == NULL);
3528*a9fa9459Szrj 
3529*a9fa9459Szrj   for (i = dir->ids.num_entries, entry = dir->ids.first_entry;
3530*a9fa9459Szrj        i > 0 && entry != NULL;
3531*a9fa9459Szrj        i--, entry = entry->next_entry)
3532*a9fa9459Szrj     {
3533*a9fa9459Szrj       BFD_ASSERT (! entry->is_name);
3534*a9fa9459Szrj       rsrc_write_entry (data, next_entry, entry);
3535*a9fa9459Szrj       next_entry += 8;
3536*a9fa9459Szrj     }
3537*a9fa9459Szrj   BFD_ASSERT (i == 0);
3538*a9fa9459Szrj   BFD_ASSERT (entry == NULL);
3539*a9fa9459Szrj   BFD_ASSERT (nt == next_entry);
3540*a9fa9459Szrj }
3541*a9fa9459Szrj 
3542*a9fa9459Szrj #if defined HAVE_WCHAR_H && ! defined __CYGWIN__ && ! defined __MINGW32__
3543*a9fa9459Szrj /* Return the length (number of units) of the first character in S,
3544*a9fa9459Szrj    putting its 'ucs4_t' representation in *PUC.  */
3545*a9fa9459Szrj 
3546*a9fa9459Szrj static unsigned int
3547*a9fa9459Szrj #if defined HAVE_WCTYPE_H
u16_mbtouc(wint_t * puc,const unsigned short * s,unsigned int n)3548*a9fa9459Szrj u16_mbtouc (wint_t * puc, const unsigned short * s, unsigned int n)
3549*a9fa9459Szrj #else
3550*a9fa9459Szrj u16_mbtouc (wchar_t * puc, const unsigned short * s, unsigned int n)
3551*a9fa9459Szrj #endif
3552*a9fa9459Szrj {
3553*a9fa9459Szrj   unsigned short c = * s;
3554*a9fa9459Szrj 
3555*a9fa9459Szrj   if (c < 0xd800 || c >= 0xe000)
3556*a9fa9459Szrj     {
3557*a9fa9459Szrj       *puc = c;
3558*a9fa9459Szrj       return 1;
3559*a9fa9459Szrj     }
3560*a9fa9459Szrj 
3561*a9fa9459Szrj   if (c < 0xdc00)
3562*a9fa9459Szrj     {
3563*a9fa9459Szrj       if (n >= 2)
3564*a9fa9459Szrj         {
3565*a9fa9459Szrj           if (s[1] >= 0xdc00 && s[1] < 0xe000)
3566*a9fa9459Szrj             {
3567*a9fa9459Szrj               *puc = 0x10000 + ((c - 0xd800) << 10) + (s[1] - 0xdc00);
3568*a9fa9459Szrj               return 2;
3569*a9fa9459Szrj             }
3570*a9fa9459Szrj         }
3571*a9fa9459Szrj       else
3572*a9fa9459Szrj         {
3573*a9fa9459Szrj           /* Incomplete multibyte character.  */
3574*a9fa9459Szrj           *puc = 0xfffd;
3575*a9fa9459Szrj           return n;
3576*a9fa9459Szrj         }
3577*a9fa9459Szrj     }
3578*a9fa9459Szrj 
3579*a9fa9459Szrj   /* Invalid multibyte character.  */
3580*a9fa9459Szrj   *puc = 0xfffd;
3581*a9fa9459Szrj   return 1;
3582*a9fa9459Szrj }
3583*a9fa9459Szrj #endif /* HAVE_WCHAR_H and not Cygwin/Mingw */
3584*a9fa9459Szrj 
3585*a9fa9459Szrj /* Perform a comparison of two entries.  */
3586*a9fa9459Szrj static signed int
rsrc_cmp(bfd_boolean is_name,rsrc_entry * a,rsrc_entry * b)3587*a9fa9459Szrj rsrc_cmp (bfd_boolean is_name, rsrc_entry * a, rsrc_entry * b)
3588*a9fa9459Szrj {
3589*a9fa9459Szrj   signed int    res;
3590*a9fa9459Szrj   bfd_byte *    astring;
3591*a9fa9459Szrj   unsigned int  alen;
3592*a9fa9459Szrj   bfd_byte *    bstring;
3593*a9fa9459Szrj   unsigned int  blen;
3594*a9fa9459Szrj 
3595*a9fa9459Szrj   if (! is_name)
3596*a9fa9459Szrj     return a->name_id.id - b->name_id.id;
3597*a9fa9459Szrj 
3598*a9fa9459Szrj   /* We have to perform a case insenstive, unicode string comparison...  */
3599*a9fa9459Szrj   astring = a->name_id.name.string;
3600*a9fa9459Szrj   alen    = a->name_id.name.len;
3601*a9fa9459Szrj   bstring = b->name_id.name.string;
3602*a9fa9459Szrj   blen    = b->name_id.name.len;
3603*a9fa9459Szrj 
3604*a9fa9459Szrj #if defined  __CYGWIN__ || defined __MINGW32__
3605*a9fa9459Szrj   /* Under Windows hosts (both Cygwin and Mingw types),
3606*a9fa9459Szrj      unicode == UTF-16 == wchar_t.  The case insensitive string comparison
3607*a9fa9459Szrj      function however goes by different names in the two environments...  */
3608*a9fa9459Szrj 
3609*a9fa9459Szrj #undef rscpcmp
3610*a9fa9459Szrj #ifdef __CYGWIN__
3611*a9fa9459Szrj #define rscpcmp wcsncasecmp
3612*a9fa9459Szrj #endif
3613*a9fa9459Szrj #ifdef __MINGW32__
3614*a9fa9459Szrj #define rscpcmp wcsnicmp
3615*a9fa9459Szrj #endif
3616*a9fa9459Szrj 
3617*a9fa9459Szrj   res = rscpcmp ((const wchar_t *) astring, (const wchar_t *) bstring,
3618*a9fa9459Szrj 		 min (alen, blen));
3619*a9fa9459Szrj 
3620*a9fa9459Szrj #elif defined HAVE_WCHAR_H
3621*a9fa9459Szrj   {
3622*a9fa9459Szrj     unsigned int  i;
3623*a9fa9459Szrj 
3624*a9fa9459Szrj     res = 0;
3625*a9fa9459Szrj     for (i = min (alen, blen); i--; astring += 2, bstring += 2)
3626*a9fa9459Szrj       {
3627*a9fa9459Szrj #if defined HAVE_WCTYPE_H
3628*a9fa9459Szrj 	wint_t awc;
3629*a9fa9459Szrj 	wint_t bwc;
3630*a9fa9459Szrj #else
3631*a9fa9459Szrj 	wchar_t awc;
3632*a9fa9459Szrj 	wchar_t bwc;
3633*a9fa9459Szrj #endif
3634*a9fa9459Szrj 
3635*a9fa9459Szrj 	/* Convert UTF-16 unicode characters into wchar_t characters
3636*a9fa9459Szrj 	   so that we can then perform a case insensitive comparison.  */
3637*a9fa9459Szrj 	unsigned int Alen = u16_mbtouc (& awc, (const unsigned short *) astring, 2);
3638*a9fa9459Szrj 	unsigned int Blen = u16_mbtouc (& bwc, (const unsigned short *) bstring, 2);
3639*a9fa9459Szrj 
3640*a9fa9459Szrj 	if (Alen != Blen)
3641*a9fa9459Szrj 	  return Alen - Blen;
3642*a9fa9459Szrj 
3643*a9fa9459Szrj #ifdef HAVE_WCTYPE_H
3644*a9fa9459Szrj 	awc = towlower (awc);
3645*a9fa9459Szrj 	bwc = towlower (bwc);
3646*a9fa9459Szrj 
3647*a9fa9459Szrj 	res = awc - bwc;
3648*a9fa9459Szrj #else
3649*a9fa9459Szrj 	res = wcsncasecmp (& awc, & bwc, 1);
3650*a9fa9459Szrj #endif
3651*a9fa9459Szrj 	if (res)
3652*a9fa9459Szrj 	  break;
3653*a9fa9459Szrj       }
3654*a9fa9459Szrj   }
3655*a9fa9459Szrj #else
3656*a9fa9459Szrj   /* Do the best we can - a case sensitive, untranslated comparison.  */
3657*a9fa9459Szrj   res = memcmp (astring, bstring, min (alen, blen) * 2);
3658*a9fa9459Szrj #endif
3659*a9fa9459Szrj 
3660*a9fa9459Szrj   if (res == 0)
3661*a9fa9459Szrj     res = alen - blen;
3662*a9fa9459Szrj 
3663*a9fa9459Szrj   return res;
3664*a9fa9459Szrj }
3665*a9fa9459Szrj 
3666*a9fa9459Szrj static void
rsrc_print_name(char * buffer,rsrc_string string)3667*a9fa9459Szrj rsrc_print_name (char * buffer, rsrc_string string)
3668*a9fa9459Szrj {
3669*a9fa9459Szrj   unsigned int  i;
3670*a9fa9459Szrj   bfd_byte *    name = string.string;
3671*a9fa9459Szrj 
3672*a9fa9459Szrj   for (i = string.len; i--; name += 2)
3673*a9fa9459Szrj     sprintf (buffer + strlen (buffer), "%.1s", name);
3674*a9fa9459Szrj }
3675*a9fa9459Szrj 
3676*a9fa9459Szrj static const char *
rsrc_resource_name(rsrc_entry * entry,rsrc_directory * dir)3677*a9fa9459Szrj rsrc_resource_name (rsrc_entry * entry, rsrc_directory * dir)
3678*a9fa9459Szrj {
3679*a9fa9459Szrj   static char buffer [256];
3680*a9fa9459Szrj   bfd_boolean is_string = FALSE;
3681*a9fa9459Szrj 
3682*a9fa9459Szrj   buffer[0] = 0;
3683*a9fa9459Szrj 
3684*a9fa9459Szrj   if (dir != NULL && dir->entry != NULL && dir->entry->parent != NULL
3685*a9fa9459Szrj       && dir->entry->parent->entry != NULL)
3686*a9fa9459Szrj     {
3687*a9fa9459Szrj       strcpy (buffer, "type: ");
3688*a9fa9459Szrj       if (dir->entry->parent->entry->is_name)
3689*a9fa9459Szrj 	rsrc_print_name (buffer + strlen (buffer),
3690*a9fa9459Szrj 			 dir->entry->parent->entry->name_id.name);
3691*a9fa9459Szrj       else
3692*a9fa9459Szrj 	{
3693*a9fa9459Szrj 	  unsigned int id = dir->entry->parent->entry->name_id.id;
3694*a9fa9459Szrj 
3695*a9fa9459Szrj 	  sprintf (buffer + strlen (buffer), "%x", id);
3696*a9fa9459Szrj 	  switch (id)
3697*a9fa9459Szrj 	    {
3698*a9fa9459Szrj 	    case 1: strcat (buffer, " (CURSOR)"); break;
3699*a9fa9459Szrj 	    case 2: strcat (buffer, " (BITMAP)"); break;
3700*a9fa9459Szrj 	    case 3: strcat (buffer, " (ICON)"); break;
3701*a9fa9459Szrj             case 4: strcat (buffer, " (MENU)"); break;
3702*a9fa9459Szrj 	    case 5: strcat (buffer, " (DIALOG)"); break;
3703*a9fa9459Szrj 	    case 6: strcat (buffer, " (STRING)"); is_string = TRUE; break;
3704*a9fa9459Szrj 	    case 7: strcat (buffer, " (FONTDIR)"); break;
3705*a9fa9459Szrj 	    case 8: strcat (buffer, " (FONT)"); break;
3706*a9fa9459Szrj 	    case 9: strcat (buffer, " (ACCELERATOR)"); break;
3707*a9fa9459Szrj 	    case 10: strcat (buffer, " (RCDATA)"); break;
3708*a9fa9459Szrj 	    case 11: strcat (buffer, " (MESSAGETABLE)"); break;
3709*a9fa9459Szrj 	    case 12: strcat (buffer, " (GROUP_CURSOR)"); break;
3710*a9fa9459Szrj 	    case 14: strcat (buffer, " (GROUP_ICON)"); break;
3711*a9fa9459Szrj 	    case 16: strcat (buffer, " (VERSION)"); break;
3712*a9fa9459Szrj 	    case 17: strcat (buffer, " (DLGINCLUDE)"); break;
3713*a9fa9459Szrj 	    case 19: strcat (buffer, " (PLUGPLAY)"); break;
3714*a9fa9459Szrj 	    case 20: strcat (buffer, " (VXD)"); break;
3715*a9fa9459Szrj 	    case 21: strcat (buffer, " (ANICURSOR)"); break;
3716*a9fa9459Szrj 	    case 22: strcat (buffer, " (ANIICON)"); break;
3717*a9fa9459Szrj 	    case 23: strcat (buffer, " (HTML)"); break;
3718*a9fa9459Szrj 	    case 24: strcat (buffer, " (MANIFEST)"); break;
3719*a9fa9459Szrj 	    case 240: strcat (buffer, " (DLGINIT)"); break;
3720*a9fa9459Szrj 	    case 241: strcat (buffer, " (TOOLBAR)"); break;
3721*a9fa9459Szrj 	    }
3722*a9fa9459Szrj 	}
3723*a9fa9459Szrj     }
3724*a9fa9459Szrj 
3725*a9fa9459Szrj   if (dir != NULL && dir->entry != NULL)
3726*a9fa9459Szrj     {
3727*a9fa9459Szrj       strcat (buffer, " name: ");
3728*a9fa9459Szrj       if (dir->entry->is_name)
3729*a9fa9459Szrj 	rsrc_print_name (buffer + strlen (buffer), dir->entry->name_id.name);
3730*a9fa9459Szrj       else
3731*a9fa9459Szrj 	{
3732*a9fa9459Szrj 	  unsigned int id = dir->entry->name_id.id;
3733*a9fa9459Szrj 
3734*a9fa9459Szrj 	  sprintf (buffer + strlen (buffer), "%x", id);
3735*a9fa9459Szrj 
3736*a9fa9459Szrj 	  if (is_string)
3737*a9fa9459Szrj 	    sprintf (buffer + strlen (buffer), " (resource id range: %d - %d)",
3738*a9fa9459Szrj 		     (id - 1) << 4, (id << 4) - 1);
3739*a9fa9459Szrj 	}
3740*a9fa9459Szrj     }
3741*a9fa9459Szrj 
3742*a9fa9459Szrj   if (entry != NULL)
3743*a9fa9459Szrj     {
3744*a9fa9459Szrj       strcat (buffer, " lang: ");
3745*a9fa9459Szrj 
3746*a9fa9459Szrj       if (entry->is_name)
3747*a9fa9459Szrj 	rsrc_print_name (buffer + strlen (buffer), entry->name_id.name);
3748*a9fa9459Szrj       else
3749*a9fa9459Szrj 	sprintf (buffer + strlen (buffer), "%x", entry->name_id.id);
3750*a9fa9459Szrj     }
3751*a9fa9459Szrj 
3752*a9fa9459Szrj   return buffer;
3753*a9fa9459Szrj }
3754*a9fa9459Szrj 
3755*a9fa9459Szrj /* *sigh* Windows resource strings are special.  Only the top 28-bits of
3756*a9fa9459Szrj    their ID is stored in the NAME entry.  The bottom four bits are used as
3757*a9fa9459Szrj    an index into unicode string table that makes up the data of the leaf.
3758*a9fa9459Szrj    So identical type-name-lang string resources may not actually be
3759*a9fa9459Szrj    identical at all.
3760*a9fa9459Szrj 
3761*a9fa9459Szrj    This function is called when we have detected two string resources with
3762*a9fa9459Szrj    match top-28-bit IDs.  We have to scan the string tables inside the leaves
3763*a9fa9459Szrj    and discover if there are any real collisions.  If there are then we report
3764*a9fa9459Szrj    them and return FALSE.  Otherwise we copy any strings from B into A and
3765*a9fa9459Szrj    then return TRUE.  */
3766*a9fa9459Szrj 
3767*a9fa9459Szrj static bfd_boolean
rsrc_merge_string_entries(rsrc_entry * a ATTRIBUTE_UNUSED,rsrc_entry * b ATTRIBUTE_UNUSED)3768*a9fa9459Szrj rsrc_merge_string_entries (rsrc_entry * a ATTRIBUTE_UNUSED,
3769*a9fa9459Szrj 			   rsrc_entry * b ATTRIBUTE_UNUSED)
3770*a9fa9459Szrj {
3771*a9fa9459Szrj   unsigned int copy_needed = 0;
3772*a9fa9459Szrj   unsigned int i;
3773*a9fa9459Szrj   bfd_byte * astring;
3774*a9fa9459Szrj   bfd_byte * bstring;
3775*a9fa9459Szrj   bfd_byte * new_data;
3776*a9fa9459Szrj   bfd_byte * nstring;
3777*a9fa9459Szrj 
3778*a9fa9459Szrj   /* Step one: Find out what we have to do.  */
3779*a9fa9459Szrj   BFD_ASSERT (! a->is_dir);
3780*a9fa9459Szrj   astring = a->value.leaf->data;
3781*a9fa9459Szrj 
3782*a9fa9459Szrj   BFD_ASSERT (! b->is_dir);
3783*a9fa9459Szrj   bstring = b->value.leaf->data;
3784*a9fa9459Szrj 
3785*a9fa9459Szrj   for (i = 0; i < 16; i++)
3786*a9fa9459Szrj     {
3787*a9fa9459Szrj       unsigned int alen = astring[0] + (astring[1] << 8);
3788*a9fa9459Szrj       unsigned int blen = bstring[0] + (bstring[1] << 8);
3789*a9fa9459Szrj 
3790*a9fa9459Szrj       if (alen == 0)
3791*a9fa9459Szrj 	{
3792*a9fa9459Szrj 	  copy_needed += blen * 2;
3793*a9fa9459Szrj 	}
3794*a9fa9459Szrj       else if (blen == 0)
3795*a9fa9459Szrj 	;
3796*a9fa9459Szrj       else if (alen != blen)
3797*a9fa9459Szrj 	/* FIXME: Should we continue the loop in order to report other duplicates ?  */
3798*a9fa9459Szrj 	break;
3799*a9fa9459Szrj       /* alen == blen != 0.  We might have two identical strings.  If so we
3800*a9fa9459Szrj 	 can ignore the second one.  There is no need for wchar_t vs UTF-16
3801*a9fa9459Szrj 	 theatrics here - we are only interested in (case sensitive) equality.  */
3802*a9fa9459Szrj       else if (memcmp (astring + 2, bstring + 2, alen * 2) != 0)
3803*a9fa9459Szrj 	break;
3804*a9fa9459Szrj 
3805*a9fa9459Szrj       astring += (alen + 1) * 2;
3806*a9fa9459Szrj       bstring += (blen + 1) * 2;
3807*a9fa9459Szrj     }
3808*a9fa9459Szrj 
3809*a9fa9459Szrj   if (i != 16)
3810*a9fa9459Szrj     {
3811*a9fa9459Szrj       if (a->parent != NULL
3812*a9fa9459Szrj 	  && a->parent->entry != NULL
3813*a9fa9459Szrj 	  && a->parent->entry->is_name == FALSE)
3814*a9fa9459Szrj 	_bfd_error_handler (_(".rsrc merge failure: duplicate string resource: %d"),
3815*a9fa9459Szrj 			    ((a->parent->entry->name_id.id - 1) << 4) + i);
3816*a9fa9459Szrj       return FALSE;
3817*a9fa9459Szrj     }
3818*a9fa9459Szrj 
3819*a9fa9459Szrj   if (copy_needed == 0)
3820*a9fa9459Szrj     return TRUE;
3821*a9fa9459Szrj 
3822*a9fa9459Szrj   /* If we reach here then A and B must both have non-colliding strings.
3823*a9fa9459Szrj      (We never get string resources with fully empty string tables).
3824*a9fa9459Szrj      We need to allocate an extra COPY_NEEDED bytes in A and then bring
3825*a9fa9459Szrj      in B's strings.  */
3826*a9fa9459Szrj   new_data = bfd_malloc (a->value.leaf->size + copy_needed);
3827*a9fa9459Szrj   if (new_data == NULL)
3828*a9fa9459Szrj     return FALSE;
3829*a9fa9459Szrj 
3830*a9fa9459Szrj   nstring = new_data;
3831*a9fa9459Szrj   astring = a->value.leaf->data;
3832*a9fa9459Szrj   bstring = b->value.leaf->data;
3833*a9fa9459Szrj 
3834*a9fa9459Szrj   for (i = 0; i < 16; i++)
3835*a9fa9459Szrj     {
3836*a9fa9459Szrj       unsigned int alen = astring[0] + (astring[1] << 8);
3837*a9fa9459Szrj       unsigned int blen = bstring[0] + (bstring[1] << 8);
3838*a9fa9459Szrj 
3839*a9fa9459Szrj       if (alen != 0)
3840*a9fa9459Szrj 	{
3841*a9fa9459Szrj 	  memcpy (nstring, astring, (alen + 1) * 2);
3842*a9fa9459Szrj 	  nstring += (alen + 1) * 2;
3843*a9fa9459Szrj 	}
3844*a9fa9459Szrj       else if (blen != 0)
3845*a9fa9459Szrj 	{
3846*a9fa9459Szrj 	  memcpy (nstring, bstring, (blen + 1) * 2);
3847*a9fa9459Szrj 	  nstring += (blen + 1) * 2;
3848*a9fa9459Szrj 	}
3849*a9fa9459Szrj       else
3850*a9fa9459Szrj 	{
3851*a9fa9459Szrj 	  * nstring++ = 0;
3852*a9fa9459Szrj 	  * nstring++ = 0;
3853*a9fa9459Szrj 	}
3854*a9fa9459Szrj 
3855*a9fa9459Szrj       astring += (alen + 1) * 2;
3856*a9fa9459Szrj       bstring += (blen + 1) * 2;
3857*a9fa9459Szrj     }
3858*a9fa9459Szrj 
3859*a9fa9459Szrj   BFD_ASSERT (nstring - new_data == (signed) (a->value.leaf->size + copy_needed));
3860*a9fa9459Szrj 
3861*a9fa9459Szrj   free (a->value.leaf->data);
3862*a9fa9459Szrj   a->value.leaf->data = new_data;
3863*a9fa9459Szrj   a->value.leaf->size += copy_needed;
3864*a9fa9459Szrj 
3865*a9fa9459Szrj   return TRUE;
3866*a9fa9459Szrj }
3867*a9fa9459Szrj 
3868*a9fa9459Szrj static void rsrc_merge (rsrc_entry *, rsrc_entry *);
3869*a9fa9459Szrj 
3870*a9fa9459Szrj /* Sort the entries in given part of the directory.
3871*a9fa9459Szrj    We use an old fashioned bubble sort because we are dealing
3872*a9fa9459Szrj    with lists and we want to handle matches specially.  */
3873*a9fa9459Szrj 
3874*a9fa9459Szrj static void
rsrc_sort_entries(rsrc_dir_chain * chain,bfd_boolean is_name,rsrc_directory * dir)3875*a9fa9459Szrj rsrc_sort_entries (rsrc_dir_chain *  chain,
3876*a9fa9459Szrj 		   bfd_boolean       is_name,
3877*a9fa9459Szrj 		   rsrc_directory *  dir)
3878*a9fa9459Szrj {
3879*a9fa9459Szrj   rsrc_entry * entry;
3880*a9fa9459Szrj   rsrc_entry * next;
3881*a9fa9459Szrj   rsrc_entry ** points_to_entry;
3882*a9fa9459Szrj   bfd_boolean swapped;
3883*a9fa9459Szrj 
3884*a9fa9459Szrj   if (chain->num_entries < 2)
3885*a9fa9459Szrj     return;
3886*a9fa9459Szrj 
3887*a9fa9459Szrj   do
3888*a9fa9459Szrj     {
3889*a9fa9459Szrj       swapped = FALSE;
3890*a9fa9459Szrj       points_to_entry = & chain->first_entry;
3891*a9fa9459Szrj       entry = * points_to_entry;
3892*a9fa9459Szrj       next  = entry->next_entry;
3893*a9fa9459Szrj 
3894*a9fa9459Szrj       do
3895*a9fa9459Szrj 	{
3896*a9fa9459Szrj 	  signed int cmp = rsrc_cmp (is_name, entry, next);
3897*a9fa9459Szrj 
3898*a9fa9459Szrj 	  if (cmp > 0)
3899*a9fa9459Szrj 	    {
3900*a9fa9459Szrj 	      entry->next_entry = next->next_entry;
3901*a9fa9459Szrj 	      next->next_entry = entry;
3902*a9fa9459Szrj 	      * points_to_entry = next;
3903*a9fa9459Szrj 	      points_to_entry = & next->next_entry;
3904*a9fa9459Szrj 	      next = entry->next_entry;
3905*a9fa9459Szrj 	      swapped = TRUE;
3906*a9fa9459Szrj 	    }
3907*a9fa9459Szrj 	  else if (cmp == 0)
3908*a9fa9459Szrj 	    {
3909*a9fa9459Szrj 	      if (entry->is_dir && next->is_dir)
3910*a9fa9459Szrj 		{
3911*a9fa9459Szrj 		  /* When we encounter identical directory entries we have to
3912*a9fa9459Szrj 		     merge them together.  The exception to this rule is for
3913*a9fa9459Szrj 		     resource manifests - there can only be one of these,
3914*a9fa9459Szrj 		     even if they differ in language.  Zero-language manifests
3915*a9fa9459Szrj 		     are assumed to be default manifests (provided by the
3916*a9fa9459Szrj 		     Cygwin/MinGW build system) and these can be silently dropped,
3917*a9fa9459Szrj 		     unless that would reduce the number of manifests to zero.
3918*a9fa9459Szrj 		     There should only ever be one non-zero lang manifest -
3919*a9fa9459Szrj 		     if there are more it is an error.  A non-zero lang
3920*a9fa9459Szrj 		     manifest takes precedence over a default manifest.  */
3921*a9fa9459Szrj 		  if (entry->is_name == FALSE
3922*a9fa9459Szrj 		      && entry->name_id.id == 1
3923*a9fa9459Szrj 		      && dir != NULL
3924*a9fa9459Szrj 		      && dir->entry != NULL
3925*a9fa9459Szrj 		      && dir->entry->is_name == FALSE
3926*a9fa9459Szrj 		      && dir->entry->name_id.id == 0x18)
3927*a9fa9459Szrj 		    {
3928*a9fa9459Szrj 		      if (next->value.directory->names.num_entries == 0
3929*a9fa9459Szrj 			  && next->value.directory->ids.num_entries == 1
3930*a9fa9459Szrj 			  && next->value.directory->ids.first_entry->is_name == FALSE
3931*a9fa9459Szrj 			  && next->value.directory->ids.first_entry->name_id.id == 0)
3932*a9fa9459Szrj 			/* Fall through so that NEXT is dropped.  */
3933*a9fa9459Szrj 			;
3934*a9fa9459Szrj 		      else if (entry->value.directory->names.num_entries == 0
3935*a9fa9459Szrj 			       && entry->value.directory->ids.num_entries == 1
3936*a9fa9459Szrj 			       && entry->value.directory->ids.first_entry->is_name == FALSE
3937*a9fa9459Szrj 			       && entry->value.directory->ids.first_entry->name_id.id == 0)
3938*a9fa9459Szrj 			{
3939*a9fa9459Szrj 			  /* Swap ENTRY and NEXT.  Then fall through so that the old ENTRY is dropped.  */
3940*a9fa9459Szrj 			  entry->next_entry = next->next_entry;
3941*a9fa9459Szrj 			  next->next_entry = entry;
3942*a9fa9459Szrj 			  * points_to_entry = next;
3943*a9fa9459Szrj 			  points_to_entry = & next->next_entry;
3944*a9fa9459Szrj 			  next = entry->next_entry;
3945*a9fa9459Szrj 			  swapped = TRUE;
3946*a9fa9459Szrj 			}
3947*a9fa9459Szrj 		      else
3948*a9fa9459Szrj 			{
3949*a9fa9459Szrj 			  _bfd_error_handler (_(".rsrc merge failure: multiple non-default manifests"));
3950*a9fa9459Szrj 			  bfd_set_error (bfd_error_file_truncated);
3951*a9fa9459Szrj 			  return;
3952*a9fa9459Szrj 			}
3953*a9fa9459Szrj 
3954*a9fa9459Szrj 		      /* Unhook NEXT from the chain.  */
3955*a9fa9459Szrj 		      /* FIXME: memory loss here.  */
3956*a9fa9459Szrj 		      entry->next_entry = next->next_entry;
3957*a9fa9459Szrj 		      chain->num_entries --;
3958*a9fa9459Szrj 		      if (chain->num_entries < 2)
3959*a9fa9459Szrj 			return;
3960*a9fa9459Szrj 		      next = next->next_entry;
3961*a9fa9459Szrj 		    }
3962*a9fa9459Szrj 		  else
3963*a9fa9459Szrj 		    rsrc_merge (entry, next);
3964*a9fa9459Szrj 		}
3965*a9fa9459Szrj 	      else if (entry->is_dir != next->is_dir)
3966*a9fa9459Szrj 		{
3967*a9fa9459Szrj 		  _bfd_error_handler (_(".rsrc merge failure: a directory matches a leaf"));
3968*a9fa9459Szrj 		  bfd_set_error (bfd_error_file_truncated);
3969*a9fa9459Szrj 		  return;
3970*a9fa9459Szrj 		}
3971*a9fa9459Szrj 	      else
3972*a9fa9459Szrj 		{
3973*a9fa9459Szrj 		  /* Otherwise with identical leaves we issue an error
3974*a9fa9459Szrj 		     message - because there should never be duplicates.
3975*a9fa9459Szrj 		     The exception is Type 18/Name 1/Lang 0 which is the
3976*a9fa9459Szrj 		     defaul manifest - this can just be dropped.  */
3977*a9fa9459Szrj 		  if (entry->is_name == FALSE
3978*a9fa9459Szrj 		      && entry->name_id.id == 0
3979*a9fa9459Szrj 		      && dir != NULL
3980*a9fa9459Szrj 		      && dir->entry != NULL
3981*a9fa9459Szrj 		      && dir->entry->is_name == FALSE
3982*a9fa9459Szrj 		      && dir->entry->name_id.id == 1
3983*a9fa9459Szrj 		      && dir->entry->parent != NULL
3984*a9fa9459Szrj 		      && dir->entry->parent->entry != NULL
3985*a9fa9459Szrj 		      && dir->entry->parent->entry->is_name == FALSE
3986*a9fa9459Szrj 		      && dir->entry->parent->entry->name_id.id == 0x18 /* RT_MANIFEST */)
3987*a9fa9459Szrj 		    ;
3988*a9fa9459Szrj 		  else if (dir != NULL
3989*a9fa9459Szrj 			   && dir->entry != NULL
3990*a9fa9459Szrj 			   && dir->entry->parent != NULL
3991*a9fa9459Szrj 			   && dir->entry->parent->entry != NULL
3992*a9fa9459Szrj 			   && dir->entry->parent->entry->is_name == FALSE
3993*a9fa9459Szrj 			   && dir->entry->parent->entry->name_id.id == 0x6 /* RT_STRING */)
3994*a9fa9459Szrj 		    {
3995*a9fa9459Szrj 		      /* Strings need special handling.  */
3996*a9fa9459Szrj 		      if (! rsrc_merge_string_entries (entry, next))
3997*a9fa9459Szrj 			{
3998*a9fa9459Szrj 			  /* _bfd_error_handler should have been called inside merge_strings.  */
3999*a9fa9459Szrj 			  bfd_set_error (bfd_error_file_truncated);
4000*a9fa9459Szrj 			  return;
4001*a9fa9459Szrj 			}
4002*a9fa9459Szrj 		    }
4003*a9fa9459Szrj 		  else
4004*a9fa9459Szrj 		    {
4005*a9fa9459Szrj 		      if (dir == NULL
4006*a9fa9459Szrj 			  || dir->entry == NULL
4007*a9fa9459Szrj 			  || dir->entry->parent == NULL
4008*a9fa9459Szrj 			  || dir->entry->parent->entry == NULL)
4009*a9fa9459Szrj 			_bfd_error_handler (_(".rsrc merge failure: duplicate leaf"));
4010*a9fa9459Szrj 		      else
4011*a9fa9459Szrj 			_bfd_error_handler (_(".rsrc merge failure: duplicate leaf: %s"),
4012*a9fa9459Szrj 					    rsrc_resource_name (entry, dir));
4013*a9fa9459Szrj 		      bfd_set_error (bfd_error_file_truncated);
4014*a9fa9459Szrj 		      return;
4015*a9fa9459Szrj 		    }
4016*a9fa9459Szrj 		}
4017*a9fa9459Szrj 
4018*a9fa9459Szrj 	      /* Unhook NEXT from the chain.  */
4019*a9fa9459Szrj 	      entry->next_entry = next->next_entry;
4020*a9fa9459Szrj 	      chain->num_entries --;
4021*a9fa9459Szrj 	      if (chain->num_entries < 2)
4022*a9fa9459Szrj 		return;
4023*a9fa9459Szrj 	      next = next->next_entry;
4024*a9fa9459Szrj 	    }
4025*a9fa9459Szrj 	  else
4026*a9fa9459Szrj 	    {
4027*a9fa9459Szrj 	      points_to_entry = & entry->next_entry;
4028*a9fa9459Szrj 	      entry = next;
4029*a9fa9459Szrj 	      next = next->next_entry;
4030*a9fa9459Szrj 	    }
4031*a9fa9459Szrj 	}
4032*a9fa9459Szrj       while (next);
4033*a9fa9459Szrj 
4034*a9fa9459Szrj       chain->last_entry = entry;
4035*a9fa9459Szrj     }
4036*a9fa9459Szrj   while (swapped);
4037*a9fa9459Szrj }
4038*a9fa9459Szrj 
4039*a9fa9459Szrj /* Attach B's chain onto A.  */
4040*a9fa9459Szrj static void
rsrc_attach_chain(rsrc_dir_chain * achain,rsrc_dir_chain * bchain)4041*a9fa9459Szrj rsrc_attach_chain (rsrc_dir_chain * achain, rsrc_dir_chain * bchain)
4042*a9fa9459Szrj {
4043*a9fa9459Szrj   if (bchain->num_entries == 0)
4044*a9fa9459Szrj     return;
4045*a9fa9459Szrj 
4046*a9fa9459Szrj   achain->num_entries += bchain->num_entries;
4047*a9fa9459Szrj 
4048*a9fa9459Szrj   if (achain->first_entry == NULL)
4049*a9fa9459Szrj     {
4050*a9fa9459Szrj       achain->first_entry = bchain->first_entry;
4051*a9fa9459Szrj       achain->last_entry  = bchain->last_entry;
4052*a9fa9459Szrj     }
4053*a9fa9459Szrj   else
4054*a9fa9459Szrj     {
4055*a9fa9459Szrj       achain->last_entry->next_entry = bchain->first_entry;
4056*a9fa9459Szrj       achain->last_entry = bchain->last_entry;
4057*a9fa9459Szrj     }
4058*a9fa9459Szrj 
4059*a9fa9459Szrj   bchain->num_entries = 0;
4060*a9fa9459Szrj   bchain->first_entry = bchain->last_entry = NULL;
4061*a9fa9459Szrj }
4062*a9fa9459Szrj 
4063*a9fa9459Szrj static void
rsrc_merge(struct rsrc_entry * a,struct rsrc_entry * b)4064*a9fa9459Szrj rsrc_merge (struct rsrc_entry * a, struct rsrc_entry * b)
4065*a9fa9459Szrj {
4066*a9fa9459Szrj   rsrc_directory * adir;
4067*a9fa9459Szrj   rsrc_directory * bdir;
4068*a9fa9459Szrj 
4069*a9fa9459Szrj   BFD_ASSERT (a->is_dir);
4070*a9fa9459Szrj   BFD_ASSERT (b->is_dir);
4071*a9fa9459Szrj 
4072*a9fa9459Szrj   adir = a->value.directory;
4073*a9fa9459Szrj   bdir = b->value.directory;
4074*a9fa9459Szrj 
4075*a9fa9459Szrj   if (adir->characteristics != bdir->characteristics)
4076*a9fa9459Szrj     {
4077*a9fa9459Szrj       _bfd_error_handler (_(".rsrc merge failure: dirs with differing characteristics\n"));
4078*a9fa9459Szrj       bfd_set_error (bfd_error_file_truncated);
4079*a9fa9459Szrj       return;
4080*a9fa9459Szrj     }
4081*a9fa9459Szrj 
4082*a9fa9459Szrj   if (adir->major != bdir->major || adir->minor != bdir->minor)
4083*a9fa9459Szrj     {
4084*a9fa9459Szrj       _bfd_error_handler (_(".rsrc merge failure: differing directory versions\n"));
4085*a9fa9459Szrj       bfd_set_error (bfd_error_file_truncated);
4086*a9fa9459Szrj       return;
4087*a9fa9459Szrj     }
4088*a9fa9459Szrj 
4089*a9fa9459Szrj   /* Attach B's name chain to A.  */
4090*a9fa9459Szrj   rsrc_attach_chain (& adir->names, & bdir->names);
4091*a9fa9459Szrj 
4092*a9fa9459Szrj   /* Attach B's ID chain to A.  */
4093*a9fa9459Szrj   rsrc_attach_chain (& adir->ids, & bdir->ids);
4094*a9fa9459Szrj 
4095*a9fa9459Szrj   /* Now sort A's entries.  */
4096*a9fa9459Szrj   rsrc_sort_entries (& adir->names, TRUE, adir);
4097*a9fa9459Szrj   rsrc_sort_entries (& adir->ids, FALSE, adir);
4098*a9fa9459Szrj }
4099*a9fa9459Szrj 
4100*a9fa9459Szrj /* Check the .rsrc section.  If it contains multiple concatenated
4101*a9fa9459Szrj    resources then we must merge them properly.  Otherwise Windows
4102*a9fa9459Szrj    will ignore all but the first set.  */
4103*a9fa9459Szrj 
4104*a9fa9459Szrj static void
rsrc_process_section(bfd * abfd,struct coff_final_link_info * pfinfo)4105*a9fa9459Szrj rsrc_process_section (bfd * abfd,
4106*a9fa9459Szrj 		      struct coff_final_link_info * pfinfo)
4107*a9fa9459Szrj {
4108*a9fa9459Szrj   rsrc_directory    new_table;
4109*a9fa9459Szrj   bfd_size_type     size;
4110*a9fa9459Szrj   asection *        sec;
4111*a9fa9459Szrj   pe_data_type *    pe;
4112*a9fa9459Szrj   bfd_vma           rva_bias;
4113*a9fa9459Szrj   bfd_byte *        data;
4114*a9fa9459Szrj   bfd_byte *        datastart;
4115*a9fa9459Szrj   bfd_byte *        dataend;
4116*a9fa9459Szrj   bfd_byte *        new_data;
4117*a9fa9459Szrj   unsigned int      num_resource_sets;
4118*a9fa9459Szrj   rsrc_directory *  type_tables;
4119*a9fa9459Szrj   rsrc_write_data   write_data;
4120*a9fa9459Szrj   unsigned int      indx;
4121*a9fa9459Szrj   bfd *             input;
4122*a9fa9459Szrj   unsigned int      num_input_rsrc = 0;
4123*a9fa9459Szrj   unsigned int      max_num_input_rsrc = 4;
4124*a9fa9459Szrj   ptrdiff_t *       rsrc_sizes = NULL;
4125*a9fa9459Szrj 
4126*a9fa9459Szrj   new_table.names.num_entries = 0;
4127*a9fa9459Szrj   new_table.ids.num_entries = 0;
4128*a9fa9459Szrj 
4129*a9fa9459Szrj   sec = bfd_get_section_by_name (abfd, ".rsrc");
4130*a9fa9459Szrj   if (sec == NULL || (size = sec->rawsize) == 0)
4131*a9fa9459Szrj     return;
4132*a9fa9459Szrj 
4133*a9fa9459Szrj   pe = pe_data (abfd);
4134*a9fa9459Szrj   if (pe == NULL)
4135*a9fa9459Szrj     return;
4136*a9fa9459Szrj 
4137*a9fa9459Szrj   rva_bias = sec->vma - pe->pe_opthdr.ImageBase;
4138*a9fa9459Szrj 
4139*a9fa9459Szrj   data = bfd_malloc (size);
4140*a9fa9459Szrj   if (data == NULL)
4141*a9fa9459Szrj     return;
4142*a9fa9459Szrj 
4143*a9fa9459Szrj   datastart = data;
4144*a9fa9459Szrj 
4145*a9fa9459Szrj   if (! bfd_get_section_contents (abfd, sec, data, 0, size))
4146*a9fa9459Szrj     goto end;
4147*a9fa9459Szrj 
4148*a9fa9459Szrj   /* Step zero: Scan the input bfds looking for .rsrc sections and record
4149*a9fa9459Szrj      their lengths.  Note - we rely upon the fact that the linker script
4150*a9fa9459Szrj      does *not* sort the input .rsrc sections, so that the order in the
4151*a9fa9459Szrj      linkinfo list matches the order in the output .rsrc section.
4152*a9fa9459Szrj 
4153*a9fa9459Szrj      We need to know the lengths because each input .rsrc section has padding
4154*a9fa9459Szrj      at the end of a variable amount.  (It does not appear to be based upon
4155*a9fa9459Szrj      the section alignment or the file alignment).  We need to skip any
4156*a9fa9459Szrj      padding bytes when parsing the input .rsrc sections.  */
4157*a9fa9459Szrj   rsrc_sizes = bfd_malloc (max_num_input_rsrc * sizeof * rsrc_sizes);
4158*a9fa9459Szrj   if (rsrc_sizes == NULL)
4159*a9fa9459Szrj     goto end;
4160*a9fa9459Szrj 
4161*a9fa9459Szrj   for (input = pfinfo->info->input_bfds;
4162*a9fa9459Szrj        input != NULL;
4163*a9fa9459Szrj        input = input->link.next)
4164*a9fa9459Szrj     {
4165*a9fa9459Szrj       asection * rsrc_sec = bfd_get_section_by_name (input, ".rsrc");
4166*a9fa9459Szrj 
4167*a9fa9459Szrj       /* PR 18372 - skip discarded .rsrc sections.  */
4168*a9fa9459Szrj       if (rsrc_sec != NULL && !discarded_section (rsrc_sec))
4169*a9fa9459Szrj 	{
4170*a9fa9459Szrj 	  if (num_input_rsrc == max_num_input_rsrc)
4171*a9fa9459Szrj 	    {
4172*a9fa9459Szrj 	      max_num_input_rsrc += 10;
4173*a9fa9459Szrj 	      rsrc_sizes = bfd_realloc (rsrc_sizes, max_num_input_rsrc
4174*a9fa9459Szrj 					* sizeof * rsrc_sizes);
4175*a9fa9459Szrj 	      if (rsrc_sizes == NULL)
4176*a9fa9459Szrj 		goto end;
4177*a9fa9459Szrj 	    }
4178*a9fa9459Szrj 
4179*a9fa9459Szrj 	  BFD_ASSERT (rsrc_sec->size > 0);
4180*a9fa9459Szrj 	  rsrc_sizes [num_input_rsrc ++] = rsrc_sec->size;
4181*a9fa9459Szrj 	}
4182*a9fa9459Szrj     }
4183*a9fa9459Szrj 
4184*a9fa9459Szrj   if (num_input_rsrc < 2)
4185*a9fa9459Szrj     goto end;
4186*a9fa9459Szrj 
4187*a9fa9459Szrj   /* Step one: Walk the section, computing the size of the tables,
4188*a9fa9459Szrj      leaves and data and decide if we need to do anything.  */
4189*a9fa9459Szrj   dataend = data + size;
4190*a9fa9459Szrj   num_resource_sets = 0;
4191*a9fa9459Szrj 
4192*a9fa9459Szrj   while (data < dataend)
4193*a9fa9459Szrj     {
4194*a9fa9459Szrj       bfd_byte * p = data;
4195*a9fa9459Szrj 
4196*a9fa9459Szrj       data = rsrc_count_directory (abfd, data, data, dataend, rva_bias);
4197*a9fa9459Szrj 
4198*a9fa9459Szrj       if (data > dataend)
4199*a9fa9459Szrj 	{
4200*a9fa9459Szrj 	  /* Corrupted .rsrc section - cannot merge.  */
4201*a9fa9459Szrj 	  _bfd_error_handler (_("%s: .rsrc merge failure: corrupt .rsrc section"),
4202*a9fa9459Szrj 			      bfd_get_filename (abfd));
4203*a9fa9459Szrj 	  bfd_set_error (bfd_error_file_truncated);
4204*a9fa9459Szrj 	  goto end;
4205*a9fa9459Szrj 	}
4206*a9fa9459Szrj 
4207*a9fa9459Szrj       if ((data - p) > rsrc_sizes [num_resource_sets])
4208*a9fa9459Szrj 	{
4209*a9fa9459Szrj 	  _bfd_error_handler (_("%s: .rsrc merge failure: unexpected .rsrc size"),
4210*a9fa9459Szrj 			      bfd_get_filename (abfd));
4211*a9fa9459Szrj 	  bfd_set_error (bfd_error_file_truncated);
4212*a9fa9459Szrj 	  goto end;
4213*a9fa9459Szrj 	}
4214*a9fa9459Szrj       /* FIXME: Should we add a check for "data - p" being much smaller
4215*a9fa9459Szrj 	 than rsrc_sizes[num_resource_sets] ?  */
4216*a9fa9459Szrj 
4217*a9fa9459Szrj       data = p + rsrc_sizes[num_resource_sets];
4218*a9fa9459Szrj       rva_bias += data - p;
4219*a9fa9459Szrj       ++ num_resource_sets;
4220*a9fa9459Szrj     }
4221*a9fa9459Szrj   BFD_ASSERT (num_resource_sets == num_input_rsrc);
4222*a9fa9459Szrj 
4223*a9fa9459Szrj   /* Step two: Walk the data again, building trees of the resources.  */
4224*a9fa9459Szrj   data = datastart;
4225*a9fa9459Szrj   rva_bias = sec->vma - pe->pe_opthdr.ImageBase;
4226*a9fa9459Szrj 
4227*a9fa9459Szrj   type_tables = bfd_malloc (num_resource_sets * sizeof * type_tables);
4228*a9fa9459Szrj   if (type_tables == NULL)
4229*a9fa9459Szrj     goto end;
4230*a9fa9459Szrj 
4231*a9fa9459Szrj   indx = 0;
4232*a9fa9459Szrj   while (data < dataend)
4233*a9fa9459Szrj     {
4234*a9fa9459Szrj       bfd_byte * p = data;
4235*a9fa9459Szrj 
4236*a9fa9459Szrj       (void) rsrc_parse_directory (abfd, type_tables + indx, data, data,
4237*a9fa9459Szrj 				   dataend, rva_bias, NULL);
4238*a9fa9459Szrj       data = p + rsrc_sizes[indx];
4239*a9fa9459Szrj       rva_bias += data - p;
4240*a9fa9459Szrj       ++ indx;
4241*a9fa9459Szrj     }
4242*a9fa9459Szrj   BFD_ASSERT (indx == num_resource_sets);
4243*a9fa9459Szrj 
4244*a9fa9459Szrj   /* Step three: Merge the top level tables (there can be only one).
4245*a9fa9459Szrj 
4246*a9fa9459Szrj      We must ensure that the merged entries are in ascending order.
4247*a9fa9459Szrj 
4248*a9fa9459Szrj      We also thread the top level table entries from the old tree onto
4249*a9fa9459Szrj      the new table, so that they can be pulled off later.  */
4250*a9fa9459Szrj 
4251*a9fa9459Szrj   /* FIXME: Should we verify that all type tables are the same ?  */
4252*a9fa9459Szrj   new_table.characteristics = type_tables[0].characteristics;
4253*a9fa9459Szrj   new_table.time            = type_tables[0].time;
4254*a9fa9459Szrj   new_table.major           = type_tables[0].major;
4255*a9fa9459Szrj   new_table.minor           = type_tables[0].minor;
4256*a9fa9459Szrj 
4257*a9fa9459Szrj   /* Chain the NAME entries onto the table.  */
4258*a9fa9459Szrj   new_table.names.first_entry = NULL;
4259*a9fa9459Szrj   new_table.names.last_entry = NULL;
4260*a9fa9459Szrj 
4261*a9fa9459Szrj   for (indx = 0; indx < num_resource_sets; indx++)
4262*a9fa9459Szrj     rsrc_attach_chain (& new_table.names, & type_tables[indx].names);
4263*a9fa9459Szrj 
4264*a9fa9459Szrj   rsrc_sort_entries (& new_table.names, TRUE, & new_table);
4265*a9fa9459Szrj 
4266*a9fa9459Szrj   /* Chain the ID entries onto the table.  */
4267*a9fa9459Szrj   new_table.ids.first_entry = NULL;
4268*a9fa9459Szrj   new_table.ids.last_entry = NULL;
4269*a9fa9459Szrj 
4270*a9fa9459Szrj   for (indx = 0; indx < num_resource_sets; indx++)
4271*a9fa9459Szrj     rsrc_attach_chain (& new_table.ids, & type_tables[indx].ids);
4272*a9fa9459Szrj 
4273*a9fa9459Szrj   rsrc_sort_entries (& new_table.ids, FALSE, & new_table);
4274*a9fa9459Szrj 
4275*a9fa9459Szrj   /* Step four: Create new contents for the .rsrc section.  */
4276*a9fa9459Szrj   /* Step four point one: Compute the size of each region of the .rsrc section.
4277*a9fa9459Szrj      We do this now, rather than earlier, as the merging above may have dropped
4278*a9fa9459Szrj      some entries.  */
4279*a9fa9459Szrj   sizeof_leaves = sizeof_strings = sizeof_tables_and_entries = 0;
4280*a9fa9459Szrj   rsrc_compute_region_sizes (& new_table);
4281*a9fa9459Szrj   /* We increment sizeof_strings to make sure that resource data
4282*a9fa9459Szrj      starts on an 8-byte boundary.  FIXME: Is this correct ?  */
4283*a9fa9459Szrj   sizeof_strings = (sizeof_strings + 7) & ~ 7;
4284*a9fa9459Szrj 
4285*a9fa9459Szrj   new_data = bfd_zalloc (abfd, size);
4286*a9fa9459Szrj   if (new_data == NULL)
4287*a9fa9459Szrj     goto end;
4288*a9fa9459Szrj 
4289*a9fa9459Szrj   write_data.abfd        = abfd;
4290*a9fa9459Szrj   write_data.datastart   = new_data;
4291*a9fa9459Szrj   write_data.next_table  = new_data;
4292*a9fa9459Szrj   write_data.next_leaf   = new_data + sizeof_tables_and_entries;
4293*a9fa9459Szrj   write_data.next_string = write_data.next_leaf + sizeof_leaves;
4294*a9fa9459Szrj   write_data.next_data   = write_data.next_string + sizeof_strings;
4295*a9fa9459Szrj   write_data.rva_bias    = sec->vma - pe->pe_opthdr.ImageBase;
4296*a9fa9459Szrj 
4297*a9fa9459Szrj   rsrc_write_directory (& write_data, & new_table);
4298*a9fa9459Szrj 
4299*a9fa9459Szrj   /* Step five: Replace the old contents with the new.
4300*a9fa9459Szrj      We recompute the size as we may have lost entries due to mergeing.  */
4301*a9fa9459Szrj   size = ((write_data.next_data - new_data) + 3) & ~ 3;
4302*a9fa9459Szrj 
4303*a9fa9459Szrj   {
4304*a9fa9459Szrj     int page_size;
4305*a9fa9459Szrj 
4306*a9fa9459Szrj     if (coff_data (abfd)->link_info)
4307*a9fa9459Szrj       {
4308*a9fa9459Szrj 	page_size = pe_data (abfd)->pe_opthdr.FileAlignment;
4309*a9fa9459Szrj 
4310*a9fa9459Szrj 	/* If no file alignment has been set, default to one.
4311*a9fa9459Szrj 	   This repairs 'ld -r' for arm-wince-pe target.  */
4312*a9fa9459Szrj 	if (page_size == 0)
4313*a9fa9459Szrj 	  page_size = 1;
4314*a9fa9459Szrj       }
4315*a9fa9459Szrj     else
4316*a9fa9459Szrj       page_size = PE_DEF_FILE_ALIGNMENT;
4317*a9fa9459Szrj     size = (size + page_size - 1) & - page_size;
4318*a9fa9459Szrj   }
4319*a9fa9459Szrj 
4320*a9fa9459Szrj   bfd_set_section_contents (pfinfo->output_bfd, sec, new_data, 0, size);
4321*a9fa9459Szrj   sec->size = sec->rawsize = size;
4322*a9fa9459Szrj 
4323*a9fa9459Szrj  end:
4324*a9fa9459Szrj   /* Step six: Free all the memory that we have used.  */
4325*a9fa9459Szrj   /* FIXME: Free the resource tree, if we have one.  */
4326*a9fa9459Szrj   free (datastart);
4327*a9fa9459Szrj   free (rsrc_sizes);
4328*a9fa9459Szrj }
4329*a9fa9459Szrj 
4330*a9fa9459Szrj /* Handle the .idata section and other things that need symbol table
4331*a9fa9459Szrj    access.  */
4332*a9fa9459Szrj 
4333*a9fa9459Szrj bfd_boolean
_bfd_XXi_final_link_postscript(bfd * abfd,struct coff_final_link_info * pfinfo)4334*a9fa9459Szrj _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
4335*a9fa9459Szrj {
4336*a9fa9459Szrj   struct coff_link_hash_entry *h1;
4337*a9fa9459Szrj   struct bfd_link_info *info = pfinfo->info;
4338*a9fa9459Szrj   bfd_boolean result = TRUE;
4339*a9fa9459Szrj 
4340*a9fa9459Szrj   /* There are a few fields that need to be filled in now while we
4341*a9fa9459Szrj      have symbol table access.
4342*a9fa9459Szrj 
4343*a9fa9459Szrj      The .idata subsections aren't directly available as sections, but
4344*a9fa9459Szrj      they are in the symbol table, so get them from there.  */
4345*a9fa9459Szrj 
4346*a9fa9459Szrj   /* The import directory.  This is the address of .idata$2, with size
4347*a9fa9459Szrj      of .idata$2 + .idata$3.  */
4348*a9fa9459Szrj   h1 = coff_link_hash_lookup (coff_hash_table (info),
4349*a9fa9459Szrj 			      ".idata$2", FALSE, FALSE, TRUE);
4350*a9fa9459Szrj   if (h1 != NULL)
4351*a9fa9459Szrj     {
4352*a9fa9459Szrj       /* PR ld/2729: We cannot rely upon all the output sections having been
4353*a9fa9459Szrj 	 created properly, so check before referencing them.  Issue a warning
4354*a9fa9459Szrj 	 message for any sections tht could not be found.  */
4355*a9fa9459Szrj       if ((h1->root.type == bfd_link_hash_defined
4356*a9fa9459Szrj 	   || h1->root.type == bfd_link_hash_defweak)
4357*a9fa9459Szrj 	  && h1->root.u.def.section != NULL
4358*a9fa9459Szrj 	  && h1->root.u.def.section->output_section != NULL)
4359*a9fa9459Szrj 	pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress =
4360*a9fa9459Szrj 	  (h1->root.u.def.value
4361*a9fa9459Szrj 	   + h1->root.u.def.section->output_section->vma
4362*a9fa9459Szrj 	   + h1->root.u.def.section->output_offset);
4363*a9fa9459Szrj       else
4364*a9fa9459Szrj 	{
4365*a9fa9459Szrj 	  _bfd_error_handler
4366*a9fa9459Szrj 	    (_("%B: unable to fill in DataDictionary[1] because .idata$2 is missing"),
4367*a9fa9459Szrj 	     abfd);
4368*a9fa9459Szrj 	  result = FALSE;
4369*a9fa9459Szrj 	}
4370*a9fa9459Szrj 
4371*a9fa9459Szrj       h1 = coff_link_hash_lookup (coff_hash_table (info),
4372*a9fa9459Szrj 				  ".idata$4", FALSE, FALSE, TRUE);
4373*a9fa9459Szrj       if (h1 != NULL
4374*a9fa9459Szrj 	  && (h1->root.type == bfd_link_hash_defined
4375*a9fa9459Szrj 	   || h1->root.type == bfd_link_hash_defweak)
4376*a9fa9459Szrj 	  && h1->root.u.def.section != NULL
4377*a9fa9459Szrj 	  && h1->root.u.def.section->output_section != NULL)
4378*a9fa9459Szrj 	pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].Size =
4379*a9fa9459Szrj 	  ((h1->root.u.def.value
4380*a9fa9459Szrj 	    + h1->root.u.def.section->output_section->vma
4381*a9fa9459Szrj 	    + h1->root.u.def.section->output_offset)
4382*a9fa9459Szrj 	   - pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress);
4383*a9fa9459Szrj       else
4384*a9fa9459Szrj 	{
4385*a9fa9459Szrj 	  _bfd_error_handler
4386*a9fa9459Szrj 	    (_("%B: unable to fill in DataDictionary[1] because .idata$4 is missing"),
4387*a9fa9459Szrj 	     abfd);
4388*a9fa9459Szrj 	  result = FALSE;
4389*a9fa9459Szrj 	}
4390*a9fa9459Szrj 
4391*a9fa9459Szrj       /* The import address table.  This is the size/address of
4392*a9fa9459Szrj          .idata$5.  */
4393*a9fa9459Szrj       h1 = coff_link_hash_lookup (coff_hash_table (info),
4394*a9fa9459Szrj 				  ".idata$5", FALSE, FALSE, TRUE);
4395*a9fa9459Szrj       if (h1 != NULL
4396*a9fa9459Szrj 	  && (h1->root.type == bfd_link_hash_defined
4397*a9fa9459Szrj 	   || h1->root.type == bfd_link_hash_defweak)
4398*a9fa9459Szrj 	  && h1->root.u.def.section != NULL
4399*a9fa9459Szrj 	  && h1->root.u.def.section->output_section != NULL)
4400*a9fa9459Szrj 	pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress =
4401*a9fa9459Szrj 	  (h1->root.u.def.value
4402*a9fa9459Szrj 	   + h1->root.u.def.section->output_section->vma
4403*a9fa9459Szrj 	   + h1->root.u.def.section->output_offset);
4404*a9fa9459Szrj       else
4405*a9fa9459Szrj 	{
4406*a9fa9459Szrj 	  _bfd_error_handler
4407*a9fa9459Szrj 	    (_("%B: unable to fill in DataDictionary[12] because .idata$5 is missing"),
4408*a9fa9459Szrj 	     abfd);
4409*a9fa9459Szrj 	  result = FALSE;
4410*a9fa9459Szrj 	}
4411*a9fa9459Szrj 
4412*a9fa9459Szrj       h1 = coff_link_hash_lookup (coff_hash_table (info),
4413*a9fa9459Szrj 				  ".idata$6", FALSE, FALSE, TRUE);
4414*a9fa9459Szrj       if (h1 != NULL
4415*a9fa9459Szrj 	  && (h1->root.type == bfd_link_hash_defined
4416*a9fa9459Szrj 	   || h1->root.type == bfd_link_hash_defweak)
4417*a9fa9459Szrj 	  && h1->root.u.def.section != NULL
4418*a9fa9459Szrj 	  && h1->root.u.def.section->output_section != NULL)
4419*a9fa9459Szrj 	pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size =
4420*a9fa9459Szrj 	  ((h1->root.u.def.value
4421*a9fa9459Szrj 	    + h1->root.u.def.section->output_section->vma
4422*a9fa9459Szrj 	    + h1->root.u.def.section->output_offset)
4423*a9fa9459Szrj 	   - pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress);
4424*a9fa9459Szrj       else
4425*a9fa9459Szrj 	{
4426*a9fa9459Szrj 	  _bfd_error_handler
4427*a9fa9459Szrj 	    (_("%B: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE (12)] because .idata$6 is missing"),
4428*a9fa9459Szrj 	     abfd);
4429*a9fa9459Szrj 	  result = FALSE;
4430*a9fa9459Szrj 	}
4431*a9fa9459Szrj     }
4432*a9fa9459Szrj   else
4433*a9fa9459Szrj     {
4434*a9fa9459Szrj       h1 = coff_link_hash_lookup (coff_hash_table (info),
4435*a9fa9459Szrj 				  "__IAT_start__", FALSE, FALSE, TRUE);
4436*a9fa9459Szrj       if (h1 != NULL
4437*a9fa9459Szrj 	  && (h1->root.type == bfd_link_hash_defined
4438*a9fa9459Szrj 	   || h1->root.type == bfd_link_hash_defweak)
4439*a9fa9459Szrj 	  && h1->root.u.def.section != NULL
4440*a9fa9459Szrj 	  && h1->root.u.def.section->output_section != NULL)
4441*a9fa9459Szrj 	{
4442*a9fa9459Szrj 	  bfd_vma iat_va;
4443*a9fa9459Szrj 
4444*a9fa9459Szrj 	  iat_va =
4445*a9fa9459Szrj 	    (h1->root.u.def.value
4446*a9fa9459Szrj 	     + h1->root.u.def.section->output_section->vma
4447*a9fa9459Szrj 	     + h1->root.u.def.section->output_offset);
4448*a9fa9459Szrj 
4449*a9fa9459Szrj 	  h1 = coff_link_hash_lookup (coff_hash_table (info),
4450*a9fa9459Szrj 				      "__IAT_end__", FALSE, FALSE, TRUE);
4451*a9fa9459Szrj 	  if (h1 != NULL
4452*a9fa9459Szrj 	      && (h1->root.type == bfd_link_hash_defined
4453*a9fa9459Szrj 	       || h1->root.type == bfd_link_hash_defweak)
4454*a9fa9459Szrj 	      && h1->root.u.def.section != NULL
4455*a9fa9459Szrj 	      && h1->root.u.def.section->output_section != NULL)
4456*a9fa9459Szrj 	    {
4457*a9fa9459Szrj 	      pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size =
4458*a9fa9459Szrj 		((h1->root.u.def.value
4459*a9fa9459Szrj 		  + h1->root.u.def.section->output_section->vma
4460*a9fa9459Szrj 		  + h1->root.u.def.section->output_offset)
4461*a9fa9459Szrj 		 - iat_va);
4462*a9fa9459Szrj 	      if (pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size != 0)
4463*a9fa9459Szrj 		pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress =
4464*a9fa9459Szrj 		  iat_va - pe_data (abfd)->pe_opthdr.ImageBase;
4465*a9fa9459Szrj 	    }
4466*a9fa9459Szrj 	  else
4467*a9fa9459Szrj 	    {
4468*a9fa9459Szrj 	      _bfd_error_handler
4469*a9fa9459Szrj 		(_("%B: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE(12)]"
4470*a9fa9459Szrj 		   " because .idata$6 is missing"), abfd);
4471*a9fa9459Szrj 	      result = FALSE;
4472*a9fa9459Szrj 	    }
4473*a9fa9459Szrj         }
4474*a9fa9459Szrj     }
4475*a9fa9459Szrj 
4476*a9fa9459Szrj   h1 = coff_link_hash_lookup (coff_hash_table (info),
4477*a9fa9459Szrj 			      (bfd_get_symbol_leading_char (abfd) != 0
4478*a9fa9459Szrj 			       ? "__tls_used" : "_tls_used"),
4479*a9fa9459Szrj 			      FALSE, FALSE, TRUE);
4480*a9fa9459Szrj   if (h1 != NULL)
4481*a9fa9459Szrj     {
4482*a9fa9459Szrj       if ((h1->root.type == bfd_link_hash_defined
4483*a9fa9459Szrj 	   || h1->root.type == bfd_link_hash_defweak)
4484*a9fa9459Szrj 	  && h1->root.u.def.section != NULL
4485*a9fa9459Szrj 	  && h1->root.u.def.section->output_section != NULL)
4486*a9fa9459Szrj 	pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].VirtualAddress =
4487*a9fa9459Szrj 	  (h1->root.u.def.value
4488*a9fa9459Szrj 	   + h1->root.u.def.section->output_section->vma
4489*a9fa9459Szrj 	   + h1->root.u.def.section->output_offset
4490*a9fa9459Szrj 	   - pe_data (abfd)->pe_opthdr.ImageBase);
4491*a9fa9459Szrj       else
4492*a9fa9459Szrj 	{
4493*a9fa9459Szrj 	  _bfd_error_handler
4494*a9fa9459Szrj 	    (_("%B: unable to fill in DataDictionary[9] because __tls_used is missing"),
4495*a9fa9459Szrj 	     abfd);
4496*a9fa9459Szrj 	  result = FALSE;
4497*a9fa9459Szrj 	}
4498*a9fa9459Szrj      /* According to PECOFF sepcifications by Microsoft version 8.2
4499*a9fa9459Szrj 	the TLS data directory consists of 4 pointers, followed
4500*a9fa9459Szrj 	by two 4-byte integer. This implies that the total size
4501*a9fa9459Szrj 	is different for 32-bit and 64-bit executables.  */
4502*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
4503*a9fa9459Szrj       pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x18;
4504*a9fa9459Szrj #else
4505*a9fa9459Szrj       pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x28;
4506*a9fa9459Szrj #endif
4507*a9fa9459Szrj     }
4508*a9fa9459Szrj 
4509*a9fa9459Szrj /* If there is a .pdata section and we have linked pdata finally, we
4510*a9fa9459Szrj      need to sort the entries ascending.  */
4511*a9fa9459Szrj #if !defined(COFF_WITH_pep) && defined(COFF_WITH_pex64)
4512*a9fa9459Szrj   {
4513*a9fa9459Szrj     asection *sec = bfd_get_section_by_name (abfd, ".pdata");
4514*a9fa9459Szrj 
4515*a9fa9459Szrj     if (sec)
4516*a9fa9459Szrj       {
4517*a9fa9459Szrj 	bfd_size_type x = sec->rawsize;
4518*a9fa9459Szrj 	bfd_byte *tmp_data = NULL;
4519*a9fa9459Szrj 
4520*a9fa9459Szrj 	if (x)
4521*a9fa9459Szrj 	  tmp_data = bfd_malloc (x);
4522*a9fa9459Szrj 
4523*a9fa9459Szrj 	if (tmp_data != NULL)
4524*a9fa9459Szrj 	  {
4525*a9fa9459Szrj 	    if (bfd_get_section_contents (abfd, sec, tmp_data, 0, x))
4526*a9fa9459Szrj 	      {
4527*a9fa9459Szrj 		qsort (tmp_data,
4528*a9fa9459Szrj 		       (size_t) (x / 12),
4529*a9fa9459Szrj 		       12, sort_x64_pdata);
4530*a9fa9459Szrj 		bfd_set_section_contents (pfinfo->output_bfd, sec,
4531*a9fa9459Szrj 					  tmp_data, 0, x);
4532*a9fa9459Szrj 	      }
4533*a9fa9459Szrj 	    free (tmp_data);
4534*a9fa9459Szrj 	  }
4535*a9fa9459Szrj 	else
4536*a9fa9459Szrj 	  result = FALSE;
4537*a9fa9459Szrj       }
4538*a9fa9459Szrj   }
4539*a9fa9459Szrj #endif
4540*a9fa9459Szrj 
4541*a9fa9459Szrj   rsrc_process_section (abfd, pfinfo);
4542*a9fa9459Szrj 
4543*a9fa9459Szrj   /* If we couldn't find idata$2, we either have an excessively
4544*a9fa9459Szrj      trivial program or are in DEEP trouble; we have to assume trivial
4545*a9fa9459Szrj      program....  */
4546*a9fa9459Szrj   return result;
4547*a9fa9459Szrj }
4548