]>
Commit | Line | Data |
---|---|---|
277d1b5e | 1 | /* Support for the generic parts of PE/PEI, for BFD. |
368d0860 | 2 | Copyright 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. |
277d1b5e | 3 | Written by Cygnus Solutions. |
252b5132 RH |
4 | |
5 | This file is part of BFD, the Binary File Descriptor library. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | /* | |
22 | Most of this hacked by Steve Chamberlain, | |
23 | [email protected] | |
277d1b5e ILT |
24 | |
25 | PE/PEI rearrangement (and code added): Donn Terry | |
26 | Softway Systems, Inc. | |
252b5132 RH |
27 | */ |
28 | ||
29 | /* Hey look, some documentation [and in a place you expect to find it]! | |
30 | ||
31 | The main reference for the pei format is "Microsoft Portable Executable | |
32 | and Common Object File Format Specification 4.1". Get it if you need to | |
33 | do some serious hacking on this code. | |
34 | ||
35 | Another reference: | |
36 | "Peering Inside the PE: A Tour of the Win32 Portable Executable | |
37 | File Format", MSJ 1994, Volume 9. | |
38 | ||
39 | The *sole* difference between the pe format and the pei format is that the | |
40 | latter has an MSDOS 2.0 .exe header on the front that prints the message | |
41 | "This app must be run under Windows." (or some such). | |
42 | (FIXME: Whether that statement is *really* true or not is unknown. | |
43 | Are there more subtle differences between pe and pei formats? | |
44 | For now assume there aren't. If you find one, then for God sakes | |
45 | document it here!) | |
46 | ||
47 | The Microsoft docs use the word "image" instead of "executable" because | |
48 | the former can also refer to a DLL (shared library). Confusion can arise | |
49 | because the `i' in `pei' also refers to "image". The `pe' format can | |
50 | also create images (i.e. executables), it's just that to run on a win32 | |
51 | system you need to use the pei format. | |
52 | ||
53 | FIXME: Please add more docs here so the next poor fool that has to hack | |
54 | on this code has a chance of getting something accomplished without | |
55 | wasting too much time. | |
56 | */ | |
57 | ||
277d1b5e ILT |
58 | #include "libpei.h" |
59 | ||
252b5132 | 60 | static boolean (*pe_saved_coff_bfd_print_private_bfd_data) |
277d1b5e ILT |
61 | PARAMS ((bfd *, PTR)) = |
62 | #ifndef coff_bfd_print_private_bfd_data | |
63 | NULL; | |
252b5132 | 64 | #else |
277d1b5e ILT |
65 | coff_bfd_print_private_bfd_data; |
66 | #undef coff_bfd_print_private_bfd_data | |
252b5132 RH |
67 | #endif |
68 | ||
277d1b5e ILT |
69 | static boolean pe_print_private_bfd_data PARAMS ((bfd *, PTR)); |
70 | #define coff_bfd_print_private_bfd_data pe_print_private_bfd_data | |
252b5132 | 71 | |
252b5132 | 72 | |
277d1b5e ILT |
73 | static boolean (*pe_saved_coff_bfd_copy_private_bfd_data) |
74 | PARAMS ((bfd *, bfd *)) = | |
75 | #ifndef coff_bfd_copy_private_bfd_data | |
76 | NULL; | |
77 | #else | |
78 | coff_bfd_copy_private_bfd_data; | |
79 | #undef coff_bfd_copy_private_bfd_data | |
252b5132 RH |
80 | #endif |
81 | ||
277d1b5e ILT |
82 | static boolean pe_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *)); |
83 | #define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data | |
252b5132 | 84 | |
277d1b5e ILT |
85 | #define coff_mkobject pe_mkobject |
86 | #define coff_mkobject_hook pe_mkobject_hook | |
252b5132 RH |
87 | |
88 | static void coff_swap_reloc_in PARAMS ((bfd *, PTR, PTR)); | |
89 | static unsigned int coff_swap_reloc_out PARAMS ((bfd *, PTR, PTR)); | |
90 | static void coff_swap_filehdr_in PARAMS ((bfd *, PTR, PTR)); | |
252b5132 | 91 | static void coff_swap_scnhdr_in PARAMS ((bfd *, PTR, PTR)); |
252b5132 RH |
92 | static boolean pe_mkobject PARAMS ((bfd *)); |
93 | static PTR pe_mkobject_hook PARAMS ((bfd *, PTR, PTR)); | |
252b5132 RH |
94 | |
95 | /**********************************************************************/ | |
96 | ||
97 | static void | |
98 | coff_swap_reloc_in (abfd, src, dst) | |
99 | bfd *abfd; | |
100 | PTR src; | |
101 | PTR dst; | |
102 | { | |
103 | RELOC *reloc_src = (RELOC *) src; | |
104 | struct internal_reloc *reloc_dst = (struct internal_reloc *) dst; | |
105 | ||
106 | reloc_dst->r_vaddr = bfd_h_get_32(abfd, (bfd_byte *)reloc_src->r_vaddr); | |
107 | reloc_dst->r_symndx = bfd_h_get_signed_32(abfd, (bfd_byte *) reloc_src->r_symndx); | |
108 | ||
109 | reloc_dst->r_type = bfd_h_get_16(abfd, (bfd_byte *) reloc_src->r_type); | |
110 | ||
111 | #ifdef SWAP_IN_RELOC_OFFSET | |
112 | reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET(abfd, | |
113 | (bfd_byte *) reloc_src->r_offset); | |
114 | #endif | |
115 | } | |
116 | ||
117 | ||
118 | static unsigned int | |
119 | coff_swap_reloc_out (abfd, src, dst) | |
120 | bfd *abfd; | |
121 | PTR src; | |
122 | PTR dst; | |
123 | { | |
124 | struct internal_reloc *reloc_src = (struct internal_reloc *)src; | |
125 | struct external_reloc *reloc_dst = (struct external_reloc *)dst; | |
126 | bfd_h_put_32(abfd, reloc_src->r_vaddr, (bfd_byte *) reloc_dst->r_vaddr); | |
127 | bfd_h_put_32(abfd, reloc_src->r_symndx, (bfd_byte *) reloc_dst->r_symndx); | |
128 | ||
129 | bfd_h_put_16(abfd, reloc_src->r_type, (bfd_byte *) | |
130 | reloc_dst->r_type); | |
131 | ||
132 | #ifdef SWAP_OUT_RELOC_OFFSET | |
133 | SWAP_OUT_RELOC_OFFSET(abfd, | |
134 | reloc_src->r_offset, | |
135 | (bfd_byte *) reloc_dst->r_offset); | |
136 | #endif | |
137 | #ifdef SWAP_OUT_RELOC_EXTRA | |
138 | SWAP_OUT_RELOC_EXTRA(abfd,reloc_src, reloc_dst); | |
139 | #endif | |
140 | return RELSZ; | |
141 | } | |
142 | ||
143 | ||
144 | static void | |
145 | coff_swap_filehdr_in (abfd, src, dst) | |
146 | bfd *abfd; | |
147 | PTR src; | |
148 | PTR dst; | |
149 | { | |
150 | FILHDR *filehdr_src = (FILHDR *) src; | |
151 | struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst; | |
152 | filehdr_dst->f_magic = bfd_h_get_16(abfd, (bfd_byte *) filehdr_src->f_magic); | |
153 | filehdr_dst->f_nscns = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_nscns); | |
154 | filehdr_dst->f_timdat = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_timdat); | |
155 | ||
156 | filehdr_dst->f_nsyms = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_nsyms); | |
157 | filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags); | |
158 | filehdr_dst->f_symptr = bfd_h_get_32 (abfd, (bfd_byte *) filehdr_src->f_symptr); | |
159 | ||
05bf877a ILT |
160 | #ifdef COFF_IMAGE_WITH_PE |
161 | /* There are really two magic numbers involved; the magic number | |
162 | that says this is a NT executable (PEI) and the magic number that | |
163 | determines the architecture. The former is DOSMAGIC, stored in | |
164 | the e_magic field. The latter is stored in the f_magic field. | |
165 | If the NT magic number isn't valid, the architecture magic number | |
166 | could be mimicked by some other field (specifically, the number | |
167 | of relocs in section 3). Since this routine can only be called | |
168 | correctly for a PEI file, check the e_magic number here, and, if | |
169 | it doesn't match, clobber the f_magic number so that we don't get | |
170 | a false match. */ | |
171 | if (bfd_h_get_16 (abfd, (bfd_byte *) filehdr_src->e_magic) != DOSMAGIC) | |
172 | filehdr_dst->f_magic = -1; | |
173 | #endif | |
174 | ||
252b5132 RH |
175 | /* Other people's tools sometimes generate headers with an nsyms but |
176 | a zero symptr. */ | |
177 | if (filehdr_dst->f_nsyms != 0 && filehdr_dst->f_symptr == 0) | |
178 | { | |
179 | filehdr_dst->f_nsyms = 0; | |
180 | filehdr_dst->f_flags |= F_LSYMS; | |
181 | } | |
182 | ||
183 | filehdr_dst->f_opthdr = bfd_h_get_16(abfd, | |
184 | (bfd_byte *)filehdr_src-> f_opthdr); | |
185 | } | |
186 | ||
187 | #ifdef COFF_IMAGE_WITH_PE | |
277d1b5e | 188 | #define coff_swap_filehdr_out _bfd_pei_only_swap_filehdr_out |
252b5132 | 189 | #else |
277d1b5e | 190 | #define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out |
252b5132 | 191 | #endif |
252b5132 | 192 | |
252b5132 RH |
193 | |
194 | static void | |
e166a60f ILT |
195 | coff_swap_scnhdr_in (abfd, ext, in) |
196 | bfd *abfd; | |
197 | PTR ext; | |
198 | PTR in; | |
252b5132 RH |
199 | { |
200 | SCNHDR *scnhdr_ext = (SCNHDR *) ext; | |
201 | struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in; | |
202 | ||
203 | memcpy(scnhdr_int->s_name, scnhdr_ext->s_name, sizeof(scnhdr_int->s_name)); | |
204 | scnhdr_int->s_vaddr = | |
205 | GET_SCNHDR_VADDR (abfd, (bfd_byte *) scnhdr_ext->s_vaddr); | |
206 | scnhdr_int->s_paddr = | |
207 | GET_SCNHDR_PADDR (abfd, (bfd_byte *) scnhdr_ext->s_paddr); | |
208 | scnhdr_int->s_size = | |
209 | GET_SCNHDR_SIZE (abfd, (bfd_byte *) scnhdr_ext->s_size); | |
210 | scnhdr_int->s_scnptr = | |
211 | GET_SCNHDR_SCNPTR (abfd, (bfd_byte *) scnhdr_ext->s_scnptr); | |
212 | scnhdr_int->s_relptr = | |
213 | GET_SCNHDR_RELPTR (abfd, (bfd_byte *) scnhdr_ext->s_relptr); | |
214 | scnhdr_int->s_lnnoptr = | |
215 | GET_SCNHDR_LNNOPTR (abfd, (bfd_byte *) scnhdr_ext->s_lnnoptr); | |
216 | scnhdr_int->s_flags = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_flags); | |
217 | ||
cb43721d ILT |
218 | /* MS handles overflow of line numbers by carrying into the reloc |
219 | field (it appears). Since it's supposed to be zero for PE | |
220 | *IMAGE* format, that's safe. This is still a bit iffy. */ | |
221 | #ifdef COFF_IMAGE_WITH_PE | |
222 | scnhdr_int->s_nlnno = | |
223 | (bfd_h_get_16 (abfd, (bfd_byte *) scnhdr_ext->s_nlnno) | |
224 | + (bfd_h_get_16 (abfd, (bfd_byte *) scnhdr_ext->s_nreloc) << 16)); | |
225 | scnhdr_int->s_nreloc = 0; | |
226 | #else | |
227 | scnhdr_int->s_nreloc = bfd_h_get_16 (abfd, | |
228 | (bfd_byte *) scnhdr_ext->s_nreloc); | |
229 | scnhdr_int->s_nlnno = bfd_h_get_16 (abfd, | |
230 | (bfd_byte *) scnhdr_ext->s_nlnno); | |
231 | #endif | |
252b5132 RH |
232 | |
233 | if (scnhdr_int->s_vaddr != 0) | |
234 | { | |
235 | scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase; | |
236 | scnhdr_int->s_vaddr &= 0xffffffff; | |
237 | } | |
e166a60f ILT |
238 | |
239 | /* If this section holds uninitialized data, use the virtual size | |
240 | (stored in s_paddr) instead of the physical size. */ | |
241 | if ((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0) | |
252b5132 RH |
242 | { |
243 | scnhdr_int->s_size = scnhdr_int->s_paddr; | |
e166a60f ILT |
244 | /* This code used to set scnhdr_int->s_paddr to 0. However, |
245 | coff_set_alignment_hook stores s_paddr in virt_size, which | |
246 | only works if it correctly holds the virtual size of the | |
247 | section. */ | |
252b5132 RH |
248 | } |
249 | } | |
250 | ||
252b5132 RH |
251 | static boolean |
252 | pe_mkobject (abfd) | |
253 | bfd * abfd; | |
254 | { | |
255 | pe_data_type *pe; | |
256 | abfd->tdata.pe_obj_data = | |
257 | (struct pe_tdata *) bfd_zalloc (abfd, sizeof (pe_data_type)); | |
258 | ||
259 | if (abfd->tdata.pe_obj_data == 0) | |
260 | return false; | |
261 | ||
262 | pe = pe_data (abfd); | |
263 | ||
264 | pe->coff.pe = 1; | |
277d1b5e ILT |
265 | |
266 | /* in_reloc_p is architecture dependent. */ | |
252b5132 RH |
267 | pe->in_reloc_p = in_reloc_p; |
268 | return true; | |
269 | } | |
270 | ||
271 | /* Create the COFF backend specific information. */ | |
272 | static PTR | |
273 | pe_mkobject_hook (abfd, filehdr, aouthdr) | |
274 | bfd * abfd; | |
275 | PTR filehdr; | |
5f771d47 | 276 | PTR aouthdr ATTRIBUTE_UNUSED; |
252b5132 RH |
277 | { |
278 | struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; | |
279 | pe_data_type *pe; | |
280 | ||
281 | if (pe_mkobject (abfd) == false) | |
282 | return NULL; | |
283 | ||
284 | pe = pe_data (abfd); | |
285 | pe->coff.sym_filepos = internal_f->f_symptr; | |
286 | /* These members communicate important constants about the symbol | |
287 | table to GDB's symbol-reading code. These `constants' | |
288 | unfortunately vary among coff implementations... */ | |
289 | pe->coff.local_n_btmask = N_BTMASK; | |
290 | pe->coff.local_n_btshft = N_BTSHFT; | |
291 | pe->coff.local_n_tmask = N_TMASK; | |
292 | pe->coff.local_n_tshift = N_TSHIFT; | |
293 | pe->coff.local_symesz = SYMESZ; | |
294 | pe->coff.local_auxesz = AUXESZ; | |
295 | pe->coff.local_linesz = LINESZ; | |
296 | ||
1135238b ILT |
297 | pe->coff.timestamp = internal_f->f_timdat; |
298 | ||
252b5132 RH |
299 | obj_raw_syment_count (abfd) = |
300 | obj_conv_table_size (abfd) = | |
301 | internal_f->f_nsyms; | |
302 | ||
303 | pe->real_flags = internal_f->f_flags; | |
304 | ||
305 | if ((internal_f->f_flags & F_DLL) != 0) | |
306 | pe->dll = 1; | |
307 | ||
4cfec37b ILT |
308 | if ((internal_f->f_flags & IMAGE_FILE_DEBUG_STRIPPED) == 0) |
309 | abfd->flags |= HAS_DEBUG; | |
310 | ||
252b5132 RH |
311 | #ifdef COFF_IMAGE_WITH_PE |
312 | if (aouthdr) | |
313 | pe->pe_opthdr = ((struct internal_aouthdr *)aouthdr)->pe; | |
314 | #endif | |
315 | ||
316 | #ifdef ARM | |
317 | if (! _bfd_coff_arm_set_private_flags (abfd, internal_f->f_flags)) | |
318 | coff_data (abfd) ->flags = 0; | |
319 | #endif | |
320 | ||
321 | return (PTR) pe; | |
322 | } | |
323 | ||
277d1b5e ILT |
324 | static boolean |
325 | pe_print_private_bfd_data (abfd, vfile) | |
326 | bfd *abfd; | |
327 | PTR vfile; | |
328 | { | |
329 | FILE *file = (FILE *) vfile; | |
330 | ||
331 | if (!_bfd_pe_print_private_bfd_data_common (abfd, vfile)) | |
332 | return false; | |
252b5132 | 333 | |
277d1b5e ILT |
334 | if (pe_saved_coff_bfd_print_private_bfd_data != NULL) |
335 | { | |
336 | fputc ('\n', file); | |
337 | ||
338 | return pe_saved_coff_bfd_print_private_bfd_data (abfd, vfile); | |
339 | } | |
340 | ||
341 | return true; | |
342 | } | |
252b5132 RH |
343 | |
344 | /* Copy any private info we understand from the input bfd | |
345 | to the output bfd. */ | |
346 | ||
252b5132 RH |
347 | static boolean |
348 | pe_bfd_copy_private_bfd_data (ibfd, obfd) | |
349 | bfd *ibfd, *obfd; | |
350 | { | |
277d1b5e ILT |
351 | if (!_bfd_pe_bfd_copy_private_bfd_data_common (ibfd, obfd)) |
352 | return false; | |
252b5132 RH |
353 | |
354 | if (pe_saved_coff_bfd_copy_private_bfd_data) | |
355 | return pe_saved_coff_bfd_copy_private_bfd_data (ibfd, obfd); | |
252b5132 RH |
356 | |
357 | return true; | |
358 | } | |
359 | ||
277d1b5e ILT |
360 | #define coff_bfd_copy_private_section_data \ |
361 | _bfd_pe_bfd_copy_private_section_data | |
7d2b58d6 ILT |
362 | |
363 | #define coff_get_symbol_info _bfd_pe_get_symbol_info | |
cb665cd3 NC |
364 | |
365 | static const bfd_target * | |
366 | pe_bfd_object_p (abfd) | |
367 | bfd * abfd; | |
368 | { | |
369 | /* We need to handle a PE image correctly. In PE images created by | |
370 | the GNU linker, the offset to the COFF header is always the size. | |
371 | However, this is not the case in images generated by other PE | |
372 | linkers. The PE format stores a four byte offset to the PE | |
373 | signature just before the COFF header at location 0x3c of the file. | |
374 | We pick up that offset, verify that the PE signature is there, and | |
375 | then set ourselves up to read in the COFF header. */ | |
376 | bfd_byte buffer[4]; | |
377 | file_ptr offset; | |
378 | unsigned long signature; | |
379 | ||
380 | /* Detect if this a Microsoft Import Library Format element. */ | |
381 | if (bfd_seek (abfd, 0x00, SEEK_SET) != 0 | |
382 | || bfd_read (buffer, 1, 4, abfd) != 4) | |
383 | { | |
384 | if (bfd_get_error () != bfd_error_system_call) | |
385 | bfd_set_error (bfd_error_wrong_format); | |
386 | return NULL; | |
387 | } | |
388 | ||
389 | signature = bfd_h_get_32 (abfd, buffer); | |
390 | ||
391 | if (signature == 0xffff0000) | |
392 | { | |
393 | _bfd_error_handler (_("%s: Import Library Format archives are not currently supported"), | |
394 | bfd_get_filename (abfd)); | |
395 | bfd_set_error (bfd_error_wrong_format); | |
396 | ||
397 | return NULL; | |
398 | } | |
399 | ||
400 | if (bfd_seek (abfd, 0x3c, SEEK_SET) != 0 | |
401 | || bfd_read (buffer, 1, 4, abfd) != 4) | |
402 | { | |
403 | if (bfd_get_error () != bfd_error_system_call) | |
404 | bfd_set_error (bfd_error_wrong_format); | |
405 | return NULL; | |
406 | } | |
407 | ||
408 | offset = bfd_h_get_32 (abfd, buffer); | |
409 | ||
410 | if (bfd_seek (abfd, offset, SEEK_SET) != 0 | |
411 | || bfd_read (buffer, 1, 4, abfd) != 4) | |
412 | { | |
413 | if (bfd_get_error () != bfd_error_system_call) | |
414 | bfd_set_error (bfd_error_wrong_format); | |
415 | return NULL; | |
416 | } | |
417 | ||
418 | signature = bfd_h_get_32 (abfd, buffer); | |
419 | ||
420 | if (signature != 0x4550) | |
421 | { | |
422 | bfd_set_error (bfd_error_wrong_format); | |
423 | return NULL; | |
424 | } | |
425 | ||
426 | /* Here is the hack. coff_object_p wants to read filhsz bytes to | |
427 | pick up the COFF header. We adjust so that that will work. 20 | |
428 | is the size of the i386 COFF filehdr. */ | |
429 | if (bfd_seek (abfd, | |
430 | (bfd_tell (abfd) | |
431 | - bfd_coff_filhsz (abfd) | |
432 | + 20), | |
433 | SEEK_SET) | |
434 | != 0) | |
435 | { | |
436 | if (bfd_get_error () != bfd_error_system_call) | |
437 | bfd_set_error (bfd_error_wrong_format); | |
438 | return NULL; | |
439 | } | |
440 | ||
441 | return coff_object_p (abfd); | |
442 | } | |
443 | ||
444 | #define coff_object_p pe_bfd_object_p |