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