packaging: Add python3-base dependency
[platform/upstream/gdb.git] / bfd / coff-stgo32.c
1 /* BFD back-end for Intel 386 COFF files (DJGPP variant with a stub).
2    Copyright (C) 1997-2022 Free Software Foundation, Inc.
3    Written by Robert Hoehne.
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22 /* This file handles now also stubbed coff images. The stub is a small
23    DOS executable program before the coff image to load it in memory
24    and execute it. This is needed, because DOS cannot run coff files.
25
26    The COFF image is loaded in memory without the stub attached, so
27    all offsets are relative to the beginning of the image, not the
28    actual file.  We handle this in bfd by setting bfd->origin to where
29    the COFF image starts.  */
30
31 #define TARGET_SYM              i386_coff_go32stubbed_vec
32 #define TARGET_NAME             "coff-go32-exe"
33 #define TARGET_UNDERSCORE       '_'
34 #define COFF_GO32_EXE
35 #define COFF_LONG_SECTION_NAMES
36 #define COFF_SUPPORT_GNU_LINKONCE
37 #define COFF_LONG_FILENAMES
38
39 #define COFF_SECTION_ALIGNMENT_ENTRIES \
40 { COFF_SECTION_NAME_EXACT_MATCH (".data"), \
41   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
42 { COFF_SECTION_NAME_EXACT_MATCH (".text"), \
43   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
44 { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
45   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
46 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi"), \
47   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
48
49 /* Section contains extended relocations. */
50 #define IMAGE_SCN_LNK_NRELOC_OVFL (0x01000000)
51
52 #include "sysdep.h"
53 #include "bfd.h"
54 #include "coff/msdos.h"
55
56 static bfd_cleanup go32exe_check_format (bfd *);
57 static bool go32exe_write_object_contents (bfd *);
58 static bool go32exe_mkobject (bfd *);
59 static bool go32exe_copy_private_bfd_data (bfd *, bfd *);
60
61 /* Defined in coff-go32.c.  */
62 bool _bfd_go32_mkobject (bfd *);
63 void _bfd_go32_swap_scnhdr_in (bfd *, void *, void *);
64 unsigned int _bfd_go32_swap_scnhdr_out (bfd *, void *, void *);
65
66 #define COFF_CHECK_FORMAT go32exe_check_format
67 #define COFF_WRITE_CONTENTS go32exe_write_object_contents
68 #define coff_mkobject go32exe_mkobject
69 #define coff_bfd_copy_private_bfd_data go32exe_copy_private_bfd_data
70 #define coff_SWAP_scnhdr_in _bfd_go32_swap_scnhdr_in
71 #define coff_SWAP_scnhdr_out _bfd_go32_swap_scnhdr_out
72
73 #include "coff-i386.c"
74
75 /* This macro is used, because I cannot assume the endianness of the
76    host system.  */
77 #define _H(index) (H_GET_16 (abfd, (header + index * 2)))
78
79 /* These bytes are a 2048-byte DOS executable, which loads the COFF
80    image into memory and then runs it. It is called 'stub'.  */
81 #define GO32EXE_DEFAULT_STUB_SIZE 2048
82 static const unsigned char go32exe_default_stub[GO32EXE_DEFAULT_STUB_SIZE] =
83 {
84 #include "go32stub.h"
85 };
86
87 /* Temporary location for stub read from input file.  */
88 static char * go32exe_temp_stub = NULL;
89 static bfd_size_type go32exe_temp_stub_size = 0;
90
91 /* That's the function, which creates the stub. There are
92    different cases from where the stub is taken.
93    At first the environment variable $(GO32STUB) is checked and then
94    $(STUB) if it was not set.
95    If it exists and points to a valid stub the stub is taken from
96    that file. This file can be also a whole executable file, because
97    the stub is computed from the exe information at the start of that
98    file.
99
100    If there was any error, the standard stub (compiled in this file)
101    is taken.
102
103    Ideally this function should exec '$(TARGET)-stubify' to generate
104    a stub, like gcc does.  */
105
106 static void
107 go32exe_create_stub (bfd *abfd)
108 {
109   /* Do it only once.  */
110   if (coff_data (abfd)->stub == NULL)
111     {
112       char *stub;
113       struct stat st;
114       int f;
115       unsigned char header[10];
116       char magic[8];
117       unsigned long coff_start;
118       long exe_start;
119
120       /* If we read a stub from an input file, use that one.  */
121       if (go32exe_temp_stub != NULL)
122         {
123           coff_data (abfd)->stub = bfd_alloc (abfd,
124                                                   go32exe_temp_stub_size);
125           if (coff_data (abfd)->stub == NULL)
126             return;
127           memcpy (coff_data (abfd)->stub, go32exe_temp_stub,
128                   go32exe_temp_stub_size);
129           coff_data (abfd)->stub_size = go32exe_temp_stub_size;
130           free (go32exe_temp_stub);
131           go32exe_temp_stub = NULL;
132           go32exe_temp_stub_size = 0;
133           return;
134         }
135
136       /* Check at first the environment variable $(GO32STUB).  */
137       stub = getenv ("GO32STUB");
138       /* Now check the environment variable $(STUB).  */
139       if (stub == NULL)
140         stub = getenv ("STUB");
141       if (stub == NULL)
142         goto stub_end;
143       if (stat (stub, &st) != 0)
144         goto stub_end;
145 #ifdef O_BINARY
146       f = open (stub, O_RDONLY | O_BINARY);
147 #else
148       f = open (stub, O_RDONLY);
149 #endif
150       if (f < 0)
151         goto stub_end;
152       if (read (f, &header, sizeof (header)) < 0)
153         {
154           close (f);
155           goto stub_end;
156         }
157       if (_H (0) != 0x5a4d)     /* It is not an exe file.  */
158         {
159           close (f);
160           goto stub_end;
161         }
162       /* Compute the size of the stub (it is every thing up
163          to the beginning of the coff image).  */
164       coff_start = (long) _H (2) * 512L;
165       if (_H (1))
166         coff_start += (long) _H (1) - 512L;
167
168       exe_start = _H (4) * 16;
169       if ((long) lseek (f, exe_start, SEEK_SET) != exe_start)
170         {
171           close (f);
172           goto stub_end;
173         }
174       if (read (f, &magic, 8) != 8)
175         {
176           close (f);
177           goto stub_end;
178         }
179       if (! startswith (magic, "go32stub"))
180         {
181           close (f);
182           goto stub_end;
183         }
184       /* Now we found a correct stub (hopefully).  */
185       coff_data (abfd)->stub = bfd_alloc (abfd, (bfd_size_type) coff_start);
186       if (coff_data (abfd)->stub == NULL)
187         {
188           close (f);
189           return;
190         }
191       lseek (f, 0L, SEEK_SET);
192       if ((unsigned long) read (f, coff_data (abfd)->stub, coff_start)
193           != coff_start)
194         {
195           bfd_release (abfd, coff_data (abfd)->stub);
196           coff_data (abfd)->stub = NULL;
197         }
198       else
199         coff_data (abfd)->stub_size = coff_start;
200       close (f);
201     }
202  stub_end:
203   /* There was something wrong above, so use now the standard builtin
204      stub.  */
205   if (coff_data (abfd)->stub == NULL)
206     {
207       coff_data (abfd)->stub
208         = bfd_alloc (abfd, (bfd_size_type) GO32EXE_DEFAULT_STUB_SIZE);
209       if (coff_data (abfd)->stub == NULL)
210         return;
211       memcpy (coff_data (abfd)->stub, go32exe_default_stub,
212               GO32EXE_DEFAULT_STUB_SIZE);
213       coff_data (abfd)->stub_size = GO32EXE_DEFAULT_STUB_SIZE;
214     }
215 }
216
217 /* If ibfd was a stubbed coff image, copy the stub from that bfd
218    to the new obfd.  */
219
220 static bool
221 go32exe_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
222 {
223   /* Check if both are the same targets.  */
224   if (ibfd->xvec != obfd->xvec)
225     return true;
226
227   /* Make sure we have a source stub.  */
228   BFD_ASSERT (coff_data (ibfd)->stub != NULL);
229
230   /* Reallocate the output stub if necessary.  */
231   if (coff_data (ibfd)->stub_size > coff_data (obfd)->stub_size)
232     coff_data (obfd)->stub = bfd_alloc (obfd, coff_data (ibfd)->stub_size);
233   if (coff_data (obfd)->stub == NULL)
234     return false;
235
236   /* Now copy the stub.  */
237   memcpy (coff_data (obfd)->stub, coff_data (ibfd)->stub,
238           coff_data (ibfd)->stub_size);
239   coff_data (obfd)->stub_size = coff_data (ibfd)->stub_size;
240   obfd->origin = coff_data (obfd)->stub_size;
241
242   return true;
243 }
244
245 /* Cleanup function, returned from check_format hook.  */
246
247 static void
248 go32exe_cleanup (bfd *abfd)
249 {
250   abfd->origin = 0;
251
252   free (go32exe_temp_stub);
253   go32exe_temp_stub = NULL;
254   go32exe_temp_stub_size = 0;
255 }
256
257 /* Check that there is a GO32 stub and read it to go32exe_temp_stub.
258    Then set abfd->origin so that the COFF image is read at the correct
259    file offset.  */
260
261 static bfd_cleanup
262 go32exe_check_format (bfd *abfd)
263 {
264   struct external_DOS_hdr filehdr_dos;
265   uint16_t num_pages;
266   uint16_t last_page_size;
267   uint32_t header_end;
268   bfd_size_type stubsize;
269
270   /* This format can not appear in an archive.  */
271   if (abfd->origin != 0)
272     {
273       bfd_set_error (bfd_error_wrong_format);
274       return NULL;
275     }
276
277   bfd_set_error (bfd_error_system_call);
278
279   /* Read in the stub file header, which is a DOS MZ executable.  */
280   if (bfd_bread (&filehdr_dos, DOS_HDR_SIZE, abfd) != DOS_HDR_SIZE)
281     goto fail;
282
283   /* Make sure that this is an MZ executable.  */
284   if (H_GET_16 (abfd, filehdr_dos.e_magic) != IMAGE_DOS_SIGNATURE)
285     goto fail_format;
286
287   /* Determine the size of the stub  */
288   num_pages = H_GET_16 (abfd, filehdr_dos.e_cp);
289   last_page_size = H_GET_16 (abfd, filehdr_dos.e_cblp);
290   stubsize = num_pages * 512;
291   if (last_page_size != 0)
292     stubsize += last_page_size - 512;
293
294   ufile_ptr filesize = bfd_get_file_size (abfd);
295   if (filesize != 0 && stubsize > filesize)
296     goto fail_format;
297
298   /* Save now the stub to be used later.  Put the stub data to a temporary
299      location first as tdata still does not exist.  It may not even
300      be ever created if we are just checking the file format of ABFD.  */
301   bfd_seek (abfd, 0, SEEK_SET);
302   go32exe_temp_stub = bfd_malloc (stubsize);
303   if (go32exe_temp_stub == NULL)
304     goto fail;
305   if (bfd_bread (go32exe_temp_stub, stubsize, abfd) != stubsize)
306     goto fail;
307   go32exe_temp_stub_size = stubsize;
308
309   /* Confirm that this is a go32stub.  */
310   header_end = H_GET_16 (abfd, filehdr_dos.e_cparhdr) * 16UL;
311   if (go32exe_temp_stub_size < header_end
312       || go32exe_temp_stub_size - header_end < sizeof "go32stub" - 1
313       || !startswith (go32exe_temp_stub + header_end, "go32stub"))
314     goto fail_format;
315
316   /* Set origin to where the COFF header starts and seek there.  */
317   abfd->origin = stubsize;
318   if (bfd_seek (abfd, 0, SEEK_SET) != 0)
319     goto fail;
320
321   /* Call coff_object_p to read the COFF image.  If this fails then the file
322      must be just a stub with no COFF data attached.  */
323   bfd_cleanup cleanup = coff_object_p (abfd);
324   if (cleanup == NULL)
325     goto fail;
326   BFD_ASSERT (cleanup == _bfd_no_cleanup);
327
328   return go32exe_cleanup;
329
330  fail_format:
331   bfd_set_error (bfd_error_wrong_format);
332  fail:
333   go32exe_cleanup (abfd);
334   return NULL;
335 }
336
337 /* Write the stub to the output file, then call coff_write_object_contents.  */
338
339 static bool
340 go32exe_write_object_contents (bfd *abfd)
341 {
342   const bfd_size_type pos = bfd_tell (abfd);
343   const bfd_size_type stubsize = coff_data (abfd)->stub_size;
344
345   BFD_ASSERT (stubsize != 0);
346
347   bfd_set_error (bfd_error_system_call);
348
349   /* Write the stub.  */
350   abfd->origin = 0;
351   if (bfd_seek (abfd, 0, SEEK_SET) != 0)
352     return false;
353   if (bfd_bwrite (coff_data (abfd)->stub, stubsize, abfd) != stubsize)
354     return false;
355
356   /* Seek back to where we were.  */
357   abfd->origin = stubsize;
358   if (bfd_seek (abfd, pos, SEEK_SET) != 0)
359     return false;
360
361   return coff_write_object_contents (abfd);
362 }
363
364 /* mkobject hook.  Called directly through bfd_set_format or via
365    coff_mkobject_hook etc from bfd_check_format.  */
366
367 static bool
368 go32exe_mkobject (bfd *abfd)
369 {
370   /* Don't output to an archive.  */
371   if (abfd->my_archive != NULL)
372     return false;
373
374   if (!_bfd_go32_mkobject (abfd))
375     return false;
376
377   go32exe_create_stub (abfd);
378   if (coff_data (abfd)->stub == NULL)
379     {
380       bfd_release (abfd, coff_data (abfd));
381       return false;
382     }
383   abfd->origin = coff_data (abfd)->stub_size;
384
385   return true;
386 }