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