1 |
/* BFD back-end for Intel 386 COFF files (DJGPP variant with a stub). |
/* BFD back-end for Intel 386 COFF files (DJGPP variant with a stub). |
2 |
Copyright 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. |
3 |
Written by Robert Hoehne. |
Written by Robert Hoehne. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
32 |
image and NOT in the file. |
image and NOT in the file. |
33 |
|
|
34 |
To be compatible with any existing executables I have fixed this |
To be compatible with any existing executables I have fixed this |
35 |
here and NOT in the DJGPP startup code. |
here and NOT in the DJGPP startup code. */ |
|
*/ |
|
36 |
|
|
37 |
#define TARGET_SYM go32stubbedcoff_vec |
#define TARGET_SYM go32stubbedcoff_vec |
38 |
#define TARGET_NAME "coff-go32-exe" |
#define TARGET_NAME "coff-go32-exe" |
54 |
|
|
55 |
#include "bfd.h" |
#include "bfd.h" |
56 |
|
|
57 |
/* At first the prototypes */ |
/* At first the prototypes. */ |
58 |
|
|
59 |
static void |
static void |
60 |
adjust_filehdr_in_post PARAMS ((bfd * abfd, PTR src, PTR dst)); |
adjust_filehdr_in_post PARAMS ((bfd *, PTR, PTR)); |
61 |
static void |
static void |
62 |
adjust_filehdr_out_pre PARAMS ((bfd * abfd, PTR in, PTR out)); |
adjust_filehdr_out_pre PARAMS ((bfd *, PTR, PTR)); |
63 |
static void |
static void |
64 |
adjust_filehdr_out_post PARAMS ((bfd * abfd, PTR in, PTR out)); |
adjust_filehdr_out_post PARAMS ((bfd *, PTR, PTR)); |
|
|
|
65 |
static void |
static void |
66 |
adjust_scnhdr_in_post PARAMS ((bfd * abfd, PTR ext, PTR in)); |
adjust_scnhdr_in_post PARAMS ((bfd *, PTR, PTR)); |
67 |
static void |
static void |
68 |
adjust_scnhdr_out_pre PARAMS ((bfd * abfd, PTR in, PTR out)); |
adjust_scnhdr_out_pre PARAMS ((bfd *, PTR, PTR)); |
69 |
static void |
static void |
70 |
adjust_scnhdr_out_post PARAMS ((bfd * abfd, PTR in, PTR out)); |
adjust_scnhdr_out_post PARAMS ((bfd *, PTR, PTR)); |
|
|
|
71 |
static void |
static void |
72 |
adjust_aux_in_post PARAMS ((bfd * abfd, PTR ext1, int type, int class, int indx, |
adjust_aux_in_post PARAMS ((bfd *, PTR, int, int, int, int, PTR)); |
|
int numaux, PTR in1)); |
|
73 |
static void |
static void |
74 |
adjust_aux_out_pre PARAMS ((bfd * abfd, PTR inp, int type, int class, int indx, |
adjust_aux_out_pre PARAMS ((bfd *, PTR, int, int, int, int, PTR)); |
|
int numaux, PTR extp)); |
|
75 |
static void |
static void |
76 |
adjust_aux_out_post PARAMS ((bfd * abfd, PTR inp, int type, int class, int indx, |
adjust_aux_out_post PARAMS ((bfd *, PTR, int, int, int, int, PTR)); |
|
int numaux, PTR extp)); |
|
|
|
|
77 |
static void |
static void |
78 |
create_go32_stub PARAMS ((bfd * abfd)); |
create_go32_stub PARAMS ((bfd *)); |
79 |
|
|
80 |
/* |
/* All that ..._PRE and ...POST functions are called from the corresponding |
|
All that ..._PRE and ...POST functions are called from the corresponding |
|
81 |
coff_swap... functions. The ...PRE functions are called at the beginning |
coff_swap... functions. The ...PRE functions are called at the beginning |
82 |
of the function and the ...POST functions at the end of the swap routines. |
of the function and the ...POST functions at the end of the swap routines. */ |
|
*/ |
|
83 |
|
|
84 |
#define COFF_ADJUST_FILEHDR_IN_POST adjust_filehdr_in_post |
#define COFF_ADJUST_FILEHDR_IN_POST adjust_filehdr_in_post |
85 |
#define COFF_ADJUST_FILEHDR_OUT_PRE adjust_filehdr_out_pre |
#define COFF_ADJUST_FILEHDR_OUT_PRE adjust_filehdr_out_pre |
93 |
#define COFF_ADJUST_AUX_OUT_PRE adjust_aux_out_pre |
#define COFF_ADJUST_AUX_OUT_PRE adjust_aux_out_pre |
94 |
#define COFF_ADJUST_AUX_OUT_POST adjust_aux_out_post |
#define COFF_ADJUST_AUX_OUT_POST adjust_aux_out_post |
95 |
|
|
96 |
static boolean |
static bfd_boolean |
97 |
go32_stubbed_coff_bfd_copy_private_bfd_data PARAMS ((bfd * ibfd, bfd * obfd)); |
go32_stubbed_coff_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *)); |
98 |
|
|
99 |
#define coff_bfd_copy_private_bfd_data go32_stubbed_coff_bfd_copy_private_bfd_data |
#define coff_bfd_copy_private_bfd_data go32_stubbed_coff_bfd_copy_private_bfd_data |
100 |
|
|
101 |
#include "coff-i386.c" |
#include "coff-i386.c" |
102 |
|
|
103 |
/* I hold in the usrdata the stub */ |
/* I hold in the usrdata the stub. */ |
104 |
#define bfd_coff_go32stub bfd_usrdata |
#define bfd_coff_go32stub bfd_usrdata |
105 |
|
|
106 |
/* This macro is used, because I cannot assume the endianess of the |
/* This macro is used, because I cannot assume the endianess of the |
107 |
host system */ |
host system. */ |
108 |
#define _H(index) (H_GET_16 (abfd, (header+index*2))) |
#define _H(index) (H_GET_16 (abfd, (header+index*2))) |
109 |
|
|
110 |
/* These bytes are a 2048-byte DOS executable, which loads the COFF |
/* These bytes are a 2048-byte DOS executable, which loads the COFF |
111 |
image into memory and then runs it. It is called 'stub' */ |
image into memory and then runs it. It is called 'stub'. */ |
112 |
|
|
113 |
static unsigned char stub_bytes[STUBSIZE] = |
static const unsigned char stub_bytes[STUBSIZE] = |
114 |
{ |
{ |
115 |
#include "go32stub.h" |
#include "go32stub.h" |
116 |
}; |
}; |
120 |
technique is in any function the same. For the ...in function, |
technique is in any function the same. For the ...in function, |
121 |
all the pointers are adjusted by adding STUBSIZE and for the |
all the pointers are adjusted by adding STUBSIZE and for the |
122 |
...out function, it is subtracted first and after calling the |
...out function, it is subtracted first and after calling the |
123 |
standard swap function it is reset to the old value */ |
standard swap function it is reset to the old value. */ |
124 |
|
|
125 |
/* This macro is used for adjusting the filepointers, which |
/* This macro is used for adjusting the filepointers, which |
126 |
is done only, if the pointer is nonzero */ |
is done only, if the pointer is nonzero. */ |
127 |
|
|
128 |
#define ADJUST_VAL(val,diff) \ |
#define ADJUST_VAL(val,diff) \ |
129 |
if (val != 0) val += diff |
if (val != 0) val += diff |
139 |
|
|
140 |
ADJUST_VAL (filehdr_dst->f_symptr, STUBSIZE); |
ADJUST_VAL (filehdr_dst->f_symptr, STUBSIZE); |
141 |
|
|
142 |
/* Save now the stub to be used later */ |
/* Save now the stub to be used later. */ |
143 |
bfd_coff_go32stub (abfd) = (PTR) bfd_alloc (abfd, (bfd_size_type) STUBSIZE); |
bfd_coff_go32stub (abfd) = (PTR) bfd_alloc (abfd, (bfd_size_type) STUBSIZE); |
144 |
|
|
145 |
/* Since this function returns no status, I do not set here |
/* Since this function returns no status, I do not set here |
146 |
any bfd_error_... |
any bfd_error_... |
147 |
That means, before the use of bfd_coff_go32stub (), this value |
That means, before the use of bfd_coff_go32stub (), this value |
148 |
should be checked if it is != NULL */ |
should be checked if it is != NULL. */ |
149 |
if (bfd_coff_go32stub (abfd) == NULL) |
if (bfd_coff_go32stub (abfd) == NULL) |
150 |
return; |
return; |
151 |
memcpy (bfd_coff_go32stub (abfd), filehdr_src->stub, STUBSIZE); |
memcpy (bfd_coff_go32stub (abfd), filehdr_src->stub, STUBSIZE); |
160 |
struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; |
struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; |
161 |
FILHDR *filehdr_out = (FILHDR *) out; |
FILHDR *filehdr_out = (FILHDR *) out; |
162 |
|
|
163 |
/* Generate the stub */ |
/* Generate the stub. */ |
164 |
create_go32_stub (abfd); |
create_go32_stub (abfd); |
165 |
|
|
166 |
/* Copy the stub to the file header */ |
/* Copy the stub to the file header. */ |
167 |
if (bfd_coff_go32stub (abfd) != NULL) |
if (bfd_coff_go32stub (abfd) != NULL) |
168 |
memcpy (filehdr_out->stub, bfd_coff_go32stub (abfd), STUBSIZE); |
memcpy (filehdr_out->stub, bfd_coff_go32stub (abfd), STUBSIZE); |
169 |
else |
else |
170 |
/* use the default */ |
/* Use the default. */ |
171 |
memcpy (filehdr_out->stub, stub_bytes, STUBSIZE); |
memcpy (filehdr_out->stub, stub_bytes, STUBSIZE); |
172 |
|
|
173 |
ADJUST_VAL (filehdr_in->f_symptr, -STUBSIZE); |
ADJUST_VAL (filehdr_in->f_symptr, -STUBSIZE); |
180 |
PTR out ATTRIBUTE_UNUSED; |
PTR out ATTRIBUTE_UNUSED; |
181 |
{ |
{ |
182 |
struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; |
struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; |
183 |
/* undo the above change */ |
/* Undo the above change. */ |
184 |
ADJUST_VAL (filehdr_in->f_symptr, STUBSIZE); |
ADJUST_VAL (filehdr_in->f_symptr, STUBSIZE); |
185 |
} |
} |
186 |
|
|
277 |
} |
} |
278 |
} |
} |
279 |
|
|
280 |
/* |
/* That's the function, which creates the stub. There are |
|
That's the function, which creates the stub. There are |
|
281 |
different cases from where the stub is taken. |
different cases from where the stub is taken. |
282 |
At first the environment variable $(GO32STUB) is checked and then |
At first the environment variable $(GO32STUB) is checked and then |
283 |
$(STUB) if it was not set. |
$(STUB) if it was not set. |
287 |
file. |
file. |
288 |
|
|
289 |
If there was any error, the standard stub (compiled in this file) |
If there was any error, the standard stub (compiled in this file) |
290 |
is taken. |
is taken. */ |
|
*/ |
|
291 |
|
|
292 |
static void |
static void |
293 |
create_go32_stub (abfd) |
create_go32_stub (abfd) |
294 |
bfd *abfd; |
bfd *abfd; |
295 |
{ |
{ |
296 |
/* Do it only once */ |
/* Do it only once. */ |
297 |
if (bfd_coff_go32stub (abfd) == NULL) |
if (bfd_coff_go32stub (abfd) == NULL) |
298 |
{ |
{ |
299 |
char *stub; |
char *stub; |
304 |
unsigned long coff_start; |
unsigned long coff_start; |
305 |
long exe_start; |
long exe_start; |
306 |
|
|
307 |
/* Check at first the environment variable $(GO32STUB) */ |
/* Check at first the environment variable $(GO32STUB). */ |
308 |
stub = getenv ("GO32STUB"); |
stub = getenv ("GO32STUB"); |
309 |
/* Now check the environment variable $(STUB) */ |
/* Now check the environment variable $(STUB). */ |
310 |
if (stub == NULL) |
if (stub == NULL) |
311 |
stub = getenv ("STUB"); |
stub = getenv ("STUB"); |
312 |
if (stub == NULL) |
if (stub == NULL) |
325 |
close (f); |
close (f); |
326 |
goto stub_end; |
goto stub_end; |
327 |
} |
} |
328 |
if (_H (0) != 0x5a4d) /* it is not an exe file */ |
if (_H (0) != 0x5a4d) /* It is not an exe file. */ |
329 |
{ |
{ |
330 |
close (f); |
close (f); |
331 |
goto stub_end; |
goto stub_end; |
332 |
} |
} |
333 |
/* Compute the size of the stub (it is every thing up |
/* Compute the size of the stub (it is every thing up |
334 |
to the beginning of the coff image) */ |
to the beginning of the coff image). */ |
335 |
coff_start = (long) _H (2) * 512L; |
coff_start = (long) _H (2) * 512L; |
336 |
if (_H (1)) |
if (_H (1)) |
337 |
coff_start += (long) _H (1) - 512L; |
coff_start += (long) _H (1) - 512L; |
338 |
|
|
339 |
/* Currently there is only a fixed stub size of 2048 bytes |
/* Currently there is only a fixed stub size of 2048 bytes |
340 |
supported */ |
supported. */ |
341 |
if (coff_start != 2048) |
if (coff_start != 2048) |
342 |
{ |
{ |
343 |
close (f); |
close (f); |
359 |
close (f); |
close (f); |
360 |
goto stub_end; |
goto stub_end; |
361 |
} |
} |
362 |
/* Now we found a correct stub (hopefully) */ |
/* Now we found a correct stub (hopefully). */ |
363 |
bfd_coff_go32stub (abfd) |
bfd_coff_go32stub (abfd) |
364 |
= (PTR) bfd_alloc (abfd, (bfd_size_type) coff_start); |
= (PTR) bfd_alloc (abfd, (bfd_size_type) coff_start); |
365 |
if (bfd_coff_go32stub (abfd) == NULL) |
if (bfd_coff_go32stub (abfd) == NULL) |
378 |
} |
} |
379 |
stub_end: |
stub_end: |
380 |
/* There was something wrong above, so use now the standard builtin |
/* There was something wrong above, so use now the standard builtin |
381 |
stub */ |
stub. */ |
382 |
if (bfd_coff_go32stub (abfd) == NULL) |
if (bfd_coff_go32stub (abfd) == NULL) |
383 |
{ |
{ |
384 |
bfd_coff_go32stub (abfd) |
bfd_coff_go32stub (abfd) |
385 |
= (PTR) bfd_alloc (abfd, (bfd_size_type) STUBSIZE); |
= (PTR) bfd_alloc (abfd, (bfd_size_type) STUBSIZE); |
386 |
if (bfd_coff_go32stub (abfd) == NULL) |
if (bfd_coff_go32stub (abfd) == NULL) |
387 |
{ |
return; |
|
return; |
|
|
} |
|
|
|
|
388 |
memcpy (bfd_coff_go32stub (abfd), stub_bytes, STUBSIZE); |
memcpy (bfd_coff_go32stub (abfd), stub_bytes, STUBSIZE); |
389 |
} |
} |
390 |
} |
} |
391 |
|
|
392 |
/* If ibfd was a stubbed coff image, copy the stub from that bfd |
/* If ibfd was a stubbed coff image, copy the stub from that bfd |
393 |
to the new obfd. |
to the new obfd. */ |
|
*/ |
|
394 |
|
|
395 |
static boolean |
static bfd_boolean |
396 |
go32_stubbed_coff_bfd_copy_private_bfd_data (ibfd, obfd) |
go32_stubbed_coff_bfd_copy_private_bfd_data (ibfd, obfd) |
397 |
bfd *ibfd; |
bfd *ibfd; |
398 |
bfd *obfd; |
bfd *obfd; |
399 |
{ |
{ |
400 |
/* check if both are the same targets */ |
/* Check if both are the same targets. */ |
401 |
if (ibfd->xvec != obfd->xvec) |
if (ibfd->xvec != obfd->xvec) |
402 |
return true; |
return TRUE; |
403 |
|
|
404 |
/* check if both have a valid stub */ |
/* Check if both have a valid stub. */ |
405 |
if (bfd_coff_go32stub (ibfd) == NULL |
if (bfd_coff_go32stub (ibfd) == NULL |
406 |
|| bfd_coff_go32stub (obfd) == NULL) |
|| bfd_coff_go32stub (obfd) == NULL) |
407 |
return true; |
return TRUE; |
408 |
|
|
409 |
/* Now copy the stub */ |
/* Now copy the stub. */ |
410 |
memcpy (bfd_coff_go32stub (obfd), bfd_coff_go32stub (ibfd), STUBSIZE); |
memcpy (bfd_coff_go32stub (obfd), bfd_coff_go32stub (ibfd), STUBSIZE); |
411 |
|
|
412 |
return true; |
return TRUE; |
413 |
} |
} |