Fixes for .reloc
[external/binutils.git] / bfd / peicode.h
1 /* Support for the generic parts of most COFF variants, for BFD.
2    Copyright 1995 Free Software Foundation, Inc.
3    Written by Cygnus Support.
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                         sac@cygnus.com
24 */
25
26
27
28 #define coff_bfd_print_private_bfd_data pe_print_private_bfd_data
29 #define coff_mkobject pe_mkobject
30 #define coff_mkobject_hook pe_mkobject_hook
31
32 #ifndef GET_FCN_LNNOPTR
33 #define GET_FCN_LNNOPTR(abfd, ext) \
34      bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
35 #endif
36
37 #ifndef GET_FCN_ENDNDX
38 #define GET_FCN_ENDNDX(abfd, ext)  \
39         bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
40 #endif
41
42 #ifndef PUT_FCN_LNNOPTR
43 #define PUT_FCN_LNNOPTR(abfd, in, ext)  bfd_h_put_32(abfd,  in, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
44 #endif
45 #ifndef PUT_FCN_ENDNDX
46 #define PUT_FCN_ENDNDX(abfd, in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
47 #endif
48 #ifndef GET_LNSZ_LNNO
49 #define GET_LNSZ_LNNO(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_lnno)
50 #endif
51 #ifndef GET_LNSZ_SIZE
52 #define GET_LNSZ_SIZE(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_size)
53 #endif
54 #ifndef PUT_LNSZ_LNNO
55 #define PUT_LNSZ_LNNO(abfd, in, ext) bfd_h_put_16(abfd, in, (bfd_byte *)ext->x_sym.x_misc.x_lnsz.x_lnno)
56 #endif
57 #ifndef PUT_LNSZ_SIZE
58 #define PUT_LNSZ_SIZE(abfd, in, ext) bfd_h_put_16(abfd, in, (bfd_byte*) ext->x_sym.x_misc.x_lnsz.x_size)
59 #endif
60 #ifndef GET_SCN_SCNLEN
61 #define GET_SCN_SCNLEN(abfd,  ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_scn.x_scnlen)
62 #endif
63 #ifndef GET_SCN_NRELOC
64 #define GET_SCN_NRELOC(abfd,  ext) bfd_h_get_16(abfd, (bfd_byte *)ext->x_scn.x_nreloc)
65 #endif
66 #ifndef GET_SCN_NLINNO
67 #define GET_SCN_NLINNO(abfd, ext)  bfd_h_get_16(abfd, (bfd_byte *)ext->x_scn.x_nlinno)
68 #endif
69 #ifndef PUT_SCN_SCNLEN
70 #define PUT_SCN_SCNLEN(abfd,in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_scn.x_scnlen)
71 #endif
72 #ifndef PUT_SCN_NRELOC
73 #define PUT_SCN_NRELOC(abfd,in, ext) bfd_h_put_16(abfd, in, (bfd_byte *)ext->x_scn.x_nreloc)
74 #endif
75 #ifndef PUT_SCN_NLINNO
76 #define PUT_SCN_NLINNO(abfd,in, ext)  bfd_h_put_16(abfd,in, (bfd_byte  *) ext->x_scn.x_nlinno)
77 #endif
78 #ifndef GET_LINENO_LNNO
79 #define GET_LINENO_LNNO(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) (ext->l_lnno));
80 #endif
81 #ifndef PUT_LINENO_LNNO
82 #define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_16(abfd,val,  (bfd_byte *) (ext->l_lnno));
83 #endif
84
85 /* The f_symptr field in the filehdr is sometimes 64 bits.  */
86 #ifndef GET_FILEHDR_SYMPTR
87 #define GET_FILEHDR_SYMPTR bfd_h_get_32
88 #endif
89 #ifndef PUT_FILEHDR_SYMPTR
90 #define PUT_FILEHDR_SYMPTR bfd_h_put_32
91 #endif
92
93 /* Some fields in the aouthdr are sometimes 64 bits.  */
94 #ifndef GET_AOUTHDR_TSIZE
95 #define GET_AOUTHDR_TSIZE bfd_h_get_32
96 #endif
97 #ifndef PUT_AOUTHDR_TSIZE
98 #define PUT_AOUTHDR_TSIZE bfd_h_put_32
99 #endif
100 #ifndef GET_AOUTHDR_DSIZE
101 #define GET_AOUTHDR_DSIZE bfd_h_get_32
102 #endif
103 #ifndef PUT_AOUTHDR_DSIZE
104 #define PUT_AOUTHDR_DSIZE bfd_h_put_32
105 #endif
106 #ifndef GET_AOUTHDR_BSIZE
107 #define GET_AOUTHDR_BSIZE bfd_h_get_32
108 #endif
109 #ifndef PUT_AOUTHDR_BSIZE
110 #define PUT_AOUTHDR_BSIZE bfd_h_put_32
111 #endif
112 #ifndef GET_AOUTHDR_ENTRY
113 #define GET_AOUTHDR_ENTRY bfd_h_get_32
114 #endif
115 #ifndef PUT_AOUTHDR_ENTRY
116 #define PUT_AOUTHDR_ENTRY bfd_h_put_32
117 #endif
118 #ifndef GET_AOUTHDR_TEXT_START
119 #define GET_AOUTHDR_TEXT_START bfd_h_get_32
120 #endif
121 #ifndef PUT_AOUTHDR_TEXT_START
122 #define PUT_AOUTHDR_TEXT_START bfd_h_put_32
123 #endif
124 #ifndef GET_AOUTHDR_DATA_START
125 #define GET_AOUTHDR_DATA_START bfd_h_get_32
126 #endif
127 #ifndef PUT_AOUTHDR_DATA_START
128 #define PUT_AOUTHDR_DATA_START bfd_h_put_32
129 #endif
130
131 /* Some fields in the scnhdr are sometimes 64 bits.  */
132 #ifndef GET_SCNHDR_PADDR
133 #define GET_SCNHDR_PADDR bfd_h_get_32
134 #endif
135 #ifndef PUT_SCNHDR_PADDR
136 #define PUT_SCNHDR_PADDR bfd_h_put_32
137 #endif
138 #ifndef GET_SCNHDR_VADDR
139 #define GET_SCNHDR_VADDR bfd_h_get_32
140 #endif
141 #ifndef PUT_SCNHDR_VADDR
142 #define PUT_SCNHDR_VADDR bfd_h_put_32
143 #endif
144 #ifndef GET_SCNHDR_SIZE
145 #define GET_SCNHDR_SIZE bfd_h_get_32
146 #endif
147 #ifndef PUT_SCNHDR_SIZE
148 #define PUT_SCNHDR_SIZE bfd_h_put_32
149 #endif
150 #ifndef GET_SCNHDR_SCNPTR
151 #define GET_SCNHDR_SCNPTR bfd_h_get_32
152 #endif
153 #ifndef PUT_SCNHDR_SCNPTR
154 #define PUT_SCNHDR_SCNPTR bfd_h_put_32
155 #endif
156 #ifndef GET_SCNHDR_RELPTR
157 #define GET_SCNHDR_RELPTR bfd_h_get_32
158 #endif
159 #ifndef PUT_SCNHDR_RELPTR
160 #define PUT_SCNHDR_RELPTR bfd_h_put_32
161 #endif
162 #ifndef GET_SCNHDR_LNNOPTR
163 #define GET_SCNHDR_LNNOPTR bfd_h_get_32
164 #endif
165 #ifndef PUT_SCNHDR_LNNOPTR
166 #define PUT_SCNHDR_LNNOPTR bfd_h_put_32
167 #endif
168
169
170
171 /**********************************************************************/
172
173 static void
174 coff_swap_reloc_in (abfd, src, dst)
175      bfd *abfd;
176      PTR src;
177      PTR dst;
178 {
179   RELOC *reloc_src = (RELOC *) src;
180   struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
181
182   reloc_dst->r_vaddr = bfd_h_get_32(abfd, (bfd_byte *)reloc_src->r_vaddr);
183   reloc_dst->r_symndx = bfd_h_get_signed_32(abfd, (bfd_byte *) reloc_src->r_symndx);
184
185   reloc_dst->r_type = bfd_h_get_16(abfd, (bfd_byte *) reloc_src->r_type);
186
187 #ifdef SWAP_IN_RELOC_OFFSET
188   reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET(abfd,
189                                              (bfd_byte *) reloc_src->r_offset);
190 #endif
191 }
192
193
194 static unsigned int
195 coff_swap_reloc_out (abfd, src, dst)
196      bfd       *abfd;
197      PTR        src;
198      PTR        dst;
199 {
200   struct internal_reloc *reloc_src = (struct internal_reloc *)src;
201   struct external_reloc *reloc_dst = (struct external_reloc *)dst;
202   bfd_h_put_32(abfd, reloc_src->r_vaddr, (bfd_byte *) reloc_dst->r_vaddr);
203   bfd_h_put_32(abfd, reloc_src->r_symndx, (bfd_byte *) reloc_dst->r_symndx);
204
205   bfd_h_put_16(abfd, reloc_src->r_type, (bfd_byte *)
206                reloc_dst->r_type);
207
208 #ifdef SWAP_OUT_RELOC_OFFSET
209   SWAP_OUT_RELOC_OFFSET(abfd,
210                         reloc_src->r_offset,
211                         (bfd_byte *) reloc_dst->r_offset);
212 #endif
213 #ifdef SWAP_OUT_RELOC_EXTRA
214   SWAP_OUT_RELOC_EXTRA(abfd,reloc_src, reloc_dst);
215 #endif
216   return sizeof(struct external_reloc);
217 }
218
219
220 static void
221 coff_swap_filehdr_in (abfd, src, dst)
222      bfd            *abfd;
223      PTR             src;
224      PTR             dst;
225 {
226   FILHDR *filehdr_src = (FILHDR *) src;
227   struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
228   filehdr_dst->f_magic = bfd_h_get_16(abfd, (bfd_byte *) filehdr_src->f_magic);
229   filehdr_dst->f_nscns = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_nscns);
230   filehdr_dst->f_timdat = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_timdat);
231
232   filehdr_dst->f_nsyms = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_nsyms);
233   filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags);
234   filehdr_dst->f_symptr = bfd_h_get_32 (abfd, (bfd_byte *) filehdr_src->f_symptr);
235
236   /* Other people's tools sometimes generate headers
237      with an nsyms but a zero symptr. */
238   if (filehdr_dst->f_nsyms && filehdr_dst->f_symptr)
239     {
240       filehdr_dst->f_flags |= HAS_SYMS;
241     }
242   else 
243     {
244       filehdr_dst->f_symptr = 0;
245       filehdr_dst->f_nsyms = 0;
246       filehdr_dst->f_flags &= ~HAS_SYMS;
247     }
248
249   filehdr_dst->f_opthdr = bfd_h_get_16(abfd, 
250                                        (bfd_byte *)filehdr_src-> f_opthdr);
251 }
252
253 #ifdef COFF_IMAGE_WITH_PE
254
255 static  unsigned int
256 coff_swap_filehdr_out (abfd, in, out)
257      bfd       *abfd;
258      PTR        in;
259      PTR        out;
260 {
261   int idx;
262   struct internal_filehdr *filehdr_in = (struct internal_filehdr *)in;
263   FILHDR *filehdr_out = (FILHDR *)out;
264
265   if (pe_data (abfd)->has_reloc_section)
266     filehdr_in->f_flags &= ~F_RELFLG;
267
268   if (pe_data (abfd)->dll)
269     filehdr_in->f_flags |= F_DLL;
270
271   filehdr_in->pe.e_magic    = DOSMAGIC;
272   filehdr_in->pe.e_cblp     = 0x90;
273   filehdr_in->pe.e_cp       = 0x3;
274   filehdr_in->pe.e_crlc     = 0x0;
275   filehdr_in->pe.e_cparhdr  = 0x4;
276   filehdr_in->pe.e_minalloc = 0x0;
277   filehdr_in->pe.e_maxalloc = 0xffff;
278   filehdr_in->pe.e_ss       = 0x0;
279   filehdr_in->pe.e_sp       = 0xb8;
280   filehdr_in->pe.e_csum     = 0x0;
281   filehdr_in->pe.e_ip       = 0x0;
282   filehdr_in->pe.e_cs       = 0x0;
283   filehdr_in->pe.e_lfarlc   = 0x40;
284   filehdr_in->pe.e_ovno     = 0x0;
285
286   for (idx=0; idx < 4; idx++)
287     filehdr_in->pe.e_res[idx] = 0x0;
288
289   filehdr_in->pe.e_oemid   = 0x0;
290   filehdr_in->pe.e_oeminfo = 0x0;
291
292   for (idx=0; idx < 10; idx++)
293     filehdr_in->pe.e_res2[idx] = 0x0;
294
295   filehdr_in->pe.e_lfanew = 0x80;
296
297   /* this next collection of data are mostly just characters.  It appears
298      to be constant within the headers put on NT exes */
299   filehdr_in->pe.dos_message[0]  = 0x0eba1f0e;
300   filehdr_in->pe.dos_message[1]  = 0xcd09b400;
301   filehdr_in->pe.dos_message[2]  = 0x4c01b821;
302   filehdr_in->pe.dos_message[3]  = 0x685421cd;
303   filehdr_in->pe.dos_message[4]  = 0x70207369;
304   filehdr_in->pe.dos_message[5]  = 0x72676f72;
305   filehdr_in->pe.dos_message[6]  = 0x63206d61;
306   filehdr_in->pe.dos_message[7]  = 0x6f6e6e61;
307   filehdr_in->pe.dos_message[8]  = 0x65622074;
308   filehdr_in->pe.dos_message[9]  = 0x6e757220;
309   filehdr_in->pe.dos_message[10] = 0x206e6920;
310   filehdr_in->pe.dos_message[11] = 0x20534f44;
311   filehdr_in->pe.dos_message[12] = 0x65646f6d;
312   filehdr_in->pe.dos_message[13] = 0x0a0d0d2e;
313   filehdr_in->pe.dos_message[14] = 0x24;
314   filehdr_in->pe.dos_message[15] = 0x0;
315   filehdr_in->pe.nt_signature = NT_SIGNATURE;
316
317
318
319   bfd_h_put_16(abfd, filehdr_in->f_magic, (bfd_byte *) filehdr_out->f_magic);
320   bfd_h_put_16(abfd, filehdr_in->f_nscns, (bfd_byte *) filehdr_out->f_nscns);
321
322   bfd_h_put_32(abfd, time (0), (bfd_byte *) filehdr_out->f_timdat);
323   PUT_FILEHDR_SYMPTR (abfd, (bfd_vma) filehdr_in->f_symptr,
324                       (bfd_byte *) filehdr_out->f_symptr);
325   bfd_h_put_32(abfd, filehdr_in->f_nsyms, (bfd_byte *) filehdr_out->f_nsyms);
326   bfd_h_put_16(abfd, filehdr_in->f_opthdr, (bfd_byte *) filehdr_out->f_opthdr);
327   bfd_h_put_16(abfd, filehdr_in->f_flags, (bfd_byte *) filehdr_out->f_flags);
328
329   /* put in extra dos header stuff.  This data remains essentially
330      constant, it just has to be tacked on to the beginning of all exes 
331      for NT */
332   bfd_h_put_16(abfd, filehdr_in->pe.e_magic, (bfd_byte *) filehdr_out->e_magic);
333   bfd_h_put_16(abfd, filehdr_in->pe.e_cblp, (bfd_byte *) filehdr_out->e_cblp);
334   bfd_h_put_16(abfd, filehdr_in->pe.e_cp, (bfd_byte *) filehdr_out->e_cp);
335   bfd_h_put_16(abfd, filehdr_in->pe.e_crlc, (bfd_byte *) filehdr_out->e_crlc);
336   bfd_h_put_16(abfd, filehdr_in->pe.e_cparhdr, 
337                (bfd_byte *) filehdr_out->e_cparhdr);
338   bfd_h_put_16(abfd, filehdr_in->pe.e_minalloc, 
339                (bfd_byte *) filehdr_out->e_minalloc);
340   bfd_h_put_16(abfd, filehdr_in->pe.e_maxalloc, 
341                (bfd_byte *) filehdr_out->e_maxalloc);
342   bfd_h_put_16(abfd, filehdr_in->pe.e_ss, (bfd_byte *) filehdr_out->e_ss);
343   bfd_h_put_16(abfd, filehdr_in->pe.e_sp, (bfd_byte *) filehdr_out->e_sp);
344   bfd_h_put_16(abfd, filehdr_in->pe.e_csum, (bfd_byte *) filehdr_out->e_csum);
345   bfd_h_put_16(abfd, filehdr_in->pe.e_ip, (bfd_byte *) filehdr_out->e_ip);
346   bfd_h_put_16(abfd, filehdr_in->pe.e_cs, (bfd_byte *) filehdr_out->e_cs);
347   bfd_h_put_16(abfd, filehdr_in->pe.e_lfarlc, (bfd_byte *) filehdr_out->e_lfarlc);
348   bfd_h_put_16(abfd, filehdr_in->pe.e_ovno, (bfd_byte *) filehdr_out->e_ovno);
349   {
350     int idx;
351     for (idx=0; idx < 4; idx++)
352       bfd_h_put_16(abfd, filehdr_in->pe.e_res[idx], 
353                    (bfd_byte *) filehdr_out->e_res[idx]);
354   }
355   bfd_h_put_16(abfd, filehdr_in->pe.e_oemid, (bfd_byte *) filehdr_out->e_oemid);
356   bfd_h_put_16(abfd, filehdr_in->pe.e_oeminfo,
357                (bfd_byte *) filehdr_out->e_oeminfo);
358   {
359     int idx;
360     for (idx=0; idx < 10; idx++)
361       bfd_h_put_16(abfd, filehdr_in->pe.e_res2[idx],
362                    (bfd_byte *) filehdr_out->e_res2[idx]);
363   }
364   bfd_h_put_32(abfd, filehdr_in->pe.e_lfanew, (bfd_byte *) filehdr_out->e_lfanew);
365
366   {
367     int idx;
368     for (idx=0; idx < 16; idx++)
369       bfd_h_put_32(abfd, filehdr_in->pe.dos_message[idx],
370                    (bfd_byte *) filehdr_out->dos_message[idx]);
371   }
372
373   /* also put in the NT signature */
374   bfd_h_put_32(abfd, filehdr_in->pe.nt_signature, 
375                (bfd_byte *) filehdr_out->nt_signature);
376
377
378
379
380   return sizeof(FILHDR);
381 }
382 #else
383
384 static  unsigned int
385 coff_swap_filehdr_out (abfd, in, out)
386      bfd       *abfd;
387      PTR        in;
388      PTR        out;
389 {
390   struct internal_filehdr *filehdr_in = (struct internal_filehdr *)in;
391   FILHDR *filehdr_out = (FILHDR *)out;
392
393   bfd_h_put_16(abfd, filehdr_in->f_magic, (bfd_byte *) filehdr_out->f_magic);
394   bfd_h_put_16(abfd, filehdr_in->f_nscns, (bfd_byte *) filehdr_out->f_nscns);
395   bfd_h_put_32(abfd, filehdr_in->f_timdat, (bfd_byte *) filehdr_out->f_timdat);
396   PUT_FILEHDR_SYMPTR (abfd, (bfd_vma) filehdr_in->f_symptr,
397                       (bfd_byte *) filehdr_out->f_symptr);
398   bfd_h_put_32(abfd, filehdr_in->f_nsyms, (bfd_byte *) filehdr_out->f_nsyms);
399   bfd_h_put_16(abfd, filehdr_in->f_opthdr, (bfd_byte *) filehdr_out->f_opthdr);
400   bfd_h_put_16(abfd, filehdr_in->f_flags, (bfd_byte *) filehdr_out->f_flags);
401
402   return sizeof(FILHDR);
403 }
404
405 #endif
406
407
408 static void
409 coff_swap_sym_in (abfd, ext1, in1)
410      bfd            *abfd;
411      PTR ext1;
412      PTR in1;
413 {
414   SYMENT *ext = (SYMENT *)ext1;
415   struct internal_syment      *in = (struct internal_syment *)in1;
416
417   if( ext->e.e_name[0] == 0) {
418     in->_n._n_n._n_zeroes = 0;
419     in->_n._n_n._n_offset = bfd_h_get_32(abfd, (bfd_byte *) ext->e.e.e_offset);
420   }
421   else {
422 #if SYMNMLEN != E_SYMNMLEN
423     -> Error, we need to cope with truncating or extending SYMNMLEN!;
424 #else
425     memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN);
426 #endif
427   }
428
429   in->n_value = bfd_h_get_32(abfd, (bfd_byte *) ext->e_value); 
430   in->n_scnum = bfd_h_get_16(abfd, (bfd_byte *) ext->e_scnum);
431   if (sizeof(ext->e_type) == 2){
432     in->n_type = bfd_h_get_16(abfd, (bfd_byte *) ext->e_type);
433   }
434   else {
435     in->n_type = bfd_h_get_32(abfd, (bfd_byte *) ext->e_type);
436   }
437   in->n_sclass = bfd_h_get_8(abfd, ext->e_sclass);
438   in->n_numaux = bfd_h_get_8(abfd, ext->e_numaux);
439
440   /* The section symbols for the .idata$ sections have class 68, which MS
441      documentation indicates is a section symbol.  The problem is that the
442      value field in the symbol is simply a copy of the .idata section's flags
443      rather than something useful.  When these symbols are encountered, change
444      the value to 0 and the section number to 1 so that they will be handled
445      somewhat correctly in the bfd code. */
446   if (in->n_sclass == 0x68) {
447     in->n_value = 0x0;
448     in->n_scnum = 1;
449     /* I have tried setting the class to 3 and using the following to set
450        the section number.  This will put the address of the pointer to the
451        string kernel32.dll at addresses 0 and 0x10 off start of idata section
452        which is not correct */
453     /*    if (strcmp (in->_n._n_name, ".idata$4") == 0) */
454     /*      in->n_scnum = 3; */
455     /*    else */
456     /*      in->n_scnum = 2; */
457   }
458
459 #ifdef coff_swap_sym_in_hook
460   coff_swap_sym_in_hook(abfd, ext1, in1);
461 #endif
462 }
463
464 static unsigned int
465 coff_swap_sym_out (abfd, inp, extp)
466      bfd       *abfd;
467      PTR        inp;
468      PTR        extp;
469 {
470   struct internal_syment *in = (struct internal_syment *)inp;
471   SYMENT *ext =(SYMENT *)extp;
472   if(in->_n._n_name[0] == 0) {
473     bfd_h_put_32(abfd, 0, (bfd_byte *) ext->e.e.e_zeroes);
474     bfd_h_put_32(abfd, in->_n._n_n._n_offset, (bfd_byte *)  ext->e.e.e_offset);
475   }
476   else {
477 #if SYMNMLEN != E_SYMNMLEN
478     -> Error, we need to cope with truncating or extending SYMNMLEN!;
479 #else
480     memcpy(ext->e.e_name, in->_n._n_name, SYMNMLEN);
481 #endif
482   }
483
484   bfd_h_put_32(abfd,  in->n_value , (bfd_byte *) ext->e_value);
485   bfd_h_put_16(abfd,  in->n_scnum , (bfd_byte *) ext->e_scnum);
486   if (sizeof(ext->e_type) == 2)
487     {
488       bfd_h_put_16(abfd,  in->n_type , (bfd_byte *) ext->e_type);
489     }
490   else
491     {
492       bfd_h_put_32(abfd,  in->n_type , (bfd_byte *) ext->e_type);
493     }
494   bfd_h_put_8(abfd,  in->n_sclass , ext->e_sclass);
495   bfd_h_put_8(abfd,  in->n_numaux , ext->e_numaux);
496
497   return sizeof(SYMENT);
498 }
499
500 static void
501 coff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
502      bfd            *abfd;
503      PTR              ext1;
504      int             type;
505      int             class;
506      int              indx;
507      int              numaux;
508      PTR              in1;
509 {
510   AUXENT    *ext = (AUXENT *)ext1;
511   union internal_auxent *in = (union internal_auxent *)in1;
512
513   switch (class) {
514   case C_FILE:
515     if (ext->x_file.x_fname[0] == 0) {
516       in->x_file.x_n.x_zeroes = 0;
517       in->x_file.x_n.x_offset = 
518         bfd_h_get_32(abfd, (bfd_byte *) ext->x_file.x_n.x_offset);
519     } else {
520 #if FILNMLEN != E_FILNMLEN
521       -> Error, we need to cope with truncating or extending FILNMLEN!;
522 #else
523       memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
524 #endif
525     }
526     return;
527
528
529   case C_STAT:
530 #ifdef C_LEAFSTAT
531   case C_LEAFSTAT:
532 #endif
533   case C_HIDDEN:
534     if (type == T_NULL) {
535       in->x_scn.x_scnlen = GET_SCN_SCNLEN(abfd, ext);
536       in->x_scn.x_nreloc = GET_SCN_NRELOC(abfd, ext);
537       in->x_scn.x_nlinno = GET_SCN_NLINNO(abfd, ext);
538       return;
539     }
540     break;
541   }
542
543   in->x_sym.x_tagndx.l = bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_tagndx);
544 #ifndef NO_TVNDX
545   in->x_sym.x_tvndx = bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_tvndx);
546 #endif
547
548   if (class == C_BLOCK || ISFCN (type) || ISTAG (class))
549     {
550       in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext);
551       in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext);
552     }
553   else
554     {
555 #if DIMNUM != E_DIMNUM
556  #error we need to cope with truncating or extending DIMNUM
557 #endif
558       in->x_sym.x_fcnary.x_ary.x_dimen[0] =
559         bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
560       in->x_sym.x_fcnary.x_ary.x_dimen[1] =
561         bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
562       in->x_sym.x_fcnary.x_ary.x_dimen[2] =
563         bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
564       in->x_sym.x_fcnary.x_ary.x_dimen[3] =
565         bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
566     }
567
568   if (ISFCN(type)) {
569     in->x_sym.x_misc.x_fsize = bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_misc.x_fsize);
570   }
571   else {
572     in->x_sym.x_misc.x_lnsz.x_lnno = GET_LNSZ_LNNO(abfd, ext);
573     in->x_sym.x_misc.x_lnsz.x_size = GET_LNSZ_SIZE(abfd, ext);
574   }
575 }
576
577 static unsigned int
578 coff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
579      bfd   *abfd;
580      PTR        inp;
581      int   type;
582      int   class;
583      int   indx;
584      int   numaux;
585      PTR        extp;
586 {
587   union internal_auxent *in = (union internal_auxent *)inp;
588   AUXENT *ext = (AUXENT *)extp;
589
590   memset((PTR)ext, 0, AUXESZ);
591   switch (class) {
592   case C_FILE:
593     if (in->x_file.x_fname[0] == 0) {
594       bfd_h_put_32(abfd, 0, (bfd_byte *) ext->x_file.x_n.x_zeroes);
595       bfd_h_put_32(abfd,
596               in->x_file.x_n.x_offset,
597               (bfd_byte *) ext->x_file.x_n.x_offset);
598     }
599     else {
600 #if FILNMLEN != E_FILNMLEN
601       -> Error, we need to cope with truncating or extending FILNMLEN!;
602 #else
603       memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
604 #endif
605     }
606     return sizeof (AUXENT);
607
608
609   case C_STAT:
610 #ifdef C_LEAFSTAT
611   case C_LEAFSTAT:
612 #endif
613   case C_HIDDEN:
614     if (type == T_NULL) {
615       PUT_SCN_SCNLEN(abfd, in->x_scn.x_scnlen, ext);
616       PUT_SCN_NRELOC(abfd, in->x_scn.x_nreloc, ext);
617       PUT_SCN_NLINNO(abfd, in->x_scn.x_nlinno, ext);
618       return sizeof (AUXENT);
619     }
620     break;
621   }
622
623   bfd_h_put_32(abfd, in->x_sym.x_tagndx.l, (bfd_byte *) ext->x_sym.x_tagndx);
624 #ifndef NO_TVNDX
625   bfd_h_put_16(abfd, in->x_sym.x_tvndx , (bfd_byte *) ext->x_sym.x_tvndx);
626 #endif
627
628   if (class == C_BLOCK || ISFCN (type) || ISTAG (class))
629     {
630       PUT_FCN_LNNOPTR(abfd,  in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext);
631       PUT_FCN_ENDNDX(abfd,  in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext);
632     }
633   else
634     {
635 #if DIMNUM != E_DIMNUM
636  #error we need to cope with truncating or extending DIMNUM
637 #endif
638       bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],
639                     (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
640       bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],
641                     (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
642       bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],
643                     (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
644       bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],
645                     (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
646     }
647
648   if (ISFCN (type))
649     bfd_h_put_32 (abfd, in->x_sym.x_misc.x_fsize,
650              (bfd_byte *)  ext->x_sym.x_misc.x_fsize);
651   else
652     {
653       PUT_LNSZ_LNNO (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext);
654       PUT_LNSZ_SIZE (abfd, in->x_sym.x_misc.x_lnsz.x_size, ext);
655     }
656
657   return sizeof(AUXENT);
658 }
659
660
661 static void
662 coff_swap_lineno_in (abfd, ext1, in1)
663      bfd            *abfd;
664      PTR ext1;
665      PTR in1;
666 {
667   LINENO *ext = (LINENO *)ext1;
668   struct internal_lineno      *in = (struct internal_lineno *)in1;
669
670   in->l_addr.l_symndx = bfd_h_get_32(abfd, (bfd_byte *) ext->l_addr.l_symndx);
671   in->l_lnno = GET_LINENO_LNNO(abfd, ext);
672 }
673
674 static unsigned int
675 coff_swap_lineno_out (abfd, inp, outp)
676      bfd       *abfd;
677      PTR        inp;
678      PTR        outp;
679 {
680   struct internal_lineno *in = (struct internal_lineno *)inp;
681   struct external_lineno *ext = (struct external_lineno *)outp;
682   bfd_h_put_32(abfd, in->l_addr.l_symndx, (bfd_byte *)
683           ext->l_addr.l_symndx);
684
685   PUT_LINENO_LNNO (abfd, in->l_lnno, ext);
686   return sizeof(struct external_lineno);
687 }
688
689
690
691 static void
692 coff_swap_aouthdr_in (abfd, aouthdr_ext1, aouthdr_int1)
693      bfd            *abfd;
694      PTR aouthdr_ext1;
695      PTR aouthdr_int1;
696 {
697   struct internal_extra_pe_aouthdr *a;
698   PEAOUTHDR *src = (PEAOUTHDR *)(aouthdr_ext1);
699   AOUTHDR        *aouthdr_ext = (AOUTHDR *) aouthdr_ext1;
700   struct internal_aouthdr *aouthdr_int = (struct internal_aouthdr *)aouthdr_int1;
701
702   aouthdr_int->magic = bfd_h_get_16(abfd, (bfd_byte *) aouthdr_ext->magic);
703   aouthdr_int->vstamp = bfd_h_get_16(abfd, (bfd_byte *) aouthdr_ext->vstamp);
704   aouthdr_int->tsize =
705     GET_AOUTHDR_TSIZE (abfd, (bfd_byte *) aouthdr_ext->tsize);
706   aouthdr_int->dsize =
707     GET_AOUTHDR_DSIZE (abfd, (bfd_byte *) aouthdr_ext->dsize);
708   aouthdr_int->bsize =
709     GET_AOUTHDR_BSIZE (abfd, (bfd_byte *) aouthdr_ext->bsize);
710   aouthdr_int->entry =
711     GET_AOUTHDR_ENTRY (abfd, (bfd_byte *) aouthdr_ext->entry);
712   aouthdr_int->text_start =
713     GET_AOUTHDR_TEXT_START (abfd, (bfd_byte *) aouthdr_ext->text_start);
714   aouthdr_int->data_start =
715     GET_AOUTHDR_DATA_START (abfd, (bfd_byte *) aouthdr_ext->data_start);
716
717   a = &aouthdr_int->pe;
718   a->ImageBase = bfd_h_get_32 (abfd, src->ImageBase);
719   a->SectionAlignment = bfd_h_get_32 (abfd, src->SectionAlignment);
720   a->FileAlignment = bfd_h_get_32 (abfd, src->FileAlignment);
721   a->MajorOperatingSystemVersion = 
722     bfd_h_get_16 (abfd, src->MajorOperatingSystemVersion);
723   a->MinorOperatingSystemVersion = 
724     bfd_h_get_16 (abfd, src->MinorOperatingSystemVersion);
725   a->MajorImageVersion = bfd_h_get_16 (abfd, src->MajorImageVersion);
726   a->MinorImageVersion = bfd_h_get_16 (abfd, src->MinorImageVersion);
727   a->MajorSubsystemVersion = bfd_h_get_16 (abfd, src->MajorSubsystemVersion);
728   a->MinorSubsystemVersion = bfd_h_get_16 (abfd, src->MinorSubsystemVersion);
729   a->Reserved1 = bfd_h_get_32 (abfd, src->Reserved1);
730   a->SizeOfImage = bfd_h_get_32 (abfd, src->SizeOfImage);
731   a->SizeOfHeaders = bfd_h_get_32 (abfd, src->SizeOfHeaders);
732   a->CheckSum = bfd_h_get_32 (abfd, src->CheckSum);
733   a->Subsystem = bfd_h_get_16 (abfd, src->Subsystem);
734   a->DllCharacteristics = bfd_h_get_16 (abfd, src->DllCharacteristics);
735   a->SizeOfStackReserve = bfd_h_get_32 (abfd, src->SizeOfStackReserve);
736   a->SizeOfStackCommit = bfd_h_get_32 (abfd, src->SizeOfStackCommit);
737   a->SizeOfHeapReserve = bfd_h_get_32 (abfd, src->SizeOfHeapReserve);
738   a->SizeOfHeapCommit = bfd_h_get_32 (abfd, src->SizeOfHeapCommit);
739   a->LoaderFlags = bfd_h_get_32 (abfd, src->LoaderFlags);
740   a->NumberOfRvaAndSizes = bfd_h_get_32 (abfd, src->NumberOfRvaAndSizes);
741
742   {
743     int idx;
744     for (idx=0; idx < 16; idx++)
745       {
746         a->DataDirectory[idx].VirtualAddress =
747           bfd_h_get_32 (abfd, src->DataDirectory[idx][0]);
748         a->DataDirectory[idx].Size =
749           bfd_h_get_32 (abfd, src->DataDirectory[idx][1]);
750       }
751   }
752
753   if (aouthdr_int->entry)
754     aouthdr_int->entry += a->ImageBase;
755   if (aouthdr_int->tsize) 
756     aouthdr_int->text_start += a->ImageBase;
757   if (aouthdr_int->dsize) 
758     aouthdr_int->data_start += a->ImageBase;
759 }
760
761
762 static void add_data_entry (abfd, aout, idx, name, base)
763      bfd *abfd;
764      struct internal_extra_pe_aouthdr *aout;
765      int idx;
766      char *name;
767      bfd_vma base;
768 {
769   asection *sec = bfd_get_section_by_name (abfd, name);
770
771   /* add import directory information if it exists */
772   if (sec != NULL)
773     {
774       aout->DataDirectory[idx].VirtualAddress = sec->lma - base;
775       aout->DataDirectory[idx].Size = sec->_cooked_size;
776       sec->flags |= SEC_DATA;
777     }
778 }
779
780 static unsigned int
781 coff_swap_aouthdr_out (abfd, in, out)
782      bfd       *abfd;
783      PTR        in;
784      PTR        out;
785 {
786   struct internal_aouthdr *aouthdr_in = (struct internal_aouthdr *)in;
787   struct internal_extra_pe_aouthdr *extra = &pe_data (abfd)->pe_opthdr;
788   PEAOUTHDR *aouthdr_out = (PEAOUTHDR *)out;
789
790   bfd_vma sa = extra->SectionAlignment;
791   bfd_vma fa = extra->FileAlignment;
792   bfd_vma ib = extra->ImageBase ;
793
794   if (aouthdr_in->tsize) 
795     aouthdr_in->text_start -= ib;
796   if (aouthdr_in->dsize) 
797     aouthdr_in->data_start -= ib;
798   if (aouthdr_in->entry) 
799     aouthdr_in->entry -= ib;
800
801 #define FA(x)  (((x) + fa -1 ) & (- fa))
802 #define SA(x)  (((x) + sa -1 ) & (- sa))
803
804   /* We like to have the sizes aligned */
805
806   aouthdr_in->bsize = FA (aouthdr_in->bsize);
807
808
809   extra->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
810
811   /* first null out all data directory entries .. */
812   memset (extra->DataDirectory, sizeof (extra->DataDirectory), 0);
813
814   add_data_entry (abfd, extra, 0, ".edata", ib);
815   add_data_entry (abfd, extra, 1, ".idata", ib);
816   add_data_entry (abfd, extra, 2, ".rsrc" ,ib);
817
818 #ifdef POWERPC_LE_PE
819   /* FIXME: do other PE platforms use this? */
820   add_data_entry (abfd, extra, 3, ".pdata" ,ib);
821 #endif
822
823   add_data_entry (abfd, extra, 5, ".reloc", ib);
824
825 #ifdef POWERPC_LE_PE
826   /* On the PPC NT system, this field is set up as follows. It is
827      not an "officially" reserved field, so it currently has no title.
828      first_thunk_address is idata$5, and the thunk_size is the size
829      of the idata$5 chunk of the idata section.
830   */
831   extra->DataDirectory[12].VirtualAddress = first_thunk_address;
832   extra->DataDirectory[12].Size = thunk_size;
833
834   /* On the PPC NT system, the size of the directory entry is not the
835      size of the entire section. It's actually offset to the end of 
836      the idata$3 component of the idata section. This is the size of
837      the entire import table. (also known as the start of idata$4)
838   */
839   extra->DataDirectory[1].Size = import_table_size;
840 #endif
841
842   {
843     asection *sec;
844     bfd_vma dsize= 0;
845     bfd_vma isize = SA(abfd->sections->filepos);
846     bfd_vma tsize= 0;
847 #ifdef PPC
848     isize = 0;
849 #endif
850     for (sec = abfd->sections; sec; sec = sec->next)
851       {
852         int rounded = FA(sec->_raw_size);
853         if (sec->flags & SEC_DATA) 
854           dsize += rounded;
855         if (sec->flags & SEC_CODE)
856           tsize += rounded;
857         isize += SA(rounded);
858       }
859
860     aouthdr_in->dsize = dsize;
861     aouthdr_in->tsize = tsize;
862     extra->SizeOfImage = isize;
863   }
864
865   extra->SizeOfHeaders = abfd->sections->filepos;
866   bfd_h_put_16(abfd, aouthdr_in->magic, (bfd_byte *) aouthdr_out->standard.magic);
867
868 #ifdef POWERPC_LE_PE
869   /* this little piece of magic sets the "linker version" field to 2.60 */
870   bfd_h_put_16(abfd, 2  + 60 * 256, (bfd_byte *) aouthdr_out->standard.vstamp);
871 #else
872   /* this little piece of magic sets the "linker version" field to 2.55 */
873   bfd_h_put_16(abfd, 2  + 55 * 256, (bfd_byte *) aouthdr_out->standard.vstamp);
874 #endif
875
876   PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, (bfd_byte *) aouthdr_out->standard.tsize);
877   PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, (bfd_byte *) aouthdr_out->standard.dsize);
878   PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, (bfd_byte *) aouthdr_out->standard.bsize);
879   PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, (bfd_byte *) aouthdr_out->standard.entry);
880   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
881                           (bfd_byte *) aouthdr_out->standard.text_start);
882
883   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
884                           (bfd_byte *) aouthdr_out->standard.data_start);
885
886
887   bfd_h_put_32 (abfd, extra->ImageBase, 
888                 (bfd_byte *) aouthdr_out->ImageBase);
889   bfd_h_put_32 (abfd, extra->SectionAlignment,
890                 (bfd_byte *) aouthdr_out->SectionAlignment);
891   bfd_h_put_32 (abfd, extra->FileAlignment,
892                 (bfd_byte *) aouthdr_out->FileAlignment);
893   bfd_h_put_16 (abfd, extra->MajorOperatingSystemVersion,
894                 (bfd_byte *) aouthdr_out->MajorOperatingSystemVersion);
895   bfd_h_put_16 (abfd, extra->MinorOperatingSystemVersion,
896                 (bfd_byte *) aouthdr_out->MinorOperatingSystemVersion);
897   bfd_h_put_16 (abfd, extra->MajorImageVersion,
898                 (bfd_byte *) aouthdr_out->MajorImageVersion);
899   bfd_h_put_16 (abfd, extra->MinorImageVersion,
900                 (bfd_byte *) aouthdr_out->MinorImageVersion);
901   bfd_h_put_16 (abfd, extra->MajorSubsystemVersion,
902                 (bfd_byte *) aouthdr_out->MajorSubsystemVersion);
903   bfd_h_put_16 (abfd, extra->MinorSubsystemVersion,
904                 (bfd_byte *) aouthdr_out->MinorSubsystemVersion);
905   bfd_h_put_32 (abfd, extra->Reserved1,
906                 (bfd_byte *) aouthdr_out->Reserved1);
907   bfd_h_put_32 (abfd, extra->SizeOfImage,
908                 (bfd_byte *) aouthdr_out->SizeOfImage);
909   bfd_h_put_32 (abfd, extra->SizeOfHeaders,
910                 (bfd_byte *) aouthdr_out->SizeOfHeaders);
911   bfd_h_put_32 (abfd, extra->CheckSum,
912                 (bfd_byte *) aouthdr_out->CheckSum);
913   bfd_h_put_16 (abfd, extra->Subsystem,
914                 (bfd_byte *) aouthdr_out->Subsystem);
915   bfd_h_put_16 (abfd, extra->DllCharacteristics,
916                 (bfd_byte *) aouthdr_out->DllCharacteristics);
917   bfd_h_put_32 (abfd, extra->SizeOfStackReserve,
918                 (bfd_byte *) aouthdr_out->SizeOfStackReserve);
919   bfd_h_put_32 (abfd, extra->SizeOfStackCommit,
920                 (bfd_byte *) aouthdr_out->SizeOfStackCommit);
921   bfd_h_put_32 (abfd, extra->SizeOfHeapReserve,
922                 (bfd_byte *) aouthdr_out->SizeOfHeapReserve);
923   bfd_h_put_32 (abfd, extra->SizeOfHeapCommit,
924                 (bfd_byte *) aouthdr_out->SizeOfHeapCommit);
925   bfd_h_put_32 (abfd, extra->LoaderFlags,
926                 (bfd_byte *) aouthdr_out->LoaderFlags);
927   bfd_h_put_32 (abfd, extra->NumberOfRvaAndSizes,
928                 (bfd_byte *) aouthdr_out->NumberOfRvaAndSizes);
929   {
930     int idx;
931     for (idx=0; idx < 16; idx++)
932       {
933         bfd_h_put_32 (abfd, extra->DataDirectory[idx].VirtualAddress,
934                       (bfd_byte *) aouthdr_out->DataDirectory[idx][0]);
935         bfd_h_put_32 (abfd, extra->DataDirectory[idx].Size,
936                       (bfd_byte *) aouthdr_out->DataDirectory[idx][1]);
937       }
938   }
939
940   return sizeof(AOUTHDR);
941 }
942
943 static void
944     coff_swap_scnhdr_in (abfd, ext, in)
945       bfd            *abfd;
946   PTR        ext;
947   PTR        in;
948 {
949   SCNHDR *scnhdr_ext = (SCNHDR *) ext;
950   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
951
952   memcpy(scnhdr_int->s_name, scnhdr_ext->s_name, sizeof(scnhdr_int->s_name));
953   scnhdr_int->s_vaddr =
954     GET_SCNHDR_VADDR (abfd, (bfd_byte *) scnhdr_ext->s_vaddr);
955   scnhdr_int->s_paddr =
956     GET_SCNHDR_PADDR (abfd, (bfd_byte *) scnhdr_ext->s_paddr);
957   scnhdr_int->s_size =
958     GET_SCNHDR_SIZE (abfd, (bfd_byte *) scnhdr_ext->s_size);
959   scnhdr_int->s_scnptr =
960     GET_SCNHDR_SCNPTR (abfd, (bfd_byte *) scnhdr_ext->s_scnptr);
961   scnhdr_int->s_relptr =
962     GET_SCNHDR_RELPTR (abfd, (bfd_byte *) scnhdr_ext->s_relptr);
963   scnhdr_int->s_lnnoptr =
964     GET_SCNHDR_LNNOPTR (abfd, (bfd_byte *) scnhdr_ext->s_lnnoptr);
965   scnhdr_int->s_flags = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_flags);
966
967   scnhdr_int->s_nreloc = bfd_h_get_16(abfd, (bfd_byte *) scnhdr_ext->s_nreloc);
968   scnhdr_int->s_nlnno = bfd_h_get_16(abfd, (bfd_byte *) scnhdr_ext->s_nlnno);
969
970   if (scnhdr_int->s_vaddr != 0) 
971     {
972       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
973     }
974   if (strcmp (scnhdr_int->s_name, _BSS) == 0) 
975     {
976       scnhdr_int->s_size = scnhdr_int->s_paddr;
977       scnhdr_int->s_paddr = 0;
978     }
979 }
980
981 static unsigned int
982 coff_swap_scnhdr_out (abfd, in, out)
983      bfd       *abfd;
984      PTR        in;
985      PTR        out;
986 {
987   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *)in;
988   SCNHDR *scnhdr_ext = (SCNHDR *)out;
989   unsigned int ret = sizeof (SCNHDR);
990   bfd_vma ps;
991   bfd_vma ss;
992
993   memcpy(scnhdr_ext->s_name, scnhdr_int->s_name, sizeof(scnhdr_int->s_name));
994
995   PUT_SCNHDR_VADDR (abfd, 
996                     (scnhdr_int->s_vaddr 
997                      - pe_data(abfd)->pe_opthdr.ImageBase),
998                     (bfd_byte *) scnhdr_ext->s_vaddr);
999
1000   /* NT wants the size data to be rounded up to the next NT_FILE_ALIGNMENT
1001      value except for the BSS section, its s_size should be 0 */
1002
1003
1004   if (strcmp (scnhdr_int->s_name, _BSS) == 0) 
1005     {
1006       ps = scnhdr_int->s_size;
1007       ss = 0;
1008     }
1009   else
1010     {
1011       ps = scnhdr_int->s_paddr;
1012       ss = scnhdr_int->s_size;
1013     }
1014
1015   PUT_SCNHDR_SIZE (abfd, ss,
1016                    (bfd_byte *) scnhdr_ext->s_size);
1017
1018
1019   PUT_SCNHDR_PADDR (abfd, ps, (bfd_byte *) scnhdr_ext->s_paddr);
1020
1021   PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr,
1022                      (bfd_byte *) scnhdr_ext->s_scnptr);
1023   PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr,
1024                      (bfd_byte *) scnhdr_ext->s_relptr);
1025   PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr,
1026                       (bfd_byte *) scnhdr_ext->s_lnnoptr);
1027
1028   /* Extra flags must be set when dealing with NT.  All sections should also
1029      have the IMAGE_SCN_MEM_READ (0x40000000) flag set.  In addition, the
1030      .text section must have IMAGE_SCN_MEM_EXECUTE (0x20000000) and the data
1031      sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set
1032      (this is especially important when dealing with the .idata section since
1033      the addresses for routines from .dlls must be overwritten).  If .reloc
1034      section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE
1035      (0x02000000).  Also, the resource data should also be read and
1036      writable.  */
1037
1038   /* FIXME: alignment is also encoded in this field, at least on ppc (krk) */
1039   /* FIXME: even worse, I don't see how to get the original alignment field*/
1040   /*        back...                                                        */
1041
1042   {
1043     int flags = scnhdr_int->s_flags;
1044     if (strcmp (scnhdr_int->s_name, ".data")  == 0 ||
1045         strcmp (scnhdr_int->s_name, ".CRT")   == 0 ||
1046         strcmp (scnhdr_int->s_name, ".rsrc")  == 0 ||
1047         strcmp (scnhdr_int->s_name, ".bss")   == 0)
1048       flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
1049     else if (strcmp (scnhdr_int->s_name, ".text") == 0)
1050       flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
1051     else if (strcmp (scnhdr_int->s_name, ".reloc") == 0)
1052       flags = SEC_DATA| IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE;
1053     else if (strcmp (scnhdr_int->s_name, ".idata") == 0)
1054       flags = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | SEC_DATA;     
1055     else if (strcmp (scnhdr_int->s_name, ".rdata") == 0
1056              || strcmp (scnhdr_int->s_name, ".edata") == 0)
1057       flags =  IMAGE_SCN_MEM_READ | SEC_DATA;     
1058     /* ppc-nt additions */
1059     else if (strcmp (scnhdr_int->s_name, ".pdata") == 0)
1060       flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES |
1061                           IMAGE_SCN_MEM_READ ;
1062     /* Remember this field is a max of 8 chars, so the null is _not_ there
1063        for an 8 character name like ".reldata". (yep. Stupid bug) */
1064     else if (strncmp (scnhdr_int->s_name, ".reldata", strlen(".reldata")) == 0)
1065       flags =  IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES |
1066                IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ;
1067     else if (strcmp (scnhdr_int->s_name, ".ydata") == 0)
1068       flags =  IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES |
1069                IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ;
1070     else if (strcmp (scnhdr_int->s_name, ".drectve") == 0)
1071       flags =  IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE ;
1072     /* end of ppc-nt additions */
1073
1074     bfd_h_put_32(abfd, flags, (bfd_byte *) scnhdr_ext->s_flags);
1075   }
1076
1077   if (scnhdr_int->s_nlnno <= 0xffff)
1078     bfd_h_put_16(abfd, scnhdr_int->s_nlnno, (bfd_byte *) scnhdr_ext->s_nlnno);
1079   else
1080     {
1081       (*_bfd_error_handler) ("%s: line number overflow: 0x%lx > 0xffff",
1082                              bfd_get_filename (abfd),
1083                              scnhdr_int->s_nlnno);
1084       bfd_set_error (bfd_error_file_truncated);
1085       bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nlnno);
1086       ret = 0;
1087     }
1088   if (scnhdr_int->s_nreloc <= 0xffff)
1089     bfd_h_put_16(abfd, scnhdr_int->s_nreloc, (bfd_byte *) scnhdr_ext->s_nreloc);
1090   else
1091     {
1092       (*_bfd_error_handler) ("%s: reloc overflow: 0x%lx > 0xffff",
1093                              bfd_get_filename (abfd),
1094                              scnhdr_int->s_nreloc);
1095       bfd_set_error (bfd_error_file_truncated);
1096       bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nreloc);
1097       ret = 0;
1098     }
1099   return ret;
1100 }
1101
1102 static char * dir_names[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = 
1103 {
1104   "Export Directory [.edata]",
1105   "Import Directory [parts of .idata]",
1106   "Resource Directory [.rsrc]",
1107   "Exception Directory [.pdata]",
1108   "Security Directory",
1109   "Base Relocation Directory [.reloc]",
1110   "Debug Directory",
1111   "Description Directory",
1112   "Special Directory",
1113   "Thread Storage Directory [.tls]",
1114   "Load Configuration Directory",
1115   "Bound Import Directory",
1116   "Import Address Table Directory",
1117   "Reserved",
1118   "Reserved",
1119   "Reserved"
1120 };
1121
1122 /**********************************************************************/
1123 static boolean
1124 pe_print_idata(abfd, vfile)
1125      bfd*abfd;
1126      void *vfile;
1127 {
1128   FILE *file = vfile;
1129   bfd_byte *data = 0;
1130   asection *section = bfd_get_section_by_name (abfd, ".idata");
1131
1132 #ifdef POWERPC_LE_PE
1133   asection *rel_section = bfd_get_section_by_name (abfd, ".reldata");
1134 #endif
1135
1136   bfd_size_type datasize = 0;
1137   bfd_size_type i;
1138   bfd_size_type start, stop;
1139   int onaline = 20;
1140   bfd_vma addr_value;
1141   bfd_vma loadable_toc_address;
1142   bfd_vma toc_address;
1143   bfd_vma start_address;
1144
1145   pe_data_type *pe = pe_data (abfd);
1146   struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
1147
1148   if (section == 0)
1149     return true;
1150
1151 #ifdef POWERPC_LE_PE
1152   if (rel_section != 0 && bfd_section_size (abfd, rel_section) != 0)
1153     {
1154       /* The toc address can be found by taking the starting address,
1155          which on the PPC locates a function descriptor. The descriptor
1156          consists of the function code starting address followed by the
1157          address of the toc. The starting address we get from the bfd,
1158          and the descriptor is supposed to be in the .reldata section. 
1159       */
1160
1161       bfd_byte *data = 0;
1162       int offset;
1163       data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, 
1164                                                                  rel_section));
1165       if (data == NULL && bfd_section_size (abfd, rel_section) != 0)
1166         return false;
1167
1168       datasize = bfd_section_size (abfd, rel_section);
1169   
1170       bfd_get_section_contents (abfd, 
1171                                 rel_section, 
1172                                 (PTR) data, 0, 
1173                                 bfd_section_size (abfd, rel_section));
1174
1175       offset = abfd->start_address - rel_section->vma;
1176
1177       start_address = bfd_get_32(abfd, data+offset);
1178       loadable_toc_address = bfd_get_32(abfd, data+offset+4);
1179       toc_address = loadable_toc_address - 32768;
1180
1181       fprintf(file,
1182               "\nFunction descriptor located at the start address: %04lx\n",
1183               (unsigned long int) (abfd->start_address));
1184       fprintf (file,
1185                "\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n", 
1186                start_address, loadable_toc_address, toc_address);
1187     }
1188   else
1189     {
1190       loadable_toc_address = 0; 
1191       toc_address = 0; 
1192       start_address = 0;
1193     }
1194 #endif
1195
1196   fprintf(file,
1197           "\nThe Import Tables (interpreted .idata section contents)\n");
1198   fprintf(file,
1199           " vma:    Hint    Time      Forward  DLL       First\n");
1200   fprintf(file,
1201           "         Table   Stamp     Chain    Name      Thunk\n");
1202
1203   if (bfd_section_size (abfd, section) == 0)
1204     return true;
1205
1206   data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
1207   datasize = bfd_section_size (abfd, section);
1208   if (data == NULL && datasize != 0)
1209     return false;
1210
1211   bfd_get_section_contents (abfd, 
1212                             section, 
1213                             (PTR) data, 0, 
1214                             bfd_section_size (abfd, section));
1215
1216   start = 0;
1217
1218   stop = bfd_section_size (abfd, section);
1219
1220   for (i = start; i < stop; i += onaline)
1221     {
1222       bfd_vma hint_addr;
1223       bfd_vma time_stamp;
1224       bfd_vma forward_chain;
1225       bfd_vma dll_name;
1226       bfd_vma first_thunk;
1227       int idx;
1228       int j;
1229       char *dll;
1230       int adj = extra->ImageBase - section->vma;
1231
1232       fprintf (file,
1233                " %04lx\t", 
1234                (unsigned long int) (i + section->vma));
1235       
1236       if (i+20 > stop)
1237         {
1238           /* check stuff */
1239           ;
1240         }
1241       
1242       hint_addr = bfd_get_32(abfd, data+i);
1243       time_stamp = bfd_get_32(abfd, data+i+4);
1244       forward_chain = bfd_get_32(abfd, data+i+8);
1245       dll_name = bfd_get_32(abfd, data+i+12);
1246       first_thunk = bfd_get_32(abfd, data+i+16);
1247       
1248       fprintf(file, "%08lx %08lx %08lx %08lx %08lx\n",
1249               hint_addr,
1250               time_stamp,
1251               forward_chain,
1252               dll_name,
1253               first_thunk);
1254
1255       if (hint_addr ==0)
1256         {
1257           break;
1258         }
1259
1260       /* the image base is present in the section->vma */
1261       dll = data + dll_name + adj;
1262       fprintf(file, "\n\tDLL Name: %s\n", dll);
1263       fprintf(file, "\tvma:  Ordinal  Member-Name\n");
1264
1265       idx = hint_addr + adj;
1266
1267       for (j=0;j<stop;j+=4)
1268         {
1269           int ordinal;
1270           char *member_name;
1271           bfd_vma member = bfd_get_32(abfd, data + idx + j);
1272           if (member == 0)
1273             break;
1274           ordinal = bfd_get_16(abfd,
1275                                data + member + adj);
1276           member_name = data + member + adj + 2;
1277           fprintf(file, "\t%04lx\t %4d  %s\n",
1278                   member, ordinal, member_name);
1279         }
1280
1281       if (hint_addr != first_thunk) 
1282         {
1283           int differ = 0;
1284           int idx2;
1285
1286           idx2 = first_thunk + adj;
1287
1288           for (j=0;j<stop;j+=4)
1289             {
1290               int ordinal;
1291               char *member_name;
1292               bfd_vma hint_member = bfd_get_32(abfd, data + idx + j);
1293               bfd_vma iat_member = bfd_get_32(abfd, data + idx2 + j);
1294               if (hint_member != iat_member)
1295                 {
1296                   if (differ == 0)
1297                     {
1298                       fprintf(file, 
1299                               "\tThe Import Address Table (difference found)\n");
1300                       fprintf(file, "\tvma:  Ordinal  Member-Name\n");
1301                       differ = 1;
1302                     }
1303                   if (iat_member == 0)
1304                     {
1305                       fprintf(file,
1306                               "\t>>> Ran out of IAT members!\n");
1307                     }
1308                   else 
1309                     {
1310                       ordinal = bfd_get_16(abfd,
1311                                            data + iat_member + adj);
1312                       member_name = data + iat_member + adj + 2;
1313                       fprintf(file, "\t%04lx\t %4d  %s\n",
1314                               iat_member, ordinal, member_name);
1315                     }
1316                   break;
1317                 }
1318               if (hint_member == 0)
1319                 break;
1320             }
1321           if (differ == 0)
1322             {
1323               fprintf(file,
1324                       "\tThe Import Address Table is identical\n");
1325             }
1326         }
1327
1328       fprintf(file, "\n");
1329
1330     }
1331
1332   free (data);
1333 }
1334
1335 static boolean
1336 pe_print_edata(abfd, vfile)
1337      bfd*abfd;
1338      void *vfile;
1339 {
1340   FILE *file = vfile;
1341   bfd_byte *data = 0;
1342   asection *section = bfd_get_section_by_name (abfd, ".edata");
1343
1344   bfd_size_type datasize = 0;
1345   bfd_size_type i;
1346
1347   int adj;
1348   struct EDT_type 
1349     {
1350       long export_flags;             /* reserved - should be zero */
1351       long time_stamp;
1352       short major_ver;
1353       short minor_ver;
1354       bfd_vma name;                  /* rva - relative to image base */
1355       long base;                     /* ordinal base */
1356       long num_functions;        /* Number in the export address table */
1357       long num_names;            /* Number in the name pointer table */
1358       bfd_vma eat_addr;    /* rva to the export address table */
1359       bfd_vma npt_addr;        /* rva to the Export Name Pointer Table */
1360       bfd_vma ot_addr; /* rva to the Ordinal Table */
1361     } edt;
1362
1363   pe_data_type *pe = pe_data (abfd);
1364   struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
1365
1366   if (section == 0)
1367     return true;
1368
1369   data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, 
1370                                                              section));
1371   datasize = bfd_section_size (abfd, section);
1372
1373   if (data == NULL && datasize != 0)
1374     return false;
1375
1376   bfd_get_section_contents (abfd, 
1377                             section, 
1378                             (PTR) data, 0, 
1379                             bfd_section_size (abfd, section));
1380
1381   /* Go get Export Directory Table */
1382   edt.export_flags   = bfd_get_32(abfd, data+0); 
1383   edt.time_stamp     = bfd_get_32(abfd, data+4);
1384   edt.major_ver      = bfd_get_16(abfd, data+8);
1385   edt.minor_ver      = bfd_get_16(abfd, data+10);
1386   edt.name           = bfd_get_32(abfd, data+12);
1387   edt.base           = bfd_get_32(abfd, data+16);
1388   edt.num_functions  = bfd_get_32(abfd, data+20); 
1389   edt.num_names      = bfd_get_32(abfd, data+24); 
1390   edt.eat_addr       = bfd_get_32(abfd, data+28);
1391   edt.npt_addr       = bfd_get_32(abfd, data+32); 
1392   edt.ot_addr        = bfd_get_32(abfd, data+36);
1393
1394   adj = extra->ImageBase - section->vma;
1395
1396
1397   /* Dump the EDT first first */
1398   fprintf(file,
1399           "\nThe Export Tables (interpreted .edata section contents)\n\n");
1400
1401   fprintf(file,
1402           "Export Flags \t\t\t%x\n",edt.export_flags);
1403
1404   fprintf(file,
1405           "Time/Date stamp \t\t%x\n",edt.time_stamp);
1406
1407   fprintf(file,
1408           "Major/Minor \t\t\t%d/%d\n", edt.major_ver, edt.minor_ver);
1409
1410   fprintf(file,
1411           "Name \t\t\t\t%x %s\n", edt.name, data + edt.name + adj);
1412
1413   fprintf(file,
1414           "Ordinal Base \t\t\t%d\n", edt.base);
1415
1416   fprintf(file,
1417           "Number in:\n");
1418
1419   fprintf(file,
1420           "\tExport Address Table \t\t%x\n", edt.num_functions);
1421
1422   fprintf(file,
1423           "\t[Name Pointer/Ordinal] Table\t%d\n", edt.num_names);
1424
1425   fprintf(file,
1426           "Table Addresses\n");
1427
1428   fprintf(file,
1429           "\tExport Address Table \t\t%x\n",
1430           edt.eat_addr);
1431
1432   fprintf(file,
1433           "\tName Pointer Table \t\t%x\n",
1434           edt.npt_addr);
1435
1436   fprintf(file,
1437           "\tOrdinal Table \t\t\t%x\n",
1438           edt.ot_addr);
1439
1440   
1441   /* The next table to find si the Export Address Table. It's basically
1442      a list of pointers that either locate a function in this dll, or
1443      forward the call to another dll. Something like:
1444       typedef union 
1445       {
1446         long export_rva;
1447         long forwarder_rva;
1448       } export_address_table_entry;
1449   */
1450
1451   fprintf(file,
1452           "\nExport Address Table -- Ordinal Base %d\n",
1453           edt.base);
1454
1455   for (i = 0; i < edt.num_functions; ++i)
1456     {
1457       bfd_vma eat_member = bfd_get_32(abfd, 
1458                                       data + edt.eat_addr + (i*4) + adj);
1459       bfd_vma eat_actual = extra->ImageBase + eat_member;
1460       bfd_vma edata_start = bfd_get_section_vma(abfd,section);
1461       bfd_vma edata_end = edata_start + bfd_section_size (abfd, section);
1462
1463
1464       if (eat_member == 0)
1465         continue;
1466
1467       if (edata_start < eat_actual && eat_actual < edata_end) 
1468         {
1469           /* this rva is to a name (forwarding function) in our section */
1470           /* Should locate a function descriptor */
1471           fprintf(file,
1472                   "\t[%4d] +base[%4d] %04lx %s -- %s\n", 
1473                   i, i+edt.base, eat_member, "Forwarder RVA",
1474                   data + eat_member + adj);
1475         }
1476       else
1477         {
1478           /* Should locate a function descriptor in the reldata section */
1479           fprintf(file,
1480                   "\t[%4d] +base[%4d] %04lx %s\n", 
1481                   i, i+edt.base, eat_member, "Export RVA");
1482         }
1483     }
1484
1485   /* The Export Name Pointer Table is paired with the Export Ordinal Table */
1486   /* Dump them in parallel for clarity */
1487   fprintf(file,
1488           "\n[Ordinal/Name Pointer] Table\n");
1489
1490   for (i = 0; i < edt.num_names; ++i)
1491     {
1492       bfd_vma name_ptr = bfd_get_32(abfd, 
1493                                     data + 
1494                                     edt.npt_addr
1495                                     + (i*4) + adj);
1496       
1497       char *name = data + name_ptr + adj;
1498
1499       bfd_vma ord = bfd_get_16(abfd, 
1500                                     data + 
1501                                     edt.ot_addr
1502                                     + (i*2) + adj);
1503       fprintf(file,
1504               "\t[%4d] %s\n", ord, name);
1505
1506     }
1507
1508   free (data);
1509 }
1510
1511 static boolean
1512 pe_print_pdata(abfd, vfile)
1513      bfd*abfd;
1514      void *vfile;
1515 {
1516   FILE *file = vfile;
1517   bfd_byte *data = 0;
1518   asection *section = bfd_get_section_by_name (abfd, ".pdata");
1519   bfd_size_type datasize = 0;
1520   bfd_size_type i;
1521   bfd_size_type start, stop;
1522   int onaline = 20;
1523   bfd_vma addr_value;
1524
1525   if (section == 0)
1526     return true;
1527
1528   fprintf(file,
1529           "\nThe Function Table (interpreted .pdata section contents)\n");
1530   fprintf(file,
1531           " vma:\t\tBegin    End      EH       EH       PrologEnd\n");
1532   fprintf(file,
1533           "     \t\tAddress  Address  Handler  Data     Address\n");
1534
1535   if (bfd_section_size (abfd, section) == 0)
1536     return true;
1537
1538   data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
1539   datasize = bfd_section_size (abfd, section);
1540   if (data == NULL && datasize != 0)
1541     return false;
1542
1543   bfd_get_section_contents (abfd, 
1544                             section, 
1545                             (PTR) data, 0, 
1546                             bfd_section_size (abfd, section));
1547
1548   start = 0;
1549
1550   stop = bfd_section_size (abfd, section);
1551
1552   for (i = start; i < stop; i += onaline)
1553     {
1554       bfd_vma begin_addr;
1555       bfd_vma end_addr;
1556       bfd_vma eh_handler;
1557       bfd_vma eh_data;
1558       bfd_vma prolog_end_addr;
1559
1560       if (i+20 > stop)
1561           break;
1562       
1563       begin_addr = bfd_get_32(abfd, data+i);
1564       end_addr = bfd_get_32(abfd, data+i+4);
1565       eh_handler = bfd_get_32(abfd, data+i+8);
1566       eh_data = bfd_get_32(abfd, data+i+12);
1567       prolog_end_addr = bfd_get_32(abfd, data+i+16);
1568       
1569       if (begin_addr == 0)
1570         {
1571           /* We are probably into the padding of the
1572              section now */
1573           break;
1574         }
1575
1576       fprintf (file,
1577                " %08lx\t", 
1578                (unsigned long int) (i + section->vma));
1579
1580       fprintf(file, "%08lx %08lx %08lx %08lx %08lx",
1581               begin_addr,
1582               end_addr,
1583               eh_handler,
1584               eh_data,
1585               prolog_end_addr);
1586
1587 #ifdef POWERPC_LE_PE
1588       if (eh_handler == 0 && eh_data != 0)
1589         {
1590           /* Special bits here, although the meaning may */
1591           /* be a little mysterious. The only one I know */
1592           /* for sure is 0x03.                           */
1593           /* Code Significance                           */
1594           /* 0x00 None                                   */
1595           /* 0x01 Register Save Millicode                */
1596           /* 0x02 Register Restore Millicode             */
1597           /* 0x03 Glue Code Sequence                     */
1598           switch (eh_data)
1599             {
1600             case 0x01:
1601               fprintf(file, " Register save millicode");
1602               break;
1603             case 0x02:
1604               fprintf(file, " Register restore millicode");
1605               break;
1606             case 0x03:
1607               fprintf(file, " Glue code sequence");
1608               break;
1609             default:
1610               break;
1611             }
1612         }
1613 #endif     
1614       fprintf(file, "\n");
1615     }
1616
1617   free (data);
1618 }
1619
1620 static const char *tbl[6] =
1621 {
1622 "ABSOLUTE",
1623 "HIGH",
1624 "LOW",
1625 "HIGHLOW",
1626 "HIGHADJ",
1627 "unknown"
1628 };
1629
1630 static boolean
1631 pe_print_reloc(abfd, vfile)
1632      bfd*abfd;
1633      void *vfile;
1634 {
1635   FILE *file = vfile;
1636   bfd_byte *data = 0;
1637   asection *section = bfd_get_section_by_name (abfd, ".reloc");
1638   bfd_size_type datasize = 0;
1639   bfd_size_type i;
1640   bfd_size_type start, stop;
1641   int onaline = 20;
1642   bfd_vma addr_value;
1643
1644   if (section == 0)
1645     return true;
1646
1647   if (bfd_section_size (abfd, section) == 0)
1648     return true;
1649
1650   fprintf(file,
1651           "\n\nPE File Base Relocations (interpreted .reloc"
1652           " section contents)\n");
1653
1654   data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
1655   datasize = bfd_section_size (abfd, section);
1656   if (data == NULL && datasize != 0)
1657     return false;
1658
1659   bfd_get_section_contents (abfd, 
1660                             section, 
1661                             (PTR) data, 0, 
1662                             bfd_section_size (abfd, section));
1663
1664   start = 0;
1665
1666   stop = bfd_section_size (abfd, section);
1667
1668   for (i = start; i < stop;)
1669     {
1670       int j;
1671       bfd_vma virtual_address;
1672       long number, size;
1673
1674       /* The .reloc section is a sequence of blocks, with a header consisting
1675          of two 32 bit quantities, followed by a number of 16 bit entries */
1676
1677       virtual_address = bfd_get_32(abfd, data+i);
1678       size = bfd_get_32(abfd, data+i+4);
1679       number = (size - 8) / 2;
1680
1681       if (size == 0) 
1682         {
1683           break;
1684         }
1685
1686       fprintf (file,
1687                "\nVirtual Address: %08lx Chunk size %d (0x%x) "
1688                "Number of fixups %d\n", 
1689                virtual_address, size, size, number);
1690
1691       for (j = 0; j < number; ++j)
1692         {
1693           unsigned short e = bfd_get_16(abfd, data + i + 8 + j*2);
1694           int t =   (e & 0xF000) >> 12;
1695           int off = e & 0x0FFF;
1696
1697           if (t > 5) 
1698             abort();
1699
1700           fprintf(file,
1701                   "\treloc %4d offset %4x [%4x] %s\n", 
1702                   j, off, off+virtual_address, tbl[t]);
1703           
1704         }
1705       i += size;
1706     }
1707
1708   free (data);
1709 }
1710
1711 static boolean
1712 pe_print_private_bfd_data (abfd, vfile)
1713      bfd *abfd;
1714      PTR vfile;
1715 {
1716   FILE *file = (FILE *) vfile;
1717   int j;
1718   pe_data_type *pe = pe_data (abfd);
1719   struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr;
1720
1721   fprintf (file,"\nImageBase\t\t");
1722   fprintf_vma (file, i->ImageBase);
1723   fprintf (file,"\nSectionAlignment\t");
1724   fprintf_vma (file, i->SectionAlignment);
1725   fprintf (file,"\nFileAlignment\t\t");
1726   fprintf_vma (file, i->FileAlignment);
1727   fprintf (file,"\nMajorOSystemVersion\t%d\n", i->MajorOperatingSystemVersion);
1728   fprintf (file,"MinorOSystemVersion\t%d\n", i->MinorOperatingSystemVersion);
1729   fprintf (file,"MajorImageVersion\t%d\n", i->MajorImageVersion);
1730   fprintf (file,"MinorImageVersion\t%d\n", i->MinorImageVersion);
1731   fprintf (file,"MajorSubsystemVersion\t%d\n", i->MajorSubsystemVersion);
1732   fprintf (file,"MinorSubsystemVersion\t%d\n", i->MinorSubsystemVersion);
1733   fprintf (file,"Reserved1\t\t%08lx\n", i->Reserved1);
1734   fprintf (file,"SizeOfImage\t\t%08lx\n", i->SizeOfImage);
1735   fprintf (file,"SizeOfHeaders\t\t%08lx\n", i->SizeOfHeaders);
1736   fprintf (file,"CheckSum\t\t%08lx\n", i->CheckSum);
1737   fprintf (file,"Subsystem\t\t%08x\n", i->Subsystem);
1738   fprintf (file,"DllCharacteristics\t%08x\n", i->DllCharacteristics);
1739   fprintf (file,"SizeOfStackReserve\t");
1740   fprintf_vma (file, i->SizeOfStackReserve);
1741   fprintf (file,"\nSizeOfStackCommit\t");
1742   fprintf_vma (file, i->SizeOfStackCommit);
1743   fprintf (file,"\nSizeOfHeapReserve\t");
1744   fprintf_vma (file, i->SizeOfHeapReserve);
1745   fprintf (file,"\nSizeOfHeapCommit\t");
1746   fprintf_vma (file, i->SizeOfHeapCommit);
1747   fprintf (file,"\nLoaderFlags\t\t%08lx\n", i->LoaderFlags);
1748   fprintf (file,"NumberOfRvaAndSizes\t%08lx\n", i->NumberOfRvaAndSizes);
1749
1750   fprintf (file,"\nThe Data Directory\n");
1751   for (j = 0; j < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; j++) 
1752     {
1753       fprintf (file, "Entry %1x ", j);
1754       fprintf_vma (file, i->DataDirectory[j].VirtualAddress);
1755       fprintf (file, " %08lx ", i->DataDirectory[j].Size);
1756       fprintf (file, "%s\n", dir_names[j]);
1757     }
1758
1759   pe_print_idata(abfd, vfile);
1760   pe_print_edata(abfd, vfile);
1761   pe_print_pdata(abfd, vfile);
1762   pe_print_reloc(abfd, vfile);
1763
1764   return true;
1765 }
1766
1767 static boolean
1768 pe_mkobject (abfd)
1769      bfd * abfd;
1770 {
1771   pe_data_type *pe;
1772   abfd->tdata.pe_obj_data = 
1773     (struct pe_tdata *) bfd_zalloc (abfd, sizeof (pe_data_type));
1774
1775   if (abfd->tdata.pe_obj_data == 0)
1776     return false;
1777
1778   pe = pe_data (abfd);
1779
1780   pe->coff.pe = 1;
1781   pe->in_reloc_p = in_reloc_p;
1782   return true;
1783 }
1784
1785 /* Create the COFF backend specific information.  */
1786 static PTR
1787 pe_mkobject_hook (abfd, filehdr, aouthdr)
1788      bfd * abfd;
1789      PTR filehdr;
1790      PTR aouthdr;
1791 {
1792   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
1793   pe_data_type *pe;
1794
1795   if (pe_mkobject (abfd) == false)
1796     return NULL;
1797
1798   pe = pe_data (abfd);
1799   pe->coff.sym_filepos = internal_f->f_symptr;
1800   /* These members communicate important constants about the symbol
1801      table to GDB's symbol-reading code.  These `constants'
1802      unfortunately vary among coff implementations...  */
1803   pe->coff.local_n_btmask = N_BTMASK;
1804   pe->coff.local_n_btshft = N_BTSHFT;
1805   pe->coff.local_n_tmask = N_TMASK;
1806   pe->coff.local_n_tshift = N_TSHIFT;
1807   pe->coff.local_symesz = SYMESZ;
1808   pe->coff.local_auxesz = AUXESZ;
1809   pe->coff.local_linesz = LINESZ;
1810
1811   obj_raw_syment_count (abfd) =
1812     obj_conv_table_size (abfd) =
1813       internal_f->f_nsyms;
1814
1815   pe->real_flags = internal_f->f_flags;
1816
1817 #ifdef COFF_IMAGE_WITH_PE
1818   if (aouthdr) 
1819     {
1820       pe->pe_opthdr = ((struct internal_aouthdr *)aouthdr)->pe;
1821     }
1822 #endif
1823
1824   return (PTR) pe;
1825 }
1826
1827
1828
1829 /* Copy any private info we understand from the input bfd
1830    to the output bfd.  */
1831
1832 #define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data
1833
1834 static boolean
1835 pe_bfd_copy_private_bfd_data (ibfd, obfd)
1836      bfd *ibfd, *obfd;
1837 {
1838   /* One day we may try to grok other private data.  */
1839   if (ibfd->xvec->flavour != bfd_target_coff_flavour
1840       || obfd->xvec->flavour != bfd_target_coff_flavour)
1841     return true;
1842
1843   pe_data(obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr;
1844
1845   return true;
1846 }