xref: /openbsd-src/gnu/usr.bin/binutils/bfd/coff-stgo32.c (revision d2201f2f89f0be1a0be6f7568000ed297414a06d)
15f210c2aSfgsch /* BFD back-end for Intel 386 COFF files (DJGPP variant with a stub).
2*d2201f2fSdrahn    Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3f7cc78ecSespie    Written by Robert Hoehne.
4f7cc78ecSespie 
5f7cc78ecSespie    This file is part of BFD, the Binary File Descriptor library.
6f7cc78ecSespie 
7f7cc78ecSespie    This program is free software; you can redistribute it and/or modify
8f7cc78ecSespie    it under the terms of the GNU General Public License as published by
9f7cc78ecSespie    the Free Software Foundation; either version 2 of the License, or
10f7cc78ecSespie    (at your option) any later version.
11f7cc78ecSespie 
12f7cc78ecSespie    This program is distributed in the hope that it will be useful,
13f7cc78ecSespie    but WITHOUT ANY WARRANTY; without even the implied warranty of
14f7cc78ecSespie    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15f7cc78ecSespie    GNU General Public License for more details.
16f7cc78ecSespie 
17f7cc78ecSespie    You should have received a copy of the GNU General Public License
18f7cc78ecSespie    along with this program; if not, write to the Free Software
19f7cc78ecSespie    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20f7cc78ecSespie 
21f7cc78ecSespie /* This file handles now also stubbed coff images. The stub is a small
22f7cc78ecSespie    DOS executable program before the coff image to load it in memory
23f7cc78ecSespie    and execute it. This is needed, because DOS cannot run coff files.
24f7cc78ecSespie 
25f7cc78ecSespie    All the functions below are called by the corresponding functions
26f7cc78ecSespie    from coffswap.h.
27f7cc78ecSespie    The only thing what they do is to adjust the information stored in
28f7cc78ecSespie    the COFF file which are offset into the file.
29f7cc78ecSespie    This is needed, because DJGPP uses a very special way to load and run
30f7cc78ecSespie    the coff image. It loads the image in memory and assumes then, that the
31f7cc78ecSespie    image had no stub by using the filepointers as pointers in the coff
32f7cc78ecSespie    image and NOT in the file.
33f7cc78ecSespie 
34f7cc78ecSespie    To be compatible with any existing executables I have fixed this
35*d2201f2fSdrahn    here and NOT in the DJGPP startup code.  */
36f7cc78ecSespie 
37f7cc78ecSespie #define TARGET_SYM		go32stubbedcoff_vec
38f7cc78ecSespie #define TARGET_NAME		"coff-go32-exe"
39f7cc78ecSespie #define TARGET_UNDERSCORE	'_'
40f7cc78ecSespie #define COFF_GO32_EXE
41f7cc78ecSespie #define COFF_LONG_SECTION_NAMES
42f7cc78ecSespie #define COFF_SUPPORT_GNU_LINKONCE
435f210c2aSfgsch #define COFF_LONG_FILENAMES
44f7cc78ecSespie 
45f7cc78ecSespie #define COFF_SECTION_ALIGNMENT_ENTRIES \
46f7cc78ecSespie { COFF_SECTION_NAME_EXACT_MATCH (".data"), \
47f7cc78ecSespie   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
48f7cc78ecSespie { COFF_SECTION_NAME_EXACT_MATCH (".text"), \
49*d2201f2fSdrahn   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
50*d2201f2fSdrahn { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
51*d2201f2fSdrahn   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
52*d2201f2fSdrahn { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi"), \
53*d2201f2fSdrahn   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
54f7cc78ecSespie 
55f7cc78ecSespie #include "bfd.h"
56f7cc78ecSespie 
57*d2201f2fSdrahn /* At first the prototypes.  */
58f7cc78ecSespie 
59f7cc78ecSespie static void
60*d2201f2fSdrahn adjust_filehdr_in_post PARAMS ((bfd *, PTR, PTR));
61f7cc78ecSespie static void
62*d2201f2fSdrahn adjust_filehdr_out_pre PARAMS ((bfd *, PTR, PTR));
63f7cc78ecSespie static void
64*d2201f2fSdrahn adjust_filehdr_out_post PARAMS ((bfd *, PTR, PTR));
65*d2201f2fSdrahn static void
66*d2201f2fSdrahn adjust_scnhdr_in_post PARAMS ((bfd *, PTR, PTR));
67*d2201f2fSdrahn static void
68*d2201f2fSdrahn adjust_scnhdr_out_pre PARAMS ((bfd *, PTR, PTR));
69*d2201f2fSdrahn static void
70*d2201f2fSdrahn adjust_scnhdr_out_post PARAMS ((bfd *, PTR, PTR));
71*d2201f2fSdrahn static void
72*d2201f2fSdrahn adjust_aux_in_post PARAMS ((bfd *, PTR, int, int, int, int, PTR));
73*d2201f2fSdrahn static void
74*d2201f2fSdrahn adjust_aux_out_pre PARAMS ((bfd *, PTR, int, int, int, int, PTR));
75*d2201f2fSdrahn static void
76*d2201f2fSdrahn adjust_aux_out_post PARAMS ((bfd *, PTR, int, int, int, int, PTR));
77*d2201f2fSdrahn static void
78*d2201f2fSdrahn create_go32_stub PARAMS ((bfd *));
79f7cc78ecSespie 
80*d2201f2fSdrahn /* All that ..._PRE and ...POST functions are called from the corresponding
81f7cc78ecSespie    coff_swap... functions. The ...PRE functions are called at the beginning
82*d2201f2fSdrahn    of the function and the ...POST functions at the end of the swap routines.  */
83f7cc78ecSespie 
84f7cc78ecSespie #define COFF_ADJUST_FILEHDR_IN_POST adjust_filehdr_in_post
85f7cc78ecSespie #define COFF_ADJUST_FILEHDR_OUT_PRE adjust_filehdr_out_pre
86f7cc78ecSespie #define COFF_ADJUST_FILEHDR_OUT_POST adjust_filehdr_out_post
87f7cc78ecSespie 
88f7cc78ecSespie #define COFF_ADJUST_SCNHDR_IN_POST adjust_scnhdr_in_post
89f7cc78ecSespie #define COFF_ADJUST_SCNHDR_OUT_PRE adjust_scnhdr_out_pre
90f7cc78ecSespie #define COFF_ADJUST_SCNHDR_OUT_POST adjust_scnhdr_out_post
91f7cc78ecSespie 
92f7cc78ecSespie #define COFF_ADJUST_AUX_IN_POST adjust_aux_in_post
93f7cc78ecSespie #define COFF_ADJUST_AUX_OUT_PRE adjust_aux_out_pre
94f7cc78ecSespie #define COFF_ADJUST_AUX_OUT_POST adjust_aux_out_post
95f7cc78ecSespie 
96*d2201f2fSdrahn static bfd_boolean
97*d2201f2fSdrahn   go32_stubbed_coff_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
98f7cc78ecSespie 
99f7cc78ecSespie #define coff_bfd_copy_private_bfd_data go32_stubbed_coff_bfd_copy_private_bfd_data
100f7cc78ecSespie 
101f7cc78ecSespie #include "coff-i386.c"
102f7cc78ecSespie 
103*d2201f2fSdrahn /* I hold in the usrdata the stub.  */
104f7cc78ecSespie #define bfd_coff_go32stub bfd_usrdata
105f7cc78ecSespie 
106f7cc78ecSespie /* This macro is used, because I cannot assume the endianess of the
107*d2201f2fSdrahn    host system.  */
108*d2201f2fSdrahn #define _H(index) (H_GET_16 (abfd, (header+index*2)))
109f7cc78ecSespie 
110f7cc78ecSespie /* These bytes are a 2048-byte DOS executable, which loads the COFF
111*d2201f2fSdrahn    image into memory and then runs it. It is called 'stub'.  */
112f7cc78ecSespie 
113*d2201f2fSdrahn static const unsigned char stub_bytes[STUBSIZE] =
114f7cc78ecSespie {
115f7cc78ecSespie #include "go32stub.h"
116f7cc78ecSespie };
117f7cc78ecSespie 
118f7cc78ecSespie /*
119f7cc78ecSespie    I have not commented each swap function below, because the
120f7cc78ecSespie    technique is in any function the same. For the ...in function,
121f7cc78ecSespie    all the pointers are adjusted by adding STUBSIZE and for the
122f7cc78ecSespie    ...out function, it is subtracted first and after calling the
123*d2201f2fSdrahn    standard swap function it is reset to the old value.  */
124f7cc78ecSespie 
125f7cc78ecSespie /* This macro is used for adjusting the filepointers, which
126*d2201f2fSdrahn    is done only, if the pointer is nonzero.  */
127f7cc78ecSespie 
128f7cc78ecSespie #define ADJUST_VAL(val,diff) \
129f7cc78ecSespie   if (val != 0) val += diff
130f7cc78ecSespie 
131f7cc78ecSespie static void
adjust_filehdr_in_post(abfd,src,dst)132f7cc78ecSespie adjust_filehdr_in_post  (abfd, src, dst)
133f7cc78ecSespie      bfd *abfd;
134f7cc78ecSespie      PTR src;
135f7cc78ecSespie      PTR dst;
136f7cc78ecSespie {
137f7cc78ecSespie   FILHDR *filehdr_src = (FILHDR *) src;
138f7cc78ecSespie   struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
139f7cc78ecSespie 
140f7cc78ecSespie   ADJUST_VAL (filehdr_dst->f_symptr, STUBSIZE);
141f7cc78ecSespie 
142*d2201f2fSdrahn   /* Save now the stub to be used later.  */
143*d2201f2fSdrahn   bfd_coff_go32stub (abfd) = (PTR) bfd_alloc (abfd, (bfd_size_type) STUBSIZE);
144f7cc78ecSespie 
145f7cc78ecSespie   /* Since this function returns no status, I do not set here
146f7cc78ecSespie      any bfd_error_...
147f7cc78ecSespie      That means, before the use of bfd_coff_go32stub (), this value
148*d2201f2fSdrahn      should be checked if it is != NULL.  */
149f7cc78ecSespie   if (bfd_coff_go32stub (abfd) == NULL)
150f7cc78ecSespie     return;
151f7cc78ecSespie   memcpy (bfd_coff_go32stub (abfd), filehdr_src->stub, STUBSIZE);
152f7cc78ecSespie }
153f7cc78ecSespie 
154f7cc78ecSespie static void
adjust_filehdr_out_pre(abfd,in,out)155f7cc78ecSespie adjust_filehdr_out_pre  (abfd, in, out)
156f7cc78ecSespie      bfd *abfd;
157f7cc78ecSespie      PTR in;
158f7cc78ecSespie      PTR out;
159f7cc78ecSespie {
160f7cc78ecSespie   struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in;
161f7cc78ecSespie   FILHDR *filehdr_out = (FILHDR *) out;
162f7cc78ecSespie 
163*d2201f2fSdrahn   /* Generate the stub.  */
164f7cc78ecSespie   create_go32_stub (abfd);
165f7cc78ecSespie 
166*d2201f2fSdrahn   /* Copy the stub to the file header.  */
167f7cc78ecSespie   if (bfd_coff_go32stub (abfd) != NULL)
168f7cc78ecSespie     memcpy (filehdr_out->stub, bfd_coff_go32stub (abfd), STUBSIZE);
169f7cc78ecSespie   else
170*d2201f2fSdrahn     /* Use the default.  */
171f7cc78ecSespie     memcpy (filehdr_out->stub, stub_bytes, STUBSIZE);
172f7cc78ecSespie 
173f7cc78ecSespie   ADJUST_VAL (filehdr_in->f_symptr, -STUBSIZE);
174f7cc78ecSespie }
175f7cc78ecSespie 
176f7cc78ecSespie static void
adjust_filehdr_out_post(abfd,in,out)177f7cc78ecSespie adjust_filehdr_out_post  (abfd, in, out)
178f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
179f7cc78ecSespie      PTR in;
180f7cc78ecSespie      PTR out ATTRIBUTE_UNUSED;
181f7cc78ecSespie {
182f7cc78ecSespie   struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in;
183*d2201f2fSdrahn   /* Undo the above change.  */
184f7cc78ecSespie   ADJUST_VAL (filehdr_in->f_symptr, STUBSIZE);
185f7cc78ecSespie }
186f7cc78ecSespie 
187f7cc78ecSespie static void
adjust_scnhdr_in_post(abfd,ext,in)188f7cc78ecSespie adjust_scnhdr_in_post  (abfd, ext, in)
189f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
190f7cc78ecSespie      PTR ext ATTRIBUTE_UNUSED;
191f7cc78ecSespie      PTR in;
192f7cc78ecSespie {
193f7cc78ecSespie   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
194f7cc78ecSespie 
195f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_scnptr, STUBSIZE);
196f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_relptr, STUBSIZE);
197f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_lnnoptr, STUBSIZE);
198f7cc78ecSespie }
199f7cc78ecSespie 
200f7cc78ecSespie static void
adjust_scnhdr_out_pre(abfd,in,out)201f7cc78ecSespie adjust_scnhdr_out_pre  (abfd, in, out)
202f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
203f7cc78ecSespie      PTR in;
204f7cc78ecSespie      PTR out ATTRIBUTE_UNUSED;
205f7cc78ecSespie {
206f7cc78ecSespie   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
207f7cc78ecSespie 
208f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_scnptr, -STUBSIZE);
209f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_relptr, -STUBSIZE);
210f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_lnnoptr, -STUBSIZE);
211f7cc78ecSespie }
212f7cc78ecSespie 
213f7cc78ecSespie static void
adjust_scnhdr_out_post(abfd,in,out)214f7cc78ecSespie adjust_scnhdr_out_post (abfd, in, out)
215f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
216f7cc78ecSespie      PTR in;
217f7cc78ecSespie      PTR out ATTRIBUTE_UNUSED;
218f7cc78ecSespie {
219f7cc78ecSespie   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
220f7cc78ecSespie 
221f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_scnptr, STUBSIZE);
222f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_relptr, STUBSIZE);
223f7cc78ecSespie   ADJUST_VAL (scnhdr_int->s_lnnoptr, STUBSIZE);
224f7cc78ecSespie }
225f7cc78ecSespie 
226f7cc78ecSespie static void
adjust_aux_in_post(abfd,ext1,type,class,indx,numaux,in1)227f7cc78ecSespie adjust_aux_in_post  (abfd, ext1, type, class, indx, numaux, in1)
228f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
229f7cc78ecSespie      PTR ext1 ATTRIBUTE_UNUSED;
230f7cc78ecSespie      int type;
231f7cc78ecSespie      int class;
232f7cc78ecSespie      int indx ATTRIBUTE_UNUSED;
233f7cc78ecSespie      int numaux ATTRIBUTE_UNUSED;
234f7cc78ecSespie      PTR in1;
235f7cc78ecSespie {
236f7cc78ecSespie   union internal_auxent *in = (union internal_auxent *) in1;
237f7cc78ecSespie 
238f7cc78ecSespie   if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
239f7cc78ecSespie     {
240f7cc78ecSespie       ADJUST_VAL (in->x_sym.x_fcnary.x_fcn.x_lnnoptr, STUBSIZE);
241f7cc78ecSespie     }
242f7cc78ecSespie }
243f7cc78ecSespie 
244f7cc78ecSespie static void
adjust_aux_out_pre(abfd,inp,type,class,indx,numaux,extp)245f7cc78ecSespie adjust_aux_out_pre  (abfd, inp, type, class, indx, numaux, extp)
246f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
247f7cc78ecSespie      PTR inp;
248f7cc78ecSespie      int type;
249f7cc78ecSespie      int class;
250f7cc78ecSespie      int indx ATTRIBUTE_UNUSED;
251f7cc78ecSespie      int numaux ATTRIBUTE_UNUSED;
252f7cc78ecSespie      PTR extp ATTRIBUTE_UNUSED;
253f7cc78ecSespie {
254f7cc78ecSespie   union internal_auxent *in = (union internal_auxent *) inp;
255f7cc78ecSespie 
256f7cc78ecSespie   if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
257f7cc78ecSespie     {
258f7cc78ecSespie       ADJUST_VAL (in->x_sym.x_fcnary.x_fcn.x_lnnoptr, -STUBSIZE);
259f7cc78ecSespie     }
260f7cc78ecSespie }
261f7cc78ecSespie 
262f7cc78ecSespie static void
adjust_aux_out_post(abfd,inp,type,class,indx,numaux,extp)263f7cc78ecSespie adjust_aux_out_post (abfd, inp, type, class, indx, numaux, extp)
264f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
265f7cc78ecSespie      PTR inp;
266f7cc78ecSespie      int type;
267f7cc78ecSespie      int class;
268f7cc78ecSespie      int indx ATTRIBUTE_UNUSED;
269f7cc78ecSespie      int numaux ATTRIBUTE_UNUSED;
270f7cc78ecSespie      PTR extp ATTRIBUTE_UNUSED;
271f7cc78ecSespie {
272f7cc78ecSespie   union internal_auxent *in = (union internal_auxent *) inp;
273f7cc78ecSespie 
274f7cc78ecSespie   if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
275f7cc78ecSespie     {
276f7cc78ecSespie       ADJUST_VAL (in->x_sym.x_fcnary.x_fcn.x_lnnoptr, STUBSIZE);
277f7cc78ecSespie     }
278f7cc78ecSespie }
279f7cc78ecSespie 
280*d2201f2fSdrahn /* That's the function, which creates the stub. There are
281f7cc78ecSespie    different cases from where the stub is taken.
282f7cc78ecSespie    At first the environment variable $(GO32STUB) is checked and then
283f7cc78ecSespie    $(STUB) if it was not set.
284f7cc78ecSespie    If it exists and points to a valid stub the stub is taken from
285f7cc78ecSespie    that file. This file can be also a whole executable file, because
286f7cc78ecSespie    the stub is computed from the exe information at the start of that
287f7cc78ecSespie    file.
288f7cc78ecSespie 
289f7cc78ecSespie    If there was any error, the standard stub (compiled in this file)
290*d2201f2fSdrahn    is taken.  */
291f7cc78ecSespie 
292f7cc78ecSespie static void
create_go32_stub(abfd)293f7cc78ecSespie create_go32_stub (abfd)
294f7cc78ecSespie      bfd *abfd;
295f7cc78ecSespie {
296*d2201f2fSdrahn   /* Do it only once.  */
297f7cc78ecSespie   if (bfd_coff_go32stub (abfd) == NULL)
298f7cc78ecSespie     {
299f7cc78ecSespie       char *stub;
300f7cc78ecSespie       struct stat st;
301f7cc78ecSespie       int f;
302f7cc78ecSespie       unsigned char header[10];
303f7cc78ecSespie       char magic[8];
304*d2201f2fSdrahn       unsigned long coff_start;
305*d2201f2fSdrahn       long exe_start;
306f7cc78ecSespie 
307*d2201f2fSdrahn       /* Check at first the environment variable $(GO32STUB).  */
308f7cc78ecSespie       stub = getenv ("GO32STUB");
309*d2201f2fSdrahn       /* Now check the environment variable $(STUB).  */
310f7cc78ecSespie       if (stub == NULL)
311f7cc78ecSespie 	stub = getenv ("STUB");
312f7cc78ecSespie       if (stub == NULL)
313f7cc78ecSespie 	goto stub_end;
314f7cc78ecSespie       if (stat (stub, &st) != 0)
315f7cc78ecSespie 	goto stub_end;
316f7cc78ecSespie #ifdef O_BINARY
317f7cc78ecSespie       f = open (stub, O_RDONLY | O_BINARY);
318f7cc78ecSespie #else
319f7cc78ecSespie       f = open (stub, O_RDONLY);
320f7cc78ecSespie #endif
321f7cc78ecSespie       if (f < 0)
322f7cc78ecSespie 	goto stub_end;
323f7cc78ecSespie       if (read (f, &header, sizeof (header)) < 0)
324f7cc78ecSespie 	{
325f7cc78ecSespie 	  close (f);
326f7cc78ecSespie 	  goto stub_end;
327f7cc78ecSespie 	}
328*d2201f2fSdrahn       if (_H (0) != 0x5a4d)	/* It is not an exe file.  */
329f7cc78ecSespie 	{
330f7cc78ecSespie 	  close (f);
331f7cc78ecSespie 	  goto stub_end;
332f7cc78ecSespie 	}
333f7cc78ecSespie       /* Compute the size of the stub (it is every thing up
334*d2201f2fSdrahn          to the beginning of the coff image).  */
335f7cc78ecSespie       coff_start = (long) _H (2) * 512L;
336f7cc78ecSespie       if (_H (1))
337f7cc78ecSespie 	coff_start += (long) _H (1) - 512L;
338f7cc78ecSespie 
339f7cc78ecSespie       /* Currently there is only a fixed stub size of 2048 bytes
340*d2201f2fSdrahn          supported.  */
341f7cc78ecSespie       if (coff_start != 2048)
342f7cc78ecSespie 	{
343f7cc78ecSespie 	  close (f);
344f7cc78ecSespie 	  goto stub_end;
345f7cc78ecSespie 	}
346f7cc78ecSespie       exe_start = _H (4) * 16;
347*d2201f2fSdrahn       if ((long) lseek (f, exe_start, SEEK_SET) != exe_start)
348f7cc78ecSespie 	{
349f7cc78ecSespie 	  close (f);
350f7cc78ecSespie 	  goto stub_end;
351f7cc78ecSespie 	}
352f7cc78ecSespie       if (read (f, &magic, 8) != 8)
353f7cc78ecSespie 	{
354f7cc78ecSespie 	  close (f);
355f7cc78ecSespie 	  goto stub_end;
356f7cc78ecSespie 	}
357f7cc78ecSespie       if (memcmp (magic, "go32stub", 8) != 0)
358f7cc78ecSespie 	{
359f7cc78ecSespie 	  close (f);
360f7cc78ecSespie 	  goto stub_end;
361f7cc78ecSespie 	}
362*d2201f2fSdrahn       /* Now we found a correct stub (hopefully).  */
363*d2201f2fSdrahn       bfd_coff_go32stub (abfd)
364*d2201f2fSdrahn 	= (PTR) bfd_alloc (abfd, (bfd_size_type) coff_start);
365f7cc78ecSespie       if (bfd_coff_go32stub (abfd) == NULL)
366f7cc78ecSespie 	{
367f7cc78ecSespie 	  close (f);
368f7cc78ecSespie 	  return;
369f7cc78ecSespie 	}
370f7cc78ecSespie       lseek (f, 0L, SEEK_SET);
371f7cc78ecSespie       if ((unsigned long) read (f, bfd_coff_go32stub (abfd), coff_start)
372f7cc78ecSespie 	  != coff_start)
373f7cc78ecSespie 	{
374f7cc78ecSespie 	  bfd_release (abfd, bfd_coff_go32stub (abfd));
375f7cc78ecSespie 	  bfd_coff_go32stub (abfd) = NULL;
376f7cc78ecSespie 	}
377f7cc78ecSespie       close (f);
378f7cc78ecSespie     }
379f7cc78ecSespie stub_end:
380f7cc78ecSespie   /* There was something wrong above, so use now the standard builtin
381*d2201f2fSdrahn      stub.  */
382f7cc78ecSespie   if (bfd_coff_go32stub (abfd) == NULL)
383f7cc78ecSespie     {
384*d2201f2fSdrahn       bfd_coff_go32stub (abfd)
385*d2201f2fSdrahn 	= (PTR) bfd_alloc (abfd, (bfd_size_type) STUBSIZE);
386f7cc78ecSespie       if (bfd_coff_go32stub (abfd) == NULL)
387f7cc78ecSespie 	return;
388f7cc78ecSespie       memcpy (bfd_coff_go32stub (abfd), stub_bytes, STUBSIZE);
389f7cc78ecSespie     }
390f7cc78ecSespie }
391f7cc78ecSespie 
392f7cc78ecSespie /* If ibfd was a stubbed coff image, copy the stub from that bfd
393*d2201f2fSdrahn    to the new obfd.  */
394f7cc78ecSespie 
395*d2201f2fSdrahn static bfd_boolean
go32_stubbed_coff_bfd_copy_private_bfd_data(ibfd,obfd)396f7cc78ecSespie go32_stubbed_coff_bfd_copy_private_bfd_data  (ibfd, obfd)
397f7cc78ecSespie      bfd *ibfd;
398f7cc78ecSespie      bfd *obfd;
399f7cc78ecSespie {
400*d2201f2fSdrahn   /* Check if both are the same targets.  */
401f7cc78ecSespie   if (ibfd->xvec != obfd->xvec)
402*d2201f2fSdrahn     return TRUE;
403f7cc78ecSespie 
404*d2201f2fSdrahn   /* Check if both have a valid stub.  */
405f7cc78ecSespie   if (bfd_coff_go32stub (ibfd) == NULL
406f7cc78ecSespie       || bfd_coff_go32stub (obfd) == NULL)
407*d2201f2fSdrahn     return TRUE;
408f7cc78ecSespie 
409*d2201f2fSdrahn   /* Now copy the stub.  */
410f7cc78ecSespie   memcpy (bfd_coff_go32stub (obfd), bfd_coff_go32stub (ibfd), STUBSIZE);
411f7cc78ecSespie 
412*d2201f2fSdrahn   return TRUE;
413f7cc78ecSespie }
414